Compare commits

...

83 Commits

Author SHA1 Message Date
dan 814aad618c Ensure that the value of the THREADSAFE symbol is always included when
reporting compile time options, even if it was not explicitly configured.

FossilOrigin-Name: 95141c642697dc037e57f9e4992ff3460155995d3caef6259235601ee722cb93
2017-06-17 17:29:24 +00:00
dan da1f49b83f Rework the code in ctime.c a bit to report on more compile time options. And
to only output configuration options passed in to SQLite, not the default
values of #define symbols set automatically. Also generate the large array in
ctime.c using new script tool/mkctime.tcl, instead of entering it manually.

FossilOrigin-Name: bc1951d699e6eeacbe15776a37cd0f5cf3f09eb85d3ae01cff43293cb286fcd7
2017-06-16 19:51:47 +00:00
drh ba87c6c2cd Minor refactoring change to clarify how ATTACH works. No functional changes.
FossilOrigin-Name: 3944a32e1dd90ff903bcbaaa7cb497cebcfcb2ba2a326726ec2268505e524ae3
2017-06-16 18:31:30 +00:00
drh 76cf858d3d Prevent pagesize changes on VACUUM in encrypted databases even when running
the VACUUM on an attached database.

FossilOrigin-Name: 11693849342a308ad929e2d9ead67faabacb523af76128c6973ed6cc8b62c11e
2017-06-16 13:43:37 +00:00
drh 0942559a14 Move the "shell_add_schema()" SQL function used by the ".schema" command
of the command-line shell to a different spot in the shell.c source file
so that it is not in the middle of an unrelated module.

FossilOrigin-Name: 254617a1ccfa1736d4e53d670d80319c79c4d93ebf1de69d89ebdba3949bc270
2017-06-15 16:56:05 +00:00
drh f217f3b68c Fix typo and improve the wording of the description of "Metadata" in the
output of the sqlite3_analyzer tool.

FossilOrigin-Name: ca1ff70780e07e5ee930fe7972db02e887d9b085d8ab78e878d7f966b6d684d4
2017-06-15 16:45:23 +00:00
drh 90cdec0672 Fix harmless compiler warnings in the shell.c file
FossilOrigin-Name: 9afd7a2ffd3a39456190ad05e85ff6485298aae262d9e0698a58c1d73507a36f
2017-06-15 13:07:56 +00:00
drh 594ccd09b1 Improvements to the ".tables" command in the command-line shell so that
it shows the name of all schemas if the name is anything other than "main".

FossilOrigin-Name: c7f778b7cee16a1dcebccd256408ee1d08ef2b62e388a9ebba5738a0a89bf3a0
2017-06-15 12:50:47 +00:00
drh 20c9c3f4eb In the command-line shell, enhance the ".schema" command show that it
shows the schema for ATTACH-ed databases in addition to "main".

FossilOrigin-Name: 48e086284a76da10a85315bc992e2294bd4711e35ec5a5abaa16e39a6a69d206
2017-06-15 12:21:09 +00:00
drh c74d962a1f Enhance the sqlite3_analyzer.exe utility so that it computes and shows the
number of bytes of metadata on btree pages and per table and index entry.

FossilOrigin-Name: 43ad41efa9e1fdd79a9804197a227491236495f14ed56c656224d6ce181703c1
2017-06-15 00:52:03 +00:00
dan 2ebf8f474e Fix sqlite3rbu_close() so that the pzErrmsg parameter may be passed NULL.
FossilOrigin-Name: c433672dd8ab625628bde2f4f40a2dc000ed915dbe91833d3f753d8ab51baf25
2017-06-13 16:52:34 +00:00
drh 6e3bccd5c9 Fix the processing of double-negatives in WHERE clause constraints with
STAT4.  Ticket [cfa2c908f2182]

FossilOrigin-Name: 35b34bdf0843b49be39e13ed212e918c2d45afdb8374b5cd02ba6d2d5b16b3b9
2017-06-13 04:31:54 +00:00
drh 56790ea567 Fix an off-by-one error that messes up the display of loop codes in the
".wheretrace" debugging output for queries with more than 62 candidate
loops when SQLITE_ENABLE_WHERETRACE is on.

FossilOrigin-Name: 0bbdaf2801e4102d952db65e53962e534b67b8b72e76fadb4ce404a6249129d9
2017-06-11 20:17:02 +00:00
drh eafc6dfe2b When reusing a materialized view, make sure the estimated number of
output rows is correctly initialized to avoid confusing the query planner.

FossilOrigin-Name: 87aceb417a813a2925b636cffa660fe25f3b7e3b3c84bb2108951bf0af644376
2017-06-11 19:51:36 +00:00
drh e46c63d565 Fix the sessiondiff test module so that it does not run if the session
extension is not enabled.

FossilOrigin-Name: 8f92b7a6223a69304dc8a6ab3b43a49cbb87f572a1e65d8a0c6dc09fca38e1a8
2017-06-11 19:40:34 +00:00
drh c62aab5ba8 Fix a potential null-pointer deference following OOM introduced by
check-in [e39795d7] (unreleased).

FossilOrigin-Name: a2f77285fa44df86863eed576271f1030ec60f15480daf175908c5082c27774b
2017-06-11 18:26:15 +00:00
drh c097b309aa Update the documentation to make it clear that the table name parameter
to sqlite3_table_column_metadata() may not be NULL.

FossilOrigin-Name: 2881ab1ed24ed72760086785bdf224c4e687cf39a02fd349ae13c6e1235e24da
2017-06-09 11:43:53 +00:00
drh c5d353fb33 Adjust the implementation of the ".selftest" feature of the shell to avoid
using the deprecated sqlite3_get_table() interface.

FossilOrigin-Name: 3168e2c92ad0a0dafc78a27ee1d87ac89f426585f506f418a0182141335dc68b
2017-06-09 02:27:49 +00:00
drh d96cc6fbcb Add a testcase() to confirm that an OOM on sqlite3DbStrNDup() is handled
correctly in trigger.c.

FossilOrigin-Name: 343e55992f503efa662e49bb0f3c0d798defd0a11f2ee1c36968902fa7e06823
2017-06-08 14:35:21 +00:00
dan ca66f6c6f4 Ensure pointer map entries are always added when a row that does use overflow
pages replaces one that does not in an auto-vacuum database. Fix for
[fda22108].

FossilOrigin-Name: b30dfba811cb531b09ff2e71a1a18ed53c816cb39155dd52ca3e2701425fe17b
2017-06-08 11:14:08 +00:00
drh cc97ca4c08 In SQLITE_DEBUG mode, attempt to log the page number of the database that
contained the problem when SQLITE_CORRUPT errors are seen.

FossilOrigin-Name: e39795d7d798d5249c7bd2a0f6ff891b455f4300a3d638c39a4668323b367666
2017-06-07 22:32:59 +00:00
drh d1417ee1cb Add the SQLITE_DEFAULT_ROWEST compile-time option for changing the estimated
number of rows in tables that lack sqlite_stat1 entries.

FossilOrigin-Name: 234ede26e30f20e6c33002739ed8be35dbfb5c77700bd857ff31072b9b7df347
2017-06-06 18:20:43 +00:00
drh cf1393df94 Fix a subtle bug in the remember UDF of the kvtest.exe utility program.
FossilOrigin-Name: 9eea3670e77e2f831b7c00ae2d65a5583f9cad626d9ab286f92582ef29ecd4e3
2017-06-05 19:20:35 +00:00
dan b1d66c5986 Fix a bug in test_fs.c that occurs when the first component of a path contains
a GLOB or LIKE escape character.

FossilOrigin-Name: 73c70590d7689806901378cd2a7e167ec4339f886031369266e07868acd23b93
2017-06-05 16:33:53 +00:00
drh a4327e65bb For the kvtest utility, add the --vacuum option to "kvtest stat" and also
run PRAGMA integrity_check with "kvtest stat".

FossilOrigin-Name: f3c25df4562efda2adeb211a4cc893246354917849a0fa4d95da3d7970e9588e
2017-06-05 13:28:17 +00:00
drh 64bf76d2b2 Fix the column width deduction logic in the command-line shell to account
for multi-byte utf8 characters.

FossilOrigin-Name: ed0842c156ab1a78d5d00d3a55dab5e3f08cd349328d606724688f1528df3f6b
2017-06-05 12:29:26 +00:00
drh 3b77506ba5 Omit some of the fstree tests in vtabH if the PWD contains LIKE wildcards.
FossilOrigin-Name: ead29f9cb757a5f9921086e3bb4998f60e0d6cfcf41ef0f9a230b365b6226947
2017-06-05 10:31:03 +00:00
drh 4c88348729 Initialize a variable to zero to prevent an (incorrect) compiler warning of
it potentially being uninitialized.

FossilOrigin-Name: 65182ce041b30cd0193b958eca975b720fe5200a868baba1e633e49433d86813
2017-06-03 20:09:37 +00:00
drh 5930f663a1 Fix the SQLITE_PTR_TO_INT macro so that works on recent versions of LLVM on
Macs.

FossilOrigin-Name: c4089ffbdb4b3467648c97044b0d3085da7128103079b686f608efde83c7df30
2017-06-03 19:16:29 +00:00
drh 629a75f69a Remove unused header file from kvtest.
FossilOrigin-Name: dd7e043f7c9e16cd98a273b7105fa74bdd14a93db8cd5bde064cc1c40591155c
2017-06-03 18:27:49 +00:00
drh 1346fdad65 In kvtest, add the ability to work with a hierarchy of files on disk,
in addition to having all files in the same directory.

FossilOrigin-Name: f568f666c85ab9b80592927dc033cfd65bd4415576cf5b3beaf300d68a8e074e
2017-06-03 17:24:04 +00:00
drh 16d62901a3 Add the --nocheckpoint and --multitrans options to kvtest.
FossilOrigin-Name: 5828633c2392274b6863b50eaffbb2a176a4d892e83542824a9a3f0d1b62c967
2017-06-03 15:17:21 +00:00
drh f151890791 Add the --fsync flag to kvtest, and document the --nosync flag.
FossilOrigin-Name: 7fdc78a672b2ea6187dcb5fdf32f809bb8e4d501e2434f2233edc3bc2e3acc7c
2017-06-02 23:32:17 +00:00
drh a2e71ced79 Work toward enhancing kvtest to measure write performance.
FossilOrigin-Name: fc73e7d2f16386f96c55c42f9830193f7c178521a7ad90c3117b85ef629b5ce4
2017-06-02 19:31:46 +00:00
drh 170ad68a40 Change the name of the OP_Seek opcode into OP_DeferredSeek for better
clarity of function.  No functional code changes.

FossilOrigin-Name: ab33d299c7dab52703d06f3441c8a98c6c809b2612ec65d71aab2919bd2b1540
2017-06-02 15:44:22 +00:00
drh 6c2d94f928 Fix a typo in the header comment of the "series.c" virtual table extension.
FossilOrigin-Name: d637feb4e3032ee0067c204b56d2af5f7eab228e645f2e77b0b043c2b299724d
2017-06-02 13:16:54 +00:00
drh c5e56b3473 Add a comment to the Lemon documentation regarding the security of the
lemon.exe command-line tool.

FossilOrigin-Name: 4c2458c1908181dc2f6bc594395c06d015fcbd78f5d3472f07a6a3909be9673c
2017-06-01 01:53:19 +00:00
drh cdbb126be7 Add the SQLITE_STMTSTATUS_MEMUSED opcode to sqlite3_stmt_status()
for finding the heap memory usage by a single prepared statement.

FossilOrigin-Name: c26cf978eead1c9d265eddabaa421e7735b472fcf2792cd2bdeb0901bcf3fb44
2017-05-31 17:30:08 +00:00
drh 3528f6b62b Add the SQLITE_STMTSTATUS_MEMUSED option for sqlite3_stmt_status() that reports
the amount of heap memory used for a single prepared statement.

FossilOrigin-Name: b57d510465458dec5b5fc778fd6e8833392964201f9febebf526e60a543da0c2
2017-05-31 16:21:54 +00:00
drh 6b37e0adc9 Add the experimental "stmts" virtual table for introspection of prepared
statements.

FossilOrigin-Name: cb4c5c66aba757356da3b8ec3c66a5c8c40e180b3360638ac634f7787404a5b1
2017-05-31 16:09:04 +00:00
drh d4ab003d4e Avoid allocating excess memory to the KeyInfo objects.
FossilOrigin-Name: df7859435161f3ecf36635ce574bf73573516a1f2c6e75be320619364e7067d1
2017-05-31 13:45:59 +00:00
drh d5bdd5effb Remove a completely unnecessary memset() from the INSERT code generator.
FossilOrigin-Name: 7d58836b9db1293a3a6581af4358b7c91a588efd5c9b2df384803f3855ff87a8
2017-05-31 13:27:15 +00:00
drh b8a1290a28 Very small performance increase in sqlite3VdbeSetNumCols().
FossilOrigin-Name: 8885b4461044ae8ecdfe1b9aa47f4aad65efabc98e3fcd9e307a06504fab34c6
2017-05-31 11:24:13 +00:00
drh 02f18cc5ac Reorder fields in the PgHdr object for a performance increase.
FossilOrigin-Name: 326e63d71e0e164c5bcd1f74772cb4071b82daf6f04a5d440b985bace5a4c941
2017-05-31 03:20:39 +00:00
drh a8b9793c86 Avoid unnecessary memory zeroing during expression list allocation.
FossilOrigin-Name: de28e6514a42438411e2c9d833ba660108128ca86d0b90f32925fb73195f4862
2017-05-31 02:58:30 +00:00
drh d03257c141 Size and performance optimizations to sqlite3ResolveExprNames().
FossilOrigin-Name: af8c0fed93c830c50641d95691bb507c31947a15529aba2a88bfaa66b3a3287a
2017-05-31 00:49:40 +00:00
drh 2ab792e4c0 Change sqlite3BtreeNext() and sqlite3BtreePrevious() so that they return
SQLITE_DONE if they have already reached the end (or beginning) of the table.
This gives a performance increase and size reduction.

FossilOrigin-Name: e972a3860892022d57b26ec44ce0fbadc61c1ff54b7a10b7e82390db88d323a7
2017-05-30 18:34:07 +00:00
dan d26d2c7de2 Omit a test of codepoint 0x202F (non-break narrow space) from the fts3 ICU
tests. Different versions of ICU apparently handle this obscure codepoint
slightly differently.

FossilOrigin-Name: 69ae688982d6cb9f859f5643c315a1dc5ba76ad35553ecea8329a75ee70a87b1
2017-05-30 18:14:47 +00:00
drh e70d01f143 More efficient error handling and reset in the binding mechanism.
FossilOrigin-Name: 9a3e3b34ba6eafce2f560c13225a3673e18d696b29295b59d958e938fa593baf
2017-05-29 22:44:18 +00:00
drh 1e669f02bc Omit unnecessary fstat() calls for determining the database file size,
resulting in smaller and faster code.

FossilOrigin-Name: dd61c736775c53450821327495276485dced7935d0b4b5ebd17662731afc8adb
2017-05-29 17:59:29 +00:00
drh 8c9ed054b3 Fix an issue with OPT_FEATURE_FLAGS in configure.ac.
FossilOrigin-Name: 43ce3bd3a4b41ea757e308e563d6c1bf7f9c09f10e4766c536d0bf1042c45613
2017-05-29 17:43:06 +00:00
drh 77f6af2b96 Avoid unnecessary fstat() calls to determine the database size when
transitioning into a read transaction on a rollback-mode database.

FossilOrigin-Name: 6c3476b513965df22d648f9a1b99733af753b44d51163cc7d42a69bf562300e1
2017-05-29 16:45:45 +00:00
drh 5f5a2d1c3c Avoid unnecessary calls to fstat() to determine the database file size.
FossilOrigin-Name: c733a1dea37e4678e7bd0d3d0ca9b8eae1fbdc28615f75d8f1e5141aa53567d9
2017-05-29 14:57:23 +00:00
drh 8abc54e2e8 Fix a typo in a comment. No code changes.
FossilOrigin-Name: cb29b838886769afe866b1172e3d5d7e36387149b79c51f91cf59da3f4a5f25b
2017-05-29 14:30:46 +00:00
drh 979dd1be57 Optimizations to the Walker object and its methods to make the code a little
smaller and to help it run a little faster.

FossilOrigin-Name: 6854a34ed708259f2280f7ee56cec09f7fc99810dc739dc2814ddeae286aa2c4
2017-05-29 14:26:07 +00:00
drh d8a295669c Correctly initialize the iSelectId of FROM clause terms that are a self
join of a reused materialized subquery.  Without this, the EXPLAIN QUERY PLAN
output for the query will identify the subquery using the uninitialized
(and arbitrary) iSelectId.

FossilOrigin-Name: 43c9ae371f6250fee98a7c4011726eff8ad37f5a97add4f490ac3a2dd501a0d2
2017-05-29 13:09:24 +00:00
mistachkin e16a350f17 Improve shell help text for the '.open' command.
FossilOrigin-Name: 7cc940a97efc096ff3725710f526c06f52453bd923fb9e825ce6990275df747a
2017-05-29 03:48:13 +00:00
drh ae2ac854b3 Smaller and faster vdbeSorterCompareText().
FossilOrigin-Name: 542dc4c5eb87017fe03b6c181e779993aa84564785e1177ccf937d52f985593b
2017-05-27 22:42:36 +00:00
drh 14e845a9d4 Small performance increase and size decrease in the btreeInitPage() routine.
FossilOrigin-Name: 6f415833e0554706dcf04f68ecba4ca2e54c08f3bbf6a1dba182bb132c912a2e
2017-05-25 21:35:56 +00:00
drh 137c46f8b6 Merge the LEFT JOIN query flattener fixes from 3.19.2.
FossilOrigin-Name: 6513e4a121e32df7e5cd95f47cdf8049b85bdbcb378cf23db29838fb1143d3ce
2017-05-25 17:27:52 +00:00
drh 65ff63ea62 Version 3.19.2
FossilOrigin-Name: edb4e819b0c058c7d74d27ebd14cc5ceb2bad6a6144a486a970182b7afe3f8b9
2017-05-25 16:50:27 +00:00
drh dc6de47925 The SQLITE_EXTRA_IFNULLROW compile-time option causes OP_IfNullRow opcodes
to be issued for references to the right-hand side table of *any* flattened
join, not just LEFT JOINs.  This puts extra stress on the OP_IfNUllRow opcodes
for testing purposes.

FossilOrigin-Name: 1a074c8a2bc0b28918ef905339d11a21d30101b4ea8c06c8b3faca7d17237538
2017-05-25 11:39:50 +00:00
drh 074ce1e7fd The TK_IF_NULL_ROW expression node must be treated as a variable that
references the table Expr.iTable.
Proposed fix for ticket [7fde638e94287d2c].

FossilOrigin-Name: b30a364a12d9865242b1444984cd25ee126dc69108d5c6a2d4b35df184437fe9
2017-05-25 00:28:36 +00:00
drh 8389bff0a8 Increase the version number to 3.19.2 since ticket [7fde638e94287d2] is
going to necessitate another patch release.

FossilOrigin-Name: c315727acd5fffe6e83ad9a5e84360d5cfa9aa8faa10d4970ea9823c7e8126ee
2017-05-25 00:12:04 +00:00
drh f43ce0b445 The TK_IF_NULL_ROW expression node must be treated as a variable that
references the table Expr.iTable.
Proposed fix for ticket [7fde638e94287d2c].

FossilOrigin-Name: 77fc23013cebc7797985864b91d78db5d0e2469511732044ebfaf02b891c979a
2017-05-25 00:08:48 +00:00
mistachkin 831265f962 Fix harmless compiler warnings in FTS5.
FossilOrigin-Name: 57a60e959c198b87ed29fab14356f89e0ea7cdb1dd99adbea45b40e8d0cb310a
2017-05-24 15:32:44 +00:00
drh 63ad86e70e Fix a problem in STAT4 equality estimation for multi-column indexes
introduced by check-in [3e0590dee0e68cc1599].

FossilOrigin-Name: cfb0d9e0207128b1c2b48689288a849b19dbc00a22cfaca26eec4bfc773629f8
2017-05-24 04:18:00 +00:00
drh ce13b99f99 Remove the msvc.h header file from the autoconf tarball.
FossilOrigin-Name: 84996aef68adeabc8bd97cad269188c67de628f776337a25ec2d63bc956cee78
2017-05-23 20:00:00 +00:00
drh 92b71757f7 Do not use strcpy() in the (obsolete) amatch extension.
In releasetest.tcl, run Apple tests using -Os instead of -O1

FossilOrigin-Name: 4440e42031b9cb0edf9a8621cd4f46f209392940ec5b9eefcf8c1e3fef5f7b76
2017-05-23 19:35:20 +00:00
drh 1d1fc5e385 Disable the LEFT JOIN flattening optimization for aggregate queries, as it
does not currently work.  Further fix for ticket [cad1ab4cb7b0fc344].

FossilOrigin-Name: 44b21e35c92137cc519d0cc87c627cc531d0bd442a7b9a7356fa2c6bc5f70fb6
2017-05-23 15:21:37 +00:00
drh eff0a7b25e Ensure that the expression rewriter inside the query flattener decends into
the substructure of the TK_IF_NULL_ROW operator.  This is a continuation
of the fix for ticket [cad1ab4cb7b0fc344].

FossilOrigin-Name: 941d8142b7c9a96ff143d1add3c86cf42d61fd08e532d400dac555f23eadbcfb
2017-05-23 12:36:13 +00:00
drh 3f1e9e00e6 When flattening a query, make sure iTable attribute of TK_IF_NULL_ROW
operators (that result from a prior flattening of a LEFT JOIN) are updated
correctly.  Fix for ticket [cad1ab4cb7b0fc344].

FossilOrigin-Name: 92c178507df553e4f1110342c8f9b11b3ee37989e1d634fcaccabf657befa22f
2017-05-23 01:21:07 +00:00
drh d4fb196531 Remove a surplus semicolon, which was harmless on gcc and clang but caused
compile-time errors on msvc.  This only comes up using the encryption extension.

FossilOrigin-Name: 987a2b5537254b1fe843eb798d7eb7f04dbe1e32fb827cfb9e1e1ef6c2096759
2017-05-23 00:32:56 +00:00
dan 07d0f15e93 Fix incompatibilities between the "sqldiff --changeset" command and the
sessions module. Specifically, allow sessions to process changesets containing
tables with zero operations on them and have sqldiff output the expected
output for tables with multi-column primary keys.

FossilOrigin-Name: 0bb23c48064cc64134697469f3f4d2d3610b9e6c7a0dc54a3c47a00bd6c2a860
2017-05-22 18:09:00 +00:00
drh 453ca043a2 Add the ".cd" command to the command-line shell.
FossilOrigin-Name: 5fe28e15b1d6d8a588fcaf93c6035c0e0ab7bcad1067c7933cd430d2e04bbbd8
2017-05-22 18:00:34 +00:00
drh ee841262d9 Increase the version number to 3.20 for the next release cycle.
FossilOrigin-Name: ab471f61ef7d9ed1bf937d5e458f720d12209712a015786434edc818a98168c9
2017-05-22 17:39:37 +00:00
drh d758722449 Merge the last-minute 3.19.0 changes into trunk.
FossilOrigin-Name: e6ba2a93a8d28074ff134dd43c142315de291b7c0a38ecc692863c33975c71c7
2017-05-22 14:04:46 +00:00
dan 21766c0c16 Fix a case where NULL was being passed to memcmp() following an OOM. This is
probably not a real problem, as the number-of-bytes parameter was passed 0 in
this case, but it was causing a santizer complaint.

FossilOrigin-Name: 3ea2bad27e516d5dbfa4a9cb0c767d6a8387280a7e4bbf2ae80cd318da670d66
2017-05-22 08:04:09 +00:00
drh 78436d4c66 When planning a query using sorting, resolve ties in the solver by selecting
loop plans with the smaller unsorted cost.

FossilOrigin-Name: f261678c90297f9767040c577796cc1d4db598aa44b0de6906cb73eaef377dee
2017-05-22 00:45:15 +00:00
drh e46515b53f Prevent a possible NULL pointer dereference in the OP_Found opcode that
can follow an OOM error.  Problem found by OSS-Fuzz.

FossilOrigin-Name: c2de178fe7e2e4e0d764e7e6ac637cfc8c053580c43f7246318dafad2974de3c
2017-05-19 22:51:00 +00:00
drh bcbb066534 Improved comments on one routine in the query planner. Improved diagnostic
output for ".wheretrace".  No production code changes.

FossilOrigin-Name: 946b87a5282f00d8c532a51f4390e6de781b9a0d6626cb3c077c5622895dc540
2017-05-19 20:55:04 +00:00
drh 748465b49e Fix a documentation typo. No changes to code.
FossilOrigin-Name: 68942a4feeb83e6e1a32d9bd724ae1d72669949adcfad07fb05b0ac48daf5151
2017-05-19 20:47:54 +00:00
drh 1e1c4226ee Fix a documentation typo. No changes to code.
FossilOrigin-Name: cfa4aa203646f44b303138c25672293bb87d97126fe2030d4709e8ad7814a807
2017-05-18 18:17:55 +00:00
63 changed files with 2499 additions and 836 deletions
+1 -1
View File
@@ -1 +1 @@
3.19.1
3.20.0
+1 -1
View File
@@ -12,7 +12,7 @@ sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
include_HEADERS = sqlite3.h sqlite3ext.h msvc.h
include_HEADERS = sqlite3.h sqlite3ext.h
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
pkgconfigdir = ${libdir}/pkgconfig
Vendored
+19 -19
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.19.1.
# Generated by GNU Autoconf 2.69 for sqlite 3.20.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.19.1'
PACKAGE_STRING='sqlite 3.19.1'
PACKAGE_VERSION='3.20.0'
PACKAGE_STRING='sqlite 3.20.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1463,7 +1463,7 @@ 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.19.1 to adapt to many kinds of systems.
\`configure' configures sqlite 3.20.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.19.1:";;
short | recursive ) echo "Configuration of sqlite 3.20.0:";;
esac
cat <<\_ACEOF
@@ -1652,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.19.1
sqlite configure 3.20.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2071,7 @@ 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.19.1, which was
It was created by sqlite $as_me 3.20.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -11356,7 +11356,7 @@ 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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11373,7 +11373,7 @@ 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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11391,7 +11391,7 @@ else
fi
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
fi
# Check whether --enable-fts4 was given.
if test "${enable_fts4+set}" = set; then :
@@ -11401,7 +11401,7 @@ else
fi
if test "${enable_fts4}" = "yes" ; then
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4"
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 :
@@ -11467,7 +11467,7 @@ else
fi
if test "${enable_fts5}" = "yes" ; then
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5"
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 :
@@ -11536,7 +11536,7 @@ else
fi
if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -11549,7 +11549,7 @@ else
fi
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -11562,12 +11562,12 @@ else
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"
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
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
for option in $CFLAGS $CPPFLAGS
do
case $option in
@@ -12151,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# 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.19.1, which was
This file was extended by sqlite $as_me 3.20.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12217,7 @@ _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.19.1
sqlite config.status 3.20.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+10 -10
View File
@@ -596,7 +596,7 @@ AC_ARG_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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -606,7 +606,7 @@ AC_ARG_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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -618,20 +618,20 @@ 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"
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"
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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
AC_SEARCH_LIBS([log],[m])
fi
@@ -641,7 +641,7 @@ 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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -650,7 +650,7 @@ 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"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -659,12 +659,12 @@ 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"
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
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
for option in $CFLAGS $CPPFLAGS
do
case $option in
+20
View File
@@ -23,6 +23,26 @@ 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)
+4 -3
View File
@@ -171,10 +171,11 @@ static int fts5HashResize(Fts5Hash *pHash){
for(i=0; i<pHash->nSlot; i++){
while( apOld[i] ){
int iHash;
unsigned int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p)));
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
(int)strlen(fts5EntryKey(p)));
p->pHashNext = apNew[iHash];
apNew[iHash] = p;
}
@@ -477,7 +478,7 @@ int sqlite3Fts5HashQuery(
int *pnDoclist /* OUT: Size of doclist in bytes */
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
char *zKey;
char *zKey = 0;
Fts5HashEntry *p;
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
+1 -1
View File
@@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
Fts5tokTable *pTab = 0;
int rc;
char **azDequote = 0;
int nDequote;
int nDequote = 0;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
+1
View File
@@ -90,6 +90,7 @@ do_test 2.7 {
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
} {1 3 2}
db2 close
#--------------------------------------------------------------------------
# At one point there was a problem with queries such as:
-6
View File
@@ -1001,7 +1001,6 @@ static void amatchWriteCost(amatch_word *pWord){
/* Circumvent compiler warnings about the use of strcpy() by supplying
** our own implementation.
*/
#if defined(__OpenBSD__)
static void amatchStrcpy(char *dest, const char *src){
while( (*(dest++) = *(src++))!=0 ){}
}
@@ -1009,11 +1008,6 @@ static void amatchStrcat(char *dest, const char *src){
while( *dest ) dest++;
amatchStrcpy(dest, src);
}
#else
# define amatchStrcpy strcpy
# define amatchStrcat strcat
#endif
/*
** Add a new amatch_word object to the queue.
+1 -1
View File
@@ -33,7 +33,7 @@
** The generate_series "function" is really a virtual table with the
** following schema:
**
** CREATE FUNCTION generate_series(
** CREATE TABLE generate_series(
** value,
** start HIDDEN,
** stop HIDDEN,
+299
View File
@@ -0,0 +1,299 @@
/*
** 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 ./stmts
** .mode line
** .header on
** SELECT * FROM stmts;
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** The following macros are used to cast pointers to integers.
** 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.
*/
#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(intptr_t)(X))
#else /* Generates a warning - but it always works */
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(X))
#endif
/* stmts_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmts virtual table
*/
typedef struct stmts_vtab stmts_vtab;
struct stmts_vtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this stmts vtab */
};
/* stmts_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 stmts_cursor stmts_cursor;
struct stmts_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 stmtsConnect() method is invoked to create a new
** stmts_vtab that describes the generate_stmts virtual table.
**
** Think of this routine as the constructor for stmts_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the stmts_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against generate_stmts will look like.
*/
static int stmtsConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
stmts_vtab *pNew;
int rc;
/* Column numbers */
#define STMTS_COLUMN_PTR 0 /* Numeric value of the statement pointer */
#define STMTS_COLUMN_SQL 1 /* SQL for the statement */
#define STMTS_COLUMN_NCOL 2 /* Number of result columns */
#define STMTS_COLUMN_RO 3 /* True if read-only */
#define STMTS_COLUMN_BUSY 4 /* True if currently busy */
#define STMTS_COLUMN_NSCAN 5 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMTS_COLUMN_NSORT 6 /* SQLITE_STMTSTATUS_SORT */
#define STMTS_COLUMN_NAIDX 7 /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMTS_COLUMN_NSTEP 8 /* SQLITE_STMTSTATUS_VM_STEP */
#define STMTS_COLUMN_MEM 9 /* SQLITE_STMTSTATUS_MEMUSED */
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(ptr,sql,ncol,ro,busy,nscan,nsort,naidx,nstep,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 stmts_cursor objects.
*/
static int stmtsDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new stmts_cursor object.
*/
static int stmtsOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
stmts_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((stmts_vtab*)p)->db;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Destructor for a stmts_cursor.
*/
static int stmtsClose(sqlite3_vtab_cursor *cur){
sqlite3_free(cur);
return SQLITE_OK;
}
/*
** Advance a stmts_cursor to its next row of output.
*/
static int stmtsNext(sqlite3_vtab_cursor *cur){
stmts_cursor *pCur = (stmts_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 stmts_cursor
** is currently pointing.
*/
static int stmtsColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
stmts_cursor *pCur = (stmts_cursor*)cur;
switch( i ){
case STMTS_COLUMN_PTR: {
sqlite3_result_int64(ctx, SQLITE_PTR_TO_INT64(pCur->pStmt));
break;
}
case STMTS_COLUMN_SQL: {
sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
break;
}
case STMTS_COLUMN_NCOL: {
sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
break;
}
case STMTS_COLUMN_RO: {
sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
break;
}
case STMTS_COLUMN_BUSY: {
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
break;
}
case STMTS_COLUMN_NSCAN:
case STMTS_COLUMN_NSORT:
case STMTS_COLUMN_NAIDX:
case STMTS_COLUMN_NSTEP:
case STMTS_COLUMN_MEM: {
sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
i-STMTS_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 stmtsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
stmts_cursor *pCur = (stmts_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 stmtsEof(sqlite3_vtab_cursor *cur){
stmts_cursor *pCur = (stmts_cursor*)cur;
return pCur->pStmt==0;
}
/*
** This method is called to "rewind" the stmts_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to stmtsColumn() or stmtsRowid() or
** stmtsEof().
*/
static int stmtsFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
stmts_cursor *pCur = (stmts_cursor *)pVtabCursor;
pCur->pStmt = 0;
pCur->iRowid = 0;
return stmtsNext(pVtabCursor);
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the generate_stmts virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int stmtsBestIndex(
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
** generate_stmts virtual table.
*/
static sqlite3_module stmtsModule = {
0, /* iVersion */
0, /* xCreate */
stmtsConnect, /* xConnect */
stmtsBestIndex, /* xBestIndex */
stmtsDisconnect, /* xDisconnect */
0, /* xDestroy */
stmtsOpen, /* xOpen - open a cursor */
stmtsClose, /* xClose - close a cursor */
stmtsFilter, /* xFilter - configure scan constraints */
stmtsNext, /* xNext - advance a cursor */
stmtsEof, /* xEof - check for end of scan */
stmtsColumn, /* xColumn - read data */
stmtsRowid, /* 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_stmts_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_stmts() requires SQLite 3.8.12 or later");
return SQLITE_ERROR;
}
rc = sqlite3_create_module(db, "stmts", &stmtsModule, 0);
#endif
return rc;
}
+8
View File
@@ -298,6 +298,14 @@ 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);
+5 -1
View File
@@ -3787,7 +3787,11 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
rbuEditErrmsg(p);
rc = p->rc;
*pzErrmsg = p->zErrmsg;
if( pzErrmsg ){
*pzErrmsg = p->zErrmsg;
}else{
sqlite3_free(p->zErrmsg);
}
sqlite3_free(p->zState);
sqlite3_free(p);
}else{
+4 -4
View File
@@ -420,10 +420,10 @@ int sqlite3rbu_savestate(sqlite3rbu *pRbu);
**
** 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, *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().
** 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
+7 -1
View File
@@ -78,6 +78,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
{"db", 3, "RBU"}, /* 6 */
{"state", 2, ""}, /* 7 */
{"progress", 2, ""}, /* 8 */
{"close_no_error", 2, ""}, /* 9 */
{0,0,0}
};
int iCmd;
@@ -102,11 +103,16 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
break;
}
case 9: /* close_no_error */
case 1: /* close */ {
char *zErrmsg = 0;
int rc;
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
rc = sqlite3rbu_close(pRbu, &zErrmsg);
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 );
+114
View File
@@ -0,0 +1,114 @@
# 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
+2 -1
View File
@@ -2836,11 +2836,12 @@ static int sessionChangesetNext(
p->in.iCurrent = p->in.iNext;
op = p->in.aData[p->in.iNext++];
if( op=='T' || op=='P' ){
while( op=='T' || op=='P' ){
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++];
}
+67 -67
View File
@@ -1,16 +1,16 @@
C Version\s3.19.1
D 2017-05-24T13:08:33.856
C Ensure\sthat\sthe\svalue\sof\sthe\sTHREADSAFE\ssymbol\sis\salways\sincluded\swhen\nreporting\scompile\stime\soptions,\seven\sif\sit\swas\snot\sexplicitly\sconfigured.
D 2017-06-17T17:29:24.923
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc
F README.md 2b15fae33852f2f53996774c21fb41e1d94181c4401a0e43ac93e11f2cc901b9
F VERSION 1699c6ade55970f0e2ab64ef0aa90ff406db479796172c8676e0899704f5dbe8
F VERSION 87f1498f27e398bce3da2fa8125c9879a38ed9d87e4b5fb922b351de1e25cadb
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 ed95854f5df64c1d0a447d8ecb55edc67e3c32f79f597c3a4870f9ac51698275
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
F autoconf/Makefile.msc 1014be616b420a5f48611d21b62ca2f50ec97ee795087ecb8a4d6bf6375ba11d
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
@@ -30,10 +30,10 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure a02beb39087ff63175fa1da1172c90db8c27b9cecf24639cd7438c1f3596163f x
F configure.ac 901e8db2c211e8b655e51ee24f2b8faa33407acde87effc47f70380f3b04e452
F configure 1bcc61cdd063171d8945551c265e5701a770deeff77e0ad634f8d22e4e91c831 x
F configure.ac 13f45f02e6c51dd0e347315b5401c3f047712b7f79b7f35619115c23755afcff
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
F doc/lemon.html 1f8b8d4c9f5cfe40e679fee279cc9eb2da8e6eb74ad406028538d7864cc4b6cb
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
@@ -104,13 +104,13 @@ F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c f2825f714d91bbe62ab5820aee9ad12e0c94205b2a01725eaa9072415ae9ff1c
F ext/fts5/fts5_hash.c 534d5591f479c0999543689122ad6952823bc7c85273a0ff4f7f91d9f914a54b
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
F ext/fts5/fts5_index.c cdceac47287c66500214ee946ca871ac48027a82a0ca82177c1c6af19f181ca0
F ext/fts5/fts5_main.c 1ba0e7806886c1bc16e20d0dde1c2b535d1aeb98cbbb937c4c3e064af5ac6f03
F ext/fts5/fts5_storage.c 7750986004f3f0c94619a85ecb5dd6cbef53e5e3853488e8a906c269d4d11db6
F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
F ext/fts5/fts5_test_tok.c f4c27f2e3200653a458f5316f6aaa863f7532d98fff7534ece3670fb7f2c196b
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
@@ -181,7 +181,7 @@ F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
F ext/fts5/test/fts5prefix.test 6ef7e875738412907b17687d25db39a25cbdaba4
F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40
F ext/fts5/test/fts5rank.test 2bdc0c5f22ccc1f9dbe9f4d0b82a491dce6f8a32
F ext/fts5/test/fts5rank.test 485e1d7ab8b0f939172a88e279acd0894b1f64458f92d7cd5826a31335c6a093
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6
@@ -209,7 +209,7 @@ F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
@@ -228,11 +228,12 @@ F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/remember.c 8440f8d0b452c5cdefb62b57135ccd1267aa729d
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/series.c b0f5f346aca9b7ff7caaf0da2efb4ad462441abd4dcd92a460cb573b3ea2370b
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/stmts.c 4aa554f671f6a55a52060437a0215a93d2e9f10f2fa66b0f7f65aa0576fc90bb
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
@@ -267,11 +268,11 @@ F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
F ext/rbu/sqlite3rbu.c 2a89efba9eeba8e6c89a498dc195e8efbdde2694
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
F ext/rbu/sqlite3rbu.c d1438580a451eebda3bfd42ef69b677512f00125285e0e4e789b6131a45f6dd8
F ext/rbu/sqlite3rbu.h fc25e1fcd99b5c6d32b1b5b1c73122632e873ac89bd0be9bf646db362b7ce02c
F ext/rbu/test_rbu.c ec18cfc69a104309df23c359e3c80306c9a6bdd1d2c53c8b70ae158e9832dcd6
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 8205d6e4466f766e57ce1b8aa38224ac9e1cec2d2bf4684cd1cc5a6ddf9b7014
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@@ -315,10 +316,11 @@ F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
F ext/session/session_common.tcl 7776eda579773113b30c7abfd4545c445228cb73
F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
F ext/session/sessionat.test b25d61d663ebc795506bf74079dc4ba0092fad25
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920
F ext/session/sqlite3session.c cc127222a9ea6f4eaa31281aa9da924f5244f6099be0ee526c950684fb3513a6
F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
@@ -341,22 +343,22 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/attach.c 3bd555e28382603e80d430dfebb2270f86e1e375b4c4be3e1ab1aec3a0c44943
F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c 8c1fd4cfa2b0bf021386e0a1f4e30b64eea7a2c1bc2e0c3e5901a626b1ab6aa9
F src/btree.h 80f518c0788be6cec8d9f8e13bd8e380df299d2b5e4ac340dc887b0642647cfc
F src/btree.c 430e34151e6ef37e42d3f956bb062907c80ff91e1380704b967b8c1a02a98f64
F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca
F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
F src/build.c 4026a9c554b233e50c5e9ad46963e676cf54dd2306d952aa1eaa07a1bc9ce14f
F src/build.c 88a8cdc11d1c081ed565aa3e795bdf9160f4556463b4c4555e9860b59dd80340
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
F src/ctime.c ce45bd3078346f08f04d87ad4cb04af573490c46ca5c55a23a45166589542a6f
F src/date.c cc42a41c7422389860d40419a5e3bce5eaf6e7835c3ba2677751dc653550a5c7
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c 665e705641e5815c3f32d05820d1a5aa630274e568af73f377fdbc614fcf40b4
F src/expr.c c83f799f3e5e3f3863bd0716119383e4a062d00a1e34e7273a78555918840a7c
F src/delete.c 3213547e97b676c6fa79948b7a9ede4801ea04a01a2043241deafedf132ecf5d
F src/expr.c 452c6f3aa656aabf3eefe96bb5f316b2c987fbc12c647964e4ed880f193ca31f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
@@ -365,10 +367,10 @@ F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c d4bb3a135948553d18cf992f76f7ed7b18aa0327f250607b5a6671e55d9947d5
F src/insert.c 974499a3999d339a4c1ba8ef129a988d9f136b3789e423808b38cdc19d28adbe
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9
F src/main.c a56577fa6407fb49650c1fd27bf828cd9b55126716b1f766a03c9c2cb42b43a0
F src/main.c 18f2145d572069dae91161add89446aec680aab296492a92ae5afcc2fc7c6b5a
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -390,32 +392,32 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 80893c0860199aebc6efa4f102ab11eebde338b7fdbb0c04d4b04647c2fd62d1
F src/pager.c 14f6982c470c05b8e85575c69e9c1712010602e20400f8670d8699e21283e0e4
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y 0513387ce02fea97897d8caef82d45f347818593f24f1bdc48e0c530a8af122d
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
F src/pragma.c 2362670a9d28b71708aecb2b9b10b3f7be71f4c950961c07e81dc400e3ce6371
F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
F src/resolve.c adf3ef9843135b1383321ad751f16f5a40c3f37925154555a3e61653d2a954e8
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 9db6887514a663ef4eb117f12cbae613bece9267f180d0fcdfa49402b013483e
F src/shell.c a37d96b20b3644d0eb905df5aa7a0fcf9f6e73c15898337230c760a24a8df794
F src/sqlite.h.in 8dd468837a4f6d76713e3a4cc65bea48095009038593d41040ab46c1b351197f
F src/select.c 0d2afdbdba5fbc61432c5454a35e0236e7aa4aa3756986a7d51b81a508e8083a
F src/shell.c bcd3358ad6cb3f3dc7ec76ad3bd8191f123ed2425360c5c48fe431780eceb729
F src/sqlite.h.in 67fa8bd29808e7988e0ce36c8d4c6043eb1727f94522fc612687aa5af51931e6
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
F src/sqliteInt.h aea3aa1b81e0d07d5b1c39b8c5a54a1dc5e4f10136cb63da392aef9eb2a5108b
F src/sqliteInt.h 17e9bce594ea0c38c44ad0cbff4aa50cbff4b25f4bac9d38306caf9f1f028ac9
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c c8cf60d0c5411d5e70e7c136470d29dbe760d250f55198b71682c67086524e4a
F src/test1.c c99f0442918a7a5d5b68a95d6024c211989e6c782c15ced5a558994baaf76a5e
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620
@@ -432,7 +434,7 @@ F src/test_config.c edcba290248dc18736dd814c9b95863c6762e0b35753048d8cbe5bf65f7a
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
F src/test_fs.c e16cbe68d3b107e00a907c20a9a02629870eb69b
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
@@ -465,29 +467,29 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
F src/treeview.c 6cf8d7fe9e63fae57dad1bb57f6615e14eac0c527e43d868e805042cae8ed1f7
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/trigger.c d1cae560bfacc8bfb3a072d73658245c1714c0389097da69b4cb23877a082d7e
F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
F src/vdbe.c 70f1c27d3de7b3ea68d3ee2b7fbf407335b66f7483eb321201ffe53724f9c54e
F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848
F src/vdbeInt.h 1ecdacc1322fdd3241ec30c32a480e328a6f864e532dc53fae8e0ab68121aebf
F src/vdbeapi.c dc904b3c5e459727993c2421e653e29d63223846d129fae98adc782b0a996481
F src/vdbeaux.c 01dcf59b2a96bd3cc9db8c0d7f266518d113587459a2b3316279c4f9c90f28a9
F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
F src/vdbe.c 6783778df820f3e0c68289fe5d12ddd34168b0eb1acf248668fec6e2ea1012d5
F src/vdbe.h 70a409d171d4e51b962f0d53abf15c33c404c6aa4c9d62fb3a931b5a62ba9615
F src/vdbeInt.h cdcdabad4f5d6bf7a3beb826a7f33ee6f8f1cb220042bedd5b7d4bf2ea1d179f
F src/vdbeapi.c c961d8d9e0f52e2df60a6ddbbccd7d99dc4d00103db7e53f77fcef44fbd23178
F src/vdbeaux.c bc9b3228f6d99bef0d0ecaf3a0e0e8358b3873242d0d2fe944226de3fdf9521e
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 2c70f8f5de6c71fb99a22c5b83be9fab5c47cdd8e279fa44a8c00cfed06d7e89
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
F src/vdbemem.c 94b17d851f31d4fd075d47d373d4b33ed3962a6ecb82cf385018025751091360
F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
F src/where.c c6352f15be5031907c68bcbde96cad1a6da20e9f4051d10168a59235de9a8566
F src/walker.c d46044e7a5842560dfe7122d93ff5145dd4a96f4d0bf5ba5910a7731b8c01e79
F src/where.c aa213e1b1c29eb8946a9f25108a18666a745ae5bac41b58d0be98730937a7785
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
F src/wherecode.c 8ad48867660519e262a401720845dc76934f86f558ec9606335fafcd7a2554f8
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
F src/wherecode.c 339ee802d9d311acf0cba8b5a9a092e167ef71c3a777d4b3e57de25d193251c7
F src/whereexpr.c a2fe3811d45af45a5c6667caabc15e01054fe6228c64e86e1f7d2ba5ef5284f9
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -537,7 +539,7 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
@@ -643,7 +645,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
@@ -827,7 +829,7 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a
F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
@@ -906,7 +908,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/join.test a26e4c45edba5d2090216be6fc26d8d862c1a66e5729ce38308b4f286aa745e5
F test/join.test 302f164f4a41c240d16ebd780762834233be77b852f15232c9a48a6fe37ac0fa
F test/join2.test a48f723c5692e2cbb23a9297ac2720cb77d51a70
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -923,7 +925,7 @@ F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb2848
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5
F test/kvtest.c d2b8cfc91047ebf6cac4f3a04f19c3a864e4ecfd683bbb65c395df450b8dc79c
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
@@ -1059,7 +1061,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl cb06c4df0de4872e65b178316f8a87ccf7624d59 x
F test/releasetest.tcl 7bb585433ce7fb2a2c255ae4b5e24f1bc27fe177ec1120f886cc4852f48f5ee9 x
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
@@ -1414,7 +1416,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
F test/vtabH.test 5f9253eb9e41ba9fe94f4aa3e9230191893d7764
F test/vtabH.test 26d54e8b5407f797638b787a55f9c88323850a58dd142de02d06b9a1159bd283
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
@@ -1476,7 +1478,7 @@ F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3
F test/with1.test 732e3ef398dcecb609839cd5ef0cb63beb2a9eff31420f3b745fc55b9e85b61e
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
@@ -1512,7 +1514,8 @@ 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 ab527af92dc684028e0d1db3fa6241787fae78987b99e5bbac7eb87e1970b8e5
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22
F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66eefaa4
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
@@ -1521,7 +1524,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 32bb40741df11bddc8451de9ea4d130e7b4476d8064794b1cf402ac110840fba
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
F tool/mksqlite3c.tcl 226da6d794d7d43a31e159a6fa89db867bf1f5eafe4b37d031222287ef8dbadc
F tool/mksqlite3h.tcl 51bd5e7e840a920388a5966c9f2ccc618f434c57bd68c1bab4085b2553e1e237
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
@@ -1539,7 +1542,7 @@ F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
F tool/spaceanal.tcl f40dc82b4d5e39d040a02a3ec38268e324068815e4292a15ffa30ee93208bbfd
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
@@ -1547,7 +1550,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/sqldiff.c 3fb48a6c6669d2d2c59a7f072a410dd2583579b4
F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
@@ -1580,10 +1583,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 05ada741554b9fd00befcf7b4083637f53de68699ae5210ac18e0773ad1a9910
R 7de9199234b8233f96ae8f86cad0d9b4
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.19.1 *
U drh
Z 01699a882c84539aef9719d24b44a477
P bc1951d699e6eeacbe15776a37cd0f5cf3f09eb85d3ae01cff43293cb286fcd7
R 45624ce11a236a8a994baa28885733aa
U dan
Z 71fa8cc8dcaaff976fb71d5480f74630
+1 -1
View File
@@ -1 +1 @@
f6d7b988f40217821a382bc298180e9e6794f3ed79a83c6ef5cae048989b3f86
95141c642697dc037e57f9e4992ff3460155995d3caef6259235601ee722cb93
+16 -15
View File
@@ -69,7 +69,8 @@ static void attachFunc(
char *zPath = 0;
char *zErr = 0;
unsigned int flags;
Db *aNew;
Db *aNew; /* New array of Db pointers */
Db *pNew; /* Db object for the newly attached database */
char *zErrDyn = 0;
sqlite3_vfs *pVfs;
@@ -117,8 +118,8 @@ static void attachFunc(
if( aNew==0 ) return;
}
db->aDb = aNew;
aNew = &db->aDb[db->nDb];
memset(aNew, 0, sizeof(*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
@@ -134,7 +135,7 @@ static void attachFunc(
}
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
db->skipBtreeMutex = 0;
@@ -143,28 +144,28 @@ static void attachFunc(
zErrDyn = sqlite3MPrintf(db, "database is already attached");
}else if( rc==SQLITE_OK ){
Pager *pPager;
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
if( !aNew->pSchema ){
pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
if( !pNew->pSchema ){
rc = SQLITE_NOMEM_BKPT;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
}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(aNew->pBt);
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3BtreeEnter(pNew->pBt);
pPager = sqlite3BtreePager(pNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(pNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
sqlite3BtreeSetPagerFlags(aNew->pBt,
sqlite3BtreeSetPagerFlags(pNew->pBt,
PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
#endif
sqlite3BtreeLeave(aNew->pBt);
sqlite3BtreeLeave(pNew->pBt);
}
aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
aNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && aNew->zDbSName==0 ){
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
pNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
+215 -210
View File
@@ -771,7 +771,7 @@ static int btreeMoveto(
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
rc = SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
goto moveto_done;
}
}else{
@@ -1000,7 +1000,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
sqlite3PagerUnref(pDbPage);
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
return SQLITE_OK;
}
@@ -1385,7 +1385,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
int sz = get2byte(&data[iFree+2]);
int top = get2byte(&data[hdr+5]);
if( iFree2 ){
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT;
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
sz2 = get2byte(&data[iFree2+2]);
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
@@ -1416,13 +1416,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
** if PRAGMA cell_size_check=ON.
*/
if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
assert( pc>=iCellFirst && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrk<iCellFirst || pc+size>usableSize ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
testcase( cbrk+size==usableSize );
@@ -1442,7 +1442,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
defragment_out:
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
assert( cbrk>=iCellFirst );
put2byte(&data[hdr+5], cbrk);
@@ -1481,7 +1481,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
** increasing offset. */
if( pc>usableSize-4 || pc<iAddr+4 ){
*pRc = SQLITE_CORRUPT_BKPT;
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
return 0;
}
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
@@ -1492,7 +1492,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
testcase( x==4 );
testcase( x==3 );
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_BKPT;
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
return 0;
}else if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
@@ -1559,7 +1559,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( top==0 && pPage->pBt->usableSize==65536 ){
top = 65536;
}else{
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
}
@@ -1655,11 +1655,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
if( iFreeBlk<iPtr+4 ){
if( iFreeBlk==0 ) break;
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
iPtr = iFreeBlk;
}
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT;
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
assert( iFreeBlk>iPtr || iFreeBlk==0 );
/* At this point:
@@ -1670,9 +1670,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
*/
if( iFreeBlk && iEnd+3>=iFreeBlk ){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT;
if( iEnd > pPage->pBt->usableSize ){
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
@@ -1684,20 +1686,20 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( iPtr>hdr+1 ){
int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
if( iPtrEnd+3>=iStart ){
if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT;
if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
nFrag += iStart - iPtrEnd;
iSize = iEnd - iPtr;
iStart = iPtr;
}
}
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT;
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
data[hdr+7] -= nFrag;
}
if( iStart==get2byte(&data[hdr+5]) ){
/* 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( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT;
if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
put2byte(&data[hdr+1], iFreeBlk);
put2byte(&data[hdr+5], iEnd);
}else{
@@ -1765,7 +1767,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}else{
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
** an error. */
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
pPage->max1bytePayload = pBt->max1bytePayload;
return SQLITE_OK;
@@ -1781,6 +1783,16 @@ static int decodeFlags(MemPage *pPage, int flagByte){
** 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 );
@@ -1788,127 +1800,119 @@ static int btreeInitPage(MemPage *pPage){
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
assert( pPage->isInit==0 );
if( !pPage->isInit ){
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 */
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_BKPT;
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_BKPT;
}
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_BKPT;
}
sz = pPage->xCellSize(pPage, &data[pc]);
testcase( pc+sz==usableSize );
if( pc+sz>usableSize ){
return SQLITE_CORRUPT_BKPT;
}
}
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_BKPT;
}
while( 1 ){
if( pc>iCellLast ){
return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
nFree = nFree + size;
if( next<=pc+size+3 ) break;
pc = next;
}
if( next>0 ){
return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */
}
if( pc+size>(unsigned int)usableSize ){
return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */
}
}
/* 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_BKPT;
}
pPage->nFree = (u16)(nFree - iCellFirst);
pPage->isInit = 1;
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_PGNO(pPage->pgno);
}
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_PGNO(pPage->pgno);
}
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_PGNO(pPage->pgno);
}
sz = pPage->xCellSize(pPage, &data[pc]);
testcase( pc+sz==usableSize );
if( pc+sz>usableSize ){
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
}
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_PGNO(pPage->pgno);
}
while( 1 ){
if( pc>iCellLast ){
/* Freeblock off the end of the page */
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
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_PGNO(pPage->pgno);
}
if( pc+size>(unsigned int)usableSize ){
/* Last freeblock extends past page end */
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
}
/* 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_PGNO(pPage->pgno);
}
pPage->nFree = (u16)(nFree - iCellFirst);
pPage->isInit = 1;
return SQLITE_OK;
}
@@ -2072,7 +2076,7 @@ static int getAndInitPage(
/* 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_BKPT;
rc = SQLITE_CORRUPT_PGNO(pgno);
releasePage(*ppPage);
goto getAndInitPage_error;
}
@@ -3360,7 +3364,7 @@ static int setChildPtrmaps(MemPage *pPage){
Pgno pgno = pPage->pgno;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
rc = btreeInitPage(pPage);
rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
if( rc!=SQLITE_OK ) return rc;
nCell = pPage->nCell;
@@ -3403,7 +3407,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
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_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
put4byte(pPage->aData, iTo);
}else{
@@ -3411,7 +3415,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
int nCell;
int rc;
rc = btreeInitPage(pPage);
rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
if( rc ) return rc;
nCell = pPage->nCell;
@@ -3422,7 +3426,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
if( iFrom==get4byte(pCell+info.nSize-4) ){
put4byte(pCell+info.nSize-4, iTo);
@@ -3440,7 +3444,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
@@ -4548,7 +4552,7 @@ static int accessPayload(
** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
** but is recast into its current form to avoid integer overflow problems
*/
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
/* Check if data must be read/written to/from the btree page itself. */
@@ -4695,7 +4699,8 @@ static int accessPayload(
}
if( rc==SQLITE_OK && amt>0 ){
return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */
/* Overflow chain ends prematurely */
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
return rc;
}
@@ -4961,7 +4966,7 @@ static int moveToRoot(BtCursor *pCur){
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
}
skip_init:
@@ -5166,16 +5171,19 @@ int sqlite3BtreeMovetoUnpacked(
/* 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 ase, only a little more slowely */
** is still obtained without this case, only a little more slowely */
if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, pRes);
if( rc ) return rc;
if( *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;
}
}
}
@@ -5231,7 +5239,9 @@ int sqlite3BtreeMovetoUnpacked(
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
if( pCell>=pPage->aDataEnd ){
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
}
}
getVarint(pCell, (u64*)&nCellKey);
@@ -5304,7 +5314,7 @@ int sqlite3BtreeMovetoUnpacked(
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
rc = SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_PGNO(pPage->pgno);
goto moveto_finish;
}
pCellKey = sqlite3Malloc( nCell+18 );
@@ -5409,10 +5419,12 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
}
/*
** Advance the cursor to the next entry in the database. If
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
** 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
@@ -5420,23 +5432,19 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been
** a unique index. Otherwise the caller will have set *pRes to zero.
** Zero is the common case. The btree implementation is free to use the
** initial *pRes value as a hint to improve performance, but the current
** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.)
** If bit 0x01 of the flags argument 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 flags 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 *pRes){
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int flags){
int rc;
int idx;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( *pRes==0 );
assert( flags==0 );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -5444,8 +5452,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -5477,15 +5484,14 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
do{
if( pCur->iPage==0 ){
*pRes = 1;
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
return SQLITE_DONE;
}
moveToParent(pCur);
pPage = pCur->apPage[pCur->iPage];
}while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
return sqlite3BtreeNext(pCur, pRes);
return sqlite3BtreeNext(pCur, flags);
}else{
return SQLITE_OK;
}
@@ -5496,20 +5502,18 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return moveToLeftmost(pCur);
}
}
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int sqlite3BtreeNext(BtCursor *pCur, int flags){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
*pRes = 0;
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, 0);
pPage = pCur->apPage[pCur->iPage];
if( (++pCur->ix)>=pPage->nCell ){
pCur->ix--;
return btreeNext(pCur, pRes);
return btreeNext(pCur, 0);
}
if( pPage->leaf ){
return SQLITE_OK;
@@ -5519,10 +5523,12 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
}
/*
** Step the cursor to the back to the previous entry in the database. If
** successful then set *pRes=0. If the cursor
** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1.
** 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
@@ -5530,22 +5536,18 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** helper routine is called when it is necessary to move to a different page
** or to restore the cursor.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been
** a unique index. Otherwise the caller will have set *pRes to zero.
** Zero is the common case. The btree implementation is free to use the
** initial *pRes value as a hint to improve performance, but the current
** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.)
**
** If bit 0x01 of the flags argument 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 flags argument is a hint to the implement.
** SQLite btree implementation does not use this hint, but COMDB2 does.
*/
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int flags){
int rc;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 );
assert( *pRes==0 );
assert( flags==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
@@ -5555,8 +5557,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -5580,8 +5581,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
while( pCur->ix==0 ){
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
*pRes = 1;
return SQLITE_OK;
return SQLITE_DONE;
}
moveToParent(pCur);
}
@@ -5591,26 +5591,24 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
pCur->ix--;
pPage = pCur->apPage[pCur->iPage];
if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
rc = sqlite3BtreePrevious(pCur, flags);
}else{
rc = SQLITE_OK;
}
}
return rc;
}
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
*pRes = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
|| pCur->ix==0
|| pCur->apPage[pCur->iPage]->leaf==0
){
return btreePrevious(pCur, pRes);
return btreePrevious(pCur, 0);
}
pCur->ix--;
return SQLITE_OK;
@@ -5718,7 +5716,7 @@ static int allocateBtreePage(
}
testcase( iTrunk==mxPage );
if( iTrunk>mxPage || nSearch++ > n ){
rc = SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1);
}else{
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
}
@@ -5747,7 +5745,7 @@ static int allocateBtreePage(
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_BKPT;
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList
@@ -5781,7 +5779,7 @@ static int allocateBtreePage(
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
if( iNewTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
@@ -5846,7 +5844,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
if( iPage>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iPage==mxPage );
@@ -6116,7 +6114,8 @@ static int clearCell(
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
/* Cell extends past end of page */
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
assert( pBt->usableSize > 4 );
@@ -8174,12 +8173,18 @@ int sqlite3BtreeInsert(
memcpy(newCell, oldCell, 4);
}
rc = clearCell(pPage, oldCell, &info);
if( info.nSize==szNew && info.nLocal==info.nPayload ){
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(). */
** 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);
@@ -8325,8 +8330,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** 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 ){
int notUsed = 0;
rc = sqlite3BtreePrevious(pCur, &notUsed);
rc = sqlite3BtreePrevious(pCur, 0);
assert( rc!=SQLITE_DONE );
if( rc ) return rc;
}
+2 -2
View File
@@ -286,9 +286,9 @@ int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int flags);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreePrevious(BtCursor*, int flags);
i64 sqlite3BtreeIntegerKey(BtCursor*);
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
+4
View File
@@ -939,7 +939,11 @@ void sqlite3StartTable(
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;
+335 -62
View File
@@ -16,7 +16,11 @@
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
#include "sqliteInt.h"
/* 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
@@ -28,17 +32,30 @@
*/
static const char * const azCompileOpt[] = {
/* 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)
/*
** 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
@@ -57,31 +74,100 @@ static const char * const azCompileOpt[] = {
#if SQLITE_COVERAGE_TEST
"COVERAGE_TEST",
#endif
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG
"DEBUG",
#endif
#if SQLITE_DEFAULT_LOCKING_MODE
#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
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
#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
#if SQLITE_DEFAULT_SYNCHRONOUS
#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
#if SQLITE_DEFAULT_WAL_SYNCHRONOUS
#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_ENABLE_8_3_NAMES
#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
@@ -96,6 +182,15 @@ static const char * const azCompileOpt[] = {
#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
@@ -114,12 +209,18 @@ static const char * const azCompileOpt[] = {
#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
@@ -132,7 +233,7 @@ static const char * const azCompileOpt[] = {
#if SQLITE_ENABLE_LOAD_EXTENSION
"ENABLE_LOAD_EXTENSION",
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -144,26 +245,86 @@ static const char * const azCompileOpt[] = {
#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_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_SQLLOG
"ENABLE_SQLLOG",
#endif
#if defined(SQLITE_ENABLE_STAT4)
"ENABLE_STAT4",
#elif defined(SQLITE_ENABLE_STAT3)
"ENABLE_STAT3",
#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 defined(SQLITE_ENABLE_URI_00_ERROR)
#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
@@ -179,27 +340,114 @@ static const char * const azCompileOpt[] = {
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
"IGNORE_FLOCK_LOCK_ERRORS",
#endif
#ifdef SQLITE_INT64_TYPE
#if SQLITE_INLINE_MEMCPY
"INLINE_MEMCPY",
#endif
#if SQLITE_INT64_TYPE
"INT64_TYPE",
#endif
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
#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 defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
#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
@@ -251,6 +499,9 @@ static const char * const azCompileOpt[] = {
#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
@@ -281,6 +532,9 @@ static const char * const azCompileOpt[] = {
#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
@@ -308,6 +562,12 @@ static const char * const azCompileOpt[] = {
#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
@@ -329,6 +589,9 @@ static const char * const azCompileOpt[] = {
#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
@@ -338,6 +601,9 @@ static const char * const azCompileOpt[] = {
#if SQLITE_OMIT_TEMPDB
"OMIT_TEMPDB",
#endif
#if SQLITE_OMIT_TEST_CONTROL
"OMIT_TEST_CONTROL",
#endif
#if SQLITE_OMIT_TRACE
"OMIT_TRACE",
#endif
@@ -368,12 +634,24 @@ static const char * const azCompileOpt[] = {
#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
@@ -383,16 +661,28 @@ static const char * const azCompileOpt[] = {
#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
#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
#ifdef SQLITE_TEMP_STORE
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#if SQLITE_TEST
@@ -400,64 +690,47 @@ static const char * const azCompileOpt[] = {
#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"
"UNTESTABLE",
#endif
#if SQLITE_USER_AUTHENTICATION
"USER_AUTHENTICATION",
#endif
#if SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#if SQLITE_USER_AUTHENTICATION
"USER_AUTHENTICATION",
#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"
"ZERO_MALLOC",
#endif
/*
** END CODE GENERATED BY tool/mkctime.tcl
*/
};
/*
** 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;
#if SQLITE_ENABLE_API_ARMOR
if( zOptName==0 ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
n = sqlite3Strlen30(zOptName);
/* Since ArraySize(azCompileOpt) is normally in single digits, a
** linear search is adequate. No need for a binary search. */
for(i=0; i<ArraySize(azCompileOpt); 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){
if( N>=0 && N<ArraySize(azCompileOpt) ){
return azCompileOpt[N];
}
return 0;
const char **sqlite3CompileOptions(int *pnOpt){
*pnOpt = sizeof(azCompileOpt) / sizeof(azCompileOpt[0]);
return (const char**)azCompileOpt;
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+2 -2
View File
@@ -353,7 +353,7 @@ void sqlite3DeleteFrom(
** API function sqlite3_count_changes) to be set incorrectly.
**
** The "rcauth==SQLITE_OK" terms is the
** IMPLEMENATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
** 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.
@@ -459,7 +459,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
}else{
/* Add the rowid of the row to be deleted to the RowSet */
nKey = 1; /* OP_Seek always uses a single rowid */
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
}
+23 -10
View File
@@ -1488,7 +1488,9 @@ ExprList *sqlite3ExprListAppend(
pList->nAlloc *= 2;
}
pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
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;
@@ -1740,10 +1742,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
}else{
pWalker->eCode = 0;
return WRC_Abort;
}
/* Fall through */
case TK_IF_NULL_ROW:
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
@@ -1770,10 +1774,12 @@ static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
}
static int exprIsConst(Expr *p, int initFlag, int iCur){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = initFlag;
w.xExprCallback = exprNodeIsConstant;
w.xSelectCallback = selectNodeIsConstant;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
@@ -1861,9 +1867,9 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
*/
int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = exprNodeIsConstantOrGroupBy;
w.xSelectCallback = 0;
w.u.pGroupBy = pGroupBy;
w.pParse = pParse;
sqlite3WalkExpr(&w, p);
@@ -1891,10 +1897,12 @@ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
*/
int sqlite3ExprContainsSubquery(Expr *p){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = sqlite3ExprWalkNoop;
w.xSelectCallback = selectNodeIsConstant;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
sqlite3WalkExpr(&w, p);
return w.eCode==0;
}
@@ -4899,8 +4907,8 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
Walker w;
struct SrcCount cnt;
assert( pExpr->op==TK_AGG_FUNCTION );
memset(&w, 0, sizeof(w));
w.xExprCallback = exprSrcCount;
w.xSelectCallback = 0;
w.u.pSrcCount = &cnt;
cnt.pSrc = pSrcList;
cnt.nThis = 0;
@@ -5072,10 +5080,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pWalker);
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
@@ -5088,9 +5100,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
*/
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = analyzeAggregate;
w.xSelectCallback = analyzeAggregatesInSelect;
w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
w.walkerDepth = 0;
w.u.pNC = pNC;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
+1 -1
View File
@@ -521,10 +521,10 @@ void sqlite3Insert(
#endif
db = pParse->db;
memset(&dest, 0, sizeof(dest));
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
+59
View File
@@ -867,6 +867,7 @@ static int binCollFunc(
/* 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
@@ -3337,6 +3338,12 @@ int sqlite3CantopenError(int lineno){
return reportError(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 reportError(SQLITE_CORRUPT, lineno, zMsg);
}
int sqlite3NomemError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
return reportError(SQLITE_NOMEM, lineno, "OOM");
@@ -4095,3 +4102,55 @@ 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 */
+18 -25
View File
@@ -3253,7 +3253,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the
** WAL sub-system, determine the page counte based on the size of
** 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.
*/
@@ -3304,23 +3304,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){
if( !pPager->tempFile ){
int isWal; /* True if WAL file exists */
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);
if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
isWal = 0;
}else{
rc = sqlite3OsAccess(
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
);
}
rc = sqlite3OsAccess(
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
);
if( rc==SQLITE_OK ){
if( isWal ){
testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
rc = sqlite3PagerOpenWal(pPager, 0);
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;
}
@@ -5263,19 +5261,14 @@ int sqlite3PagerSharedLock(Pager *pPager){
** detected. The chance of an undetected change is so small that
** it can be neglected.
*/
Pgno nPage = 0;
char dbFileVers[sizeof(pPager->dbFileVers)];
rc = pagerPagecount(pPager, &nPage);
if( rc ) goto failed;
if( nPage>0 ){
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
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;
}
}else{
memset(dbFileVers, 0, sizeof(dbFileVers));
}
+4 -4
View File
@@ -26,6 +26,7 @@ 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 */
@@ -35,12 +36,11 @@ struct PgHdr {
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
** Elements above are public. All that follows is private to pcache.c
** and should not be accessed by other modules.
** 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 */
PCache *pCache; /* Cache that owns this page */
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
};
+10 -18
View File
@@ -1430,37 +1430,29 @@ int sqlite3ResolveExprNames(
u16 savedHasAgg;
Walker w;
if( pExpr==0 ) return 0;
#if SQLITE_MAX_EXPR_DEPTH>0
{
Parse *pParse = pNC->pParse;
if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
return 1;
}
pParse->nHeight += pExpr->nHeight;
}
#endif
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.walkerDepth = 0;
w.eCode = 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
pNC->pParse->nHeight -= pExpr->nHeight;
w.pParse->nHeight -= pExpr->nHeight;
#endif
if( pNC->nErr>0 || w.pParse->nErr>0 ){
ExprSetProperty(pExpr, EP_Error);
}
if( pNC->ncFlags & NC_HasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}
pNC->ncFlags |= savedHasAgg;
return ExprHasProperty(pExpr, EP_Error);
return pNC->nErr>0 || w.pParse->nErr>0;
}
/*
@@ -1501,9 +1493,9 @@ void sqlite3ResolveSelectNames(
Walker w;
assert( p!=0 );
memset(&w, 0, sizeof(w));
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
w.xSelectCallback2 = 0;
w.pParse = pParse;
w.u.pNC = pOuterNC;
sqlite3WalkSelect(&w, p);
+34 -4
View File
@@ -1031,7 +1031,7 @@ static void selectInnerLoop(
** X extra columns.
*/
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
int nExtra = (N+X)*(sizeof(CollSeq*)+1);
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];
@@ -3511,6 +3511,14 @@ static int flattenSubquery(
return 0; /* Restriction (3) */
}
}
#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
@@ -3764,7 +3772,7 @@ static int flattenSubquery(
pSub->pOrderBy = 0;
}
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
if( isLeftJoin ){
if( isLeftJoin>0 ){
setJoinExpr(pWhere, iNewParent);
}
if( subqueryIsAgg ){
@@ -4602,6 +4610,25 @@ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *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
@@ -4617,11 +4644,11 @@ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
*/
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3ExprWalkNoop;
w.pParse = pParse;
if( pParse->hasCompound ){
w.xSelectCallback = convertCompoundSelectToSubquery;
w.xSelectCallback2 = 0;
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
@@ -4681,7 +4708,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
#ifndef SQLITE_OMIT_SUBQUERY
Walker w;
memset(&w, 0, sizeof(w));
w.xSelectCallback = sqlite3SelectWalkNoop;
w.xSelectCallback2 = selectAddSubqueryTypeInfo;
w.xExprCallback = sqlite3ExprWalkNoop;
w.pParse = pParse;
@@ -5262,6 +5289,9 @@ int sqlite3Select(
pPrior = isSelfJoinView(pTabList, pItem);
if( pPrior ){
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
explainSetInteger(pItem->iSelectId, pPrior->iSelectId);
assert( pPrior->pSelect!=0 );
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+264 -145
View File
@@ -18,11 +18,25 @@
#endif
/*
** If requested, include the SQLite compiler options file for MSVC.
** Warning pragmas copied from msvc.h in the core.
*/
#if defined(INCLUDE_MSVC_H)
#include "msvc.h"
#endif
#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.
@@ -495,6 +509,18 @@ static int strlen30(const char *z){
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
@@ -703,6 +729,61 @@ static char quoteChar(const char *zName){
return 0;
}
/*
** 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]);
assert( nVal==2 );
if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
for(i=0; i<sizeof(aPrefix)/sizeof(aPrefix[0]); i++){
int n = strlen30(aPrefix[i]);
if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
char cQuote = quoteChar(zSchema);
char *z;
if( cQuote ){
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);
}
sqlite3_result_text(pCtx, z, -1, sqlite3_free);
return;
}
}
}
sqlite3_result_value(pCtx, apVal[0]);
}
/******************************************************************************
** SHA3 hash implementation copied from ../ext/misc/shathree.c
*/
@@ -1163,7 +1244,7 @@ static unsigned char *SHA3Final(SHA3Context *p){
** 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.
** 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.
@@ -1903,9 +1984,9 @@ static int shell_callback(
w = 0;
}
if( w==0 ){
w = strlen30(azCol[i] ? azCol[i] : "");
w = strlenChar(azCol[i] ? azCol[i] : "");
if( w<10 ) w = 10;
n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue);
n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
if( w<n ) w = n;
}
if( i<ArraySize(p->actualWidth) ){
@@ -1940,8 +2021,8 @@ static int shell_callback(
}else{
w = 10;
}
if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
w = strlen30(azArg[i]);
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 ){
@@ -2997,7 +3078,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
nPK++;
if( nPK==1
&& sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
"INTEGER")==0
"INTEGER")==0
){
isIPK = 1;
}else{
@@ -3234,6 +3315,7 @@ static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\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"
@@ -3279,8 +3361,8 @@ static char zHelp[] =
" tcl TCL list elements\n"
".nullvalue STRING Use STRING in place of NULL values\n"
".once FILENAME Output for the next SQL command only to FILENAME\n"
".open ?--new? ?FILE? Close existing database and reopen FILE\n"
" The --new starts with an empty file\n"
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
" The --new option starts with an empty file\n"
".output ?FILENAME? Send output to FILENAME or stdout\n"
".print STRING... Print literal STRING\n"
".prompt MAIN CONTINUE Replace the standard prompts\n"
@@ -3345,8 +3427,8 @@ 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.
** 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.
@@ -3509,6 +3591,9 @@ static void open_db(ShellState *p, int keepAlive){
sha3QueryFunc, 0, 0);
sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0,
sha3QueryFunc, 0, 0);
sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0,
shellAddSchemaName, 0, 0);
}
}
@@ -4353,15 +4438,15 @@ int shellDeleteFile(const char *zFilename){
** 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
** 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_context *pCtx,
int nVal,
sqlite3_value **apVal
){
sqlite3 *db = sqlite3_context_db_handle(pCtx);
@@ -4372,7 +4457,7 @@ static void shellFkeyCollateClause(
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]);
@@ -4494,7 +4579,7 @@ static int lintFkeyIndexes(
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
@@ -4537,9 +4622,9 @@ static int lintFkeyIndexes(
raw_printf(stderr, "Error: internal error");
break;
}else{
if( bGroupByParent
if( bGroupByParent
&& (bVerbose || res==0)
&& (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
&& (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
){
raw_printf(out, "-- Parent table %s\n", zParent);
sqlite3_free(zPrev);
@@ -4549,7 +4634,7 @@ static int lintFkeyIndexes(
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",
raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
zIndent, zFrom, zTarget
);
}
@@ -4731,6 +4816,25 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}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().
*/
@@ -5643,12 +5747,17 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
ShellText sSelect;
ShellState data;
char *zErrMsg = 0;
const char *zDiv = 0;
int iSchema = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_Semi;
initText(&sSelect);
if( nArg>=2 && optionMatch(azArg[1], "indent") ){
data.cMode = data.mode = MODE_Pretty;
nArg--;
@@ -5686,33 +5795,62 @@ static int do_meta_command(char *zLine, ShellState *p){
callback(&data, 1, new_argv, new_colv);
rc = SQLITE_OK;
}else{
char *zSql;
zSql = sqlite3_mprintf(
"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 lower(tbl_name) LIKE %Q"
" AND type!='meta' AND sql NOTNULL "
"ORDER BY rowid", azArg[1]);
rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg);
sqlite3_free(zSql);
zDiv = "(";
}
}else if( nArg==1 ){
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
);
zDiv = "(";
}else{
raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
if( zDiv ){
sqlite3_stmt *pStmt = 0;
sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
-1, &pStmt, 0);
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 ";
if( strcmp(zDb, "main")!=0 ){
appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
appendText(&sSelect, zDb, '"');
appendText(&sSelect, ") 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);
}else{
appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0);
appendText(&sSelect, zScNum, 0);
appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0);
}
}
sqlite3_finalize(pStmt);
appendText(&sSelect, ") WHERE ", 0);
if( nArg>1 ){
char *zQarg = sqlite3_mprintf("%Q", azArg[1]);
if( strchr(azArg[1], '.') ){
appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
}else{
appendText(&sSelect, "lower(tbl_name)", 0);
}
appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0);
appendText(&sSelect, zQarg, 0);
appendText(&sSelect, " AND ", 0);
sqlite3_free(zQarg);
}
appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
freeText(&sSelect);
}
if( zErrMsg ){
utf8_printf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
@@ -5954,19 +6092,11 @@ static int do_meta_command(char *zLine, ShellState *p){
int bIsInit = 0; /* True to initialize the SELFTEST table */
int bVerbose = 0; /* Verbose output */
int bSelftestExists; /* True if SELFTEST already exists */
char **azTest = 0; /* Content of the SELFTEST table */
int nRow = 0; /* Number of rows in the SELFTEST table */
int nCol = 4; /* Number of columns in the SELFTEST table */
int i; /* Loop counter */
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 */
static char *azDefaultTest[] = {
0, 0, 0, 0,
"0", "memo", "Missing SELFTEST table - default checks only", "",
"1", "run", "PRAGMA integrity_check", "ok"
};
static const int nDefaultRow = 2;
sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
open_db(p,0);
for(i=1; i<nArg; i++){
@@ -5996,70 +6126,71 @@ static int do_meta_command(char *zLine, ShellState *p){
createSelftestTable(p);
bSelftestExists = 1;
}
if( bSelftestExists ){
rc = sqlite3_get_table(p->db,
"SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
&azTest, &nRow, &nCol, 0);
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_free_table(azTest);
sqlite3_finalize(pStmt);
goto meta_command_exit;
}else if( nRow==0 ){
sqlite3_free_table(azTest);
azTest = azDefaultTest;
nRow = nDefaultRow;
}
}else{
azTest = azDefaultTest;
nRow = nDefaultRow;
}
initText(&str);
appendText(&str, "x", 0);
for(i=1; i<=nRow; i++){
int tno = atoi(azTest[i*nCol]);
const char *zOp = azTest[i*nCol+1];
const char *zSql = azTest[i*nCol+2];
const char *zAns = azTest[i*nCol+3];
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);
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( rc || zErrMsg ){
nErr++;
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;
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);
break;
}
}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);
if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
}else
@@ -6099,8 +6230,8 @@ static int do_meta_command(char *zLine, ShellState *p){
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
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
@@ -6268,59 +6399,47 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_stmt *pStmt;
char **azResult;
int nRow, nAlloc;
char *zSql = 0;
int ii;
ShellText s;
initText(&s);
open_db(p, 0);
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
if( rc ) return shellDatabaseError(p->db);
/* Create an SQL statement to query for the list of tables in the
** main and all attached databases where the table name matches the
** LIKE pattern bound to variable "?1". */
if( c=='t' ){
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1");
}else if( nArg>2 ){
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;
goto meta_command_exit;
}else{
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_master"
" WHERE type='index'"
" AND tbl_name LIKE ?1");
}
for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
if( zDbName==0 || ii==0 ) continue;
if( c=='t' ){
zSql = sqlite3_mprintf(
"%z UNION ALL "
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
" WHERE type IN ('table','view')"
" AND name NOT LIKE 'sqlite_%%'"
" AND name LIKE ?1", zSql, zDbName, zDbName);
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{
zSql = sqlite3_mprintf(
"%z UNION ALL "
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
" WHERE type='index'"
" AND tbl_name LIKE ?1", zSql, zDbName, zDbName);
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);
if( zSql && rc==SQLITE_OK ){
zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
}
sqlite3_free(zSql);
if( !zSql ) return shellNomemError();
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
+10 -1
View File
@@ -5620,7 +5620,9 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** ^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.
** 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
@@ -7133,6 +7135,12 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** 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_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>
*/
@@ -7140,6 +7148,7 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
#define SQLITE_STMTSTATUS_VM_STEP 4
#define SQLITE_STMTSTATUS_MEMUSED 5
/*
** CAPI3REF: Custom Page Cache Object
+16 -5
View File
@@ -274,6 +274,11 @@
**
** 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)
@@ -589,7 +594,6 @@
*/
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 1
# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
#endif
/*
@@ -890,7 +894,6 @@ typedef INT16_TYPE LogEst;
# else
# define SQLITE_MAX_MMAP_SIZE 0
# endif
# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
#endif
/*
@@ -900,7 +903,6 @@ typedef INT16_TYPE LogEst;
*/
#ifndef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE 0
# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
@@ -2364,7 +2366,7 @@ struct Expr {
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x000008 /* Expression contains one or more errors */
/* 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 "..." */
@@ -2831,10 +2833,10 @@ struct Select {
*/
struct SelectDest {
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
char *zAffSdst; /* Affinity used when eDest==SRT_Set */
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 */
};
@@ -3337,6 +3339,10 @@ int sqlite3WalkSelect(Walker*, Select*);
int sqlite3WalkSelectExpr(Walker*, Select*);
int sqlite3WalkSelectFrom(Walker*, Select*);
int sqlite3ExprWalkNoop(Walker*, Expr*);
int sqlite3SelectWalkNoop(Walker*, Select*);
#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
/*
** Return code from the parse-tree walking primitives and their
@@ -3398,11 +3404,14 @@ int sqlite3CantopenError(int);
#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
/*
@@ -4363,4 +4372,6 @@ Expr *sqlite3VectorFieldSubexpr(Expr*, int);
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
void sqlite3VectorErrorMsg(Parse*, Expr*);
const char **sqlite3CompileOptions(int *pnOpt);
#endif /* SQLITEINT_H */
+5 -1
View File
@@ -306,7 +306,11 @@ static int SQLITE_TCLAPI btree_next(
}
pCur = sqlite3TestTextToPtr(argv[1]);
sqlite3BtreeEnter(pCur->pBtree);
rc = sqlite3BtreeNext(pCur, &res);
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_DONE ){
res = 1;
rc = SQLITE_OK;
}
sqlite3BtreeLeave(pCur->pBtree);
if( rc ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+1
View File
@@ -545,6 +545,7 @@ static int fstreeFilter(
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);
+1
View File
@@ -306,6 +306,7 @@ void sqlite3FinishTrigger(
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,
+1 -1
View File
@@ -201,7 +201,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
char *zKey;
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
if( nKey ) db->nextPagesize = 0;
}
#endif
+41 -28
View File
@@ -573,7 +573,7 @@ int sqlite3VdbeExec(
int iCompare = 0; /* Result of last comparison */
unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
@@ -605,6 +605,8 @@ int sqlite3VdbeExec(
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
@@ -782,7 +784,7 @@ check_for_interrupt:
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
assert( db->nProgressOps!=0 );
nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
if( db->xProgress(db->pProgressArg) ){
@@ -1324,7 +1326,7 @@ case OP_ResultRow: {
/* Run the progress counter just before returning.
*/
if( db->xProgress!=0
&& nVmStep>=nProgressLimit
&& nVmStep>=nProgressLimit
&& db->xProgress(db->pProgressArg)!=0
){
rc = SQLITE_INTERRUPT;
@@ -2495,7 +2497,9 @@ case OP_Column: {
pC = p->apCsr[pOp->p1];
p2 = pOp->p2;
/* If the cursor cache is stale, bring it up-to-date */
/* 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;
@@ -3977,8 +3981,15 @@ case OP_SeekGT: { /* jump, in3 */
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, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
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;
}
@@ -3986,8 +3997,15 @@ case OP_SeekGT: { /* jump, in3 */
assert( oc==OP_SeekLT || oc==OP_SeekLE );
if( res>0 || (res==0 && oc==OP_SeekLT) ){
res = 0;
rc = sqlite3BtreePrevious(pC->uc.pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
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.
@@ -5093,12 +5111,10 @@ case OP_Rewind: { /* jump */
*/
case OP_SorterNext: { /* jump */
VdbeCursor *pC;
int res;
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
res = 0;
rc = sqlite3VdbeSorterNext(db, pC, &res);
rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_PrevIfOpen: /* jump */
case OP_NextIfOpen: /* jump */
@@ -5109,12 +5125,9 @@ case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<ArraySize(p->aCounter) );
pC = p->apCsr[pOp->p1];
res = pOp->p3;
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( res==0 || (res==1 && pC->isTable==0) );
testcase( res==1 );
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 );
@@ -5129,21 +5142,21 @@ case OP_Next: /* jump */
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last );
rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
pC->cacheStatus = CACHE_STALE;
VdbeBranchTaken(res==0,2);
if( rc ) goto abort_due_to_error;
if( res==0 ){
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;
}else{
pC->nullRow = 1;
}
if( rc!=SQLITE_DONE ) goto abort_due_to_error;
rc = SQLITE_OK;
pC->nullRow = 1;
goto check_for_interrupt;
}
@@ -5254,8 +5267,8 @@ case OP_IdxDelete: {
break;
}
/* Opcode: Seek P1 * P3 P4 *
** Synopsis: Move P3 to P1.rowid
/* 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
@@ -5282,11 +5295,11 @@ case OP_IdxDelete: {
**
** See also: Rowid, MakeRecord.
*/
case OP_Seek:
case OP_IdxRowid: { /* out2 */
VdbeCursor *pC; /* The P1 index cursor */
VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */
i64 rowid; /* Rowid that P1 current points to */
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];
@@ -5312,7 +5325,7 @@ case OP_IdxRowid: { /* out2 */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( pOp->opcode==OP_Seek ){
if( pOp->opcode==OP_DeferredSeek ){
assert( pOp->p3>=0 && pOp->p3<p->nCursor );
pTabCur = p->apCsr[pOp->p3];
assert( pTabCur!=0 );
+1 -1
View File
@@ -63,7 +63,7 @@ struct VdbeOp {
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
int (*xAdvance)(BtCursor *, int *);
int (*xAdvance)(BtCursor *, int);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
+1 -1
View File
@@ -506,7 +506,7 @@ int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
+17 -4
View File
@@ -1303,8 +1303,10 @@ static int bindText(
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
sqlite3Error(p->db, rc);
rc = sqlite3ApiExit(p->db, rc);
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 ){
@@ -1611,8 +1613,19 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
return 0;
}
#endif
v = pVdbe->aCounter[op];
if( resetFlag ) pVdbe->aCounter[op] = 0;
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;
}
+15 -13
View File
@@ -2160,17 +2160,18 @@ static void Cleanup(Vdbe *p){
** be called on an SQL statement before sqlite3_step().
*/
void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
Mem *pColName;
int n;
sqlite3 *db = p->db;
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqlite3DbFree(db, p->aColName);
if( p->nResColumn ){
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqlite3DbFree(db, p->aColName);
}
n = nResColumn*COLNAME_N;
p->nResColumn = (u16)nResColumn;
p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
initMemArray(p->aColName, n, p->db, MEM_Null);
initMemArray(p->aColName, n, db, MEM_Null);
}
/*
@@ -2820,10 +2821,10 @@ int sqlite3VdbeTransferError(Vdbe *p){
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->bBenignMalloc--;
db->errCode = rc;
}else{
sqlite3Error(db, rc);
}else if( db->pErr ){
sqlite3ValueSetNull(db->pErr);
}
db->errCode = rc;
return rc;
}
@@ -3731,7 +3732,6 @@ static int vdbeCompareMemString(
}else{
int rc;
const void *v1, *v2;
int n1, n2;
Mem c1;
Mem c2;
sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
@@ -3739,11 +3739,13 @@ static int vdbeCompareMemString(
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
n1 = v1==0 ? 0 : c1.n;
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
n2 = v2==0 ? 0 : c2.n;
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
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;
+1 -1
View File
@@ -1325,7 +1325,7 @@ static int valueFromExpr(
}
}else if( op==TK_UMINUS ) {
/* This branch happens for multiple negative signs. Ex: -(-5) */
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
&& pVal!=0
){
sqlite3VdbeMemNumerify(pVal);
+14 -9
View File
@@ -815,9 +815,9 @@ static int vdbeSorterCompareText(
int n2;
int res;
getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
res = memcmp(v1, v2, MIN(n1, n2));
getVarint32(&p1[1], n1);
getVarint32(&p2[1], n2);
res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
if( res==0 ){
res = n1 - n2;
}
@@ -2612,9 +2612,13 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
}
/*
** Advance to the next element in the sorter.
** 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, int *pbEof){
int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){
VdbeSorter *pSorter;
int rc; /* Return code */
@@ -2628,21 +2632,22 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
#if SQLITE_MAX_WORKER_THREADS>0
if( pSorter->bUseThreads ){
rc = vdbePmaReaderNext(pSorter->pReader);
*pbEof = (pSorter->pReader->pFd==0);
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, pbEof);
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);
*pbEof = !pSorter->list.pList;
rc = SQLITE_OK;
rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
}
return rc;
}
+9 -16
View File
@@ -124,8 +124,9 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
**
** If it is not NULL, the xSelectCallback() callback is invoked before
** the walk of the expressions and FROM clause. The xSelectCallback2()
** method, if it is not NULL, is invoked following the walk of the
** expressions and FROM clause.
** 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.
@@ -135,27 +136,19 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
*/
int sqlite3WalkSelect(Walker *pWalker, Select *p){
int rc;
if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
return WRC_Continue;
}
rc = WRC_Continue;
pWalker->walkerDepth++;
while( p ){
if( pWalker->xSelectCallback ){
rc = pWalker->xSelectCallback(pWalker, p);
if( rc ) break;
}
if( p==0 || 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)
){
pWalker->walkerDepth--;
return WRC_Abort;
}
if( pWalker->xSelectCallback2 ){
pWalker->xSelectCallback2(pWalker, p);
}
p = p->pPrior;
}
pWalker->walkerDepth--;
return rc & WRC_Abort;
}while( p!=0 );
return WRC_Continue;
}
+37 -24
View File
@@ -1192,7 +1192,7 @@ static int whereKeyStats(
iGap = iGap/3;
}
aStat[0] = iLower + iGap;
aStat[1] = pIdx->aAvgEq[iCol];
aStat[1] = pIdx->aAvgEq[nField-1];
}
/* Restore the pRec->nField value before returning. */
@@ -1945,16 +1945,17 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
/*
** Search the list of WhereLoops in *ppPrev looking for one that can be
** supplanted by pTemplate.
** replaced by pTemplate.
**
** Return NULL if the WhereLoop list contains an entry that can supplant
** pTemplate, in other words if pTemplate does not belong on the list.
** 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 supplant, then return the
** If pX is a WhereLoop that pTemplate can replace, then return the
** link that points to pX.
**
** If pTemplate cannot supplant any existing element of the list but needs
** to be added to the list, then return a pointer to the tail of the list.
** 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,
@@ -2099,8 +2100,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
if( p!=0 ){
sqlite3DebugPrintf("replace: ");
whereLoopPrint(p, pBuilder->pWC);
sqlite3DebugPrintf(" with: ");
}else{
sqlite3DebugPrintf(" add: ");
}
sqlite3DebugPrintf(" add: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
@@ -4000,8 +4003,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** this candidate as not viable. */
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -4019,26 +4022,36 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
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 sam isOrdered setting as 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 */
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
** 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 order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
"Skip %s cost=%-3d,%3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
isOrdered>=0 ? isOrdered+'0' : '?');
sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
/* Discard the candidate path from further consideration */
@@ -4051,12 +4064,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Update %s cost=%-3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
"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 order=%c\n",
sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
}
@@ -4564,7 +4577,7 @@ WhereInfo *sqlite3WhereBegin(
static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
p->cId = zLabel[i%sizeof(zLabel)];
p->cId = zLabel[i%(sizeof(zLabel)-1)];
whereLoopPrint(p, sWLB.pWC);
}
}
+3 -3
View File
@@ -966,10 +966,10 @@ static void codeCursorHint(
**
** Normally, this is just:
**
** OP_Seek $iCur $iRowid
** 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 the OP_Seek
** 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
@@ -988,7 +988,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur);
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
){
+3 -3
View File
@@ -1375,11 +1375,11 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
Bitmask mask;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
mask = sqlite3WhereGetMask(pMaskSet, p->iTable);
return mask;
return sqlite3WhereGetMask(pMaskSet, p->iTable);
}
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
assert( !ExprHasProperty(p, EP_TokenOnly) );
mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0;
if( p->pRight ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
if( ExprHasProperty(p, EP_xIsSelect) ){
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
+7
View File
@@ -705,5 +705,12 @@ do_test autovacuum-9.5 {
file size test.db
} $::sqlite_pending_byte
do_execsql_test autovacuum-10.1 {
DROP TABLE t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
INSERT INTO t1 VALUES(25, randomblob(104));
REPLACE INTO t1 VALUES(25, randomblob(1117));
PRAGMA integrity_check;
} {ok}
finish_test
+18
View File
@@ -61,6 +61,24 @@ do_test ctime-1.2.2 {
list [ lindex $ans 0 ] [ expr { [lsort [lindex $ans 1]]==[lindex $ans 1] } ]
} {0 1}
# Check the THREADSAFE option for SQLITE_THREADSAFE=2 builds (there are
# a couple of these configurations in releasetest.tcl).
#
ifcapable threadsafe2 {
foreach {tn opt res} {
1 SQLITE_THREADSAFE 1
2 THREADSAFE 1
3 THREADSAFE=0 0
4 THREADSAFE=1 0
5 THREADSAFE=2 1
6 THREADSAFE= 0
} {
do_execsql_test ctime-1.3.$tn {
SELECT sqlite_compileoption_used($opt)
} $res
}
}
# SQLITE_THREADSAFE should pretty much always be defined
# one way or the other, and it must have a value of 0 or 1.
do_test ctime-1.4.1 {
+3 -1
View File
@@ -384,7 +384,9 @@ foreach T $tokenizers {
do_isspace_test 6.$T.13 $T 8200
do_isspace_test 6.$T.14 $T 8201
do_isspace_test 6.$T.15 $T 8202
do_isspace_test 6.$T.16 $T 8239
if {$T!="icu"} {
do_isspace_test 6.$T.16 $T 8239
}
do_isspace_test 6.$T.17 $T 8287
do_isspace_test 6.$T.18 $T 12288
+20
View File
@@ -743,4 +743,24 @@ do_execsql_test join-14.5 {
SELECT * FROM (SELECT 111) LEFT JOIN (SELECT c+222 FROM t1) GROUP BY 1;
} {111 {}}
# Verify the fix to ticket
# https://www.sqlite.org/src/tktview/7fde638e94287d2c948cd9389
#
db close
sqlite3 db :memory:
do_execsql_test join-14.10 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(1),(2),(3);
CREATE VIEW v2 AS SELECT a, 1 AS b FROM t1;
CREATE TABLE t3(x);
INSERT INTO t3 VALUES(2),(4);
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x WHERE b=1;
} {2 2 1 |}
do_execsql_test join-14.11 {
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x WHERE b+1=x;
} {2 2 1 |}
do_execsql_test join-14.12 {
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x ORDER BY b;
} {4 {} {} | 2 2 1 |}
finish_test
+355 -86
View File
@@ -71,14 +71,21 @@ static const char zHelp[] =
"\n"
" --variance V Randomly vary M by plus or minus V\n"
"\n"
" kvtest export DBFILE DIRECTORY\n"
" kvtest export DBFILE DIRECTORY [--tree]\n"
"\n"
" Export all the blobs in the kv table of DBFILE into separate\n"
" files in DIRECTORY.\n"
" files in DIRECTORY. DIRECTORY is created if it does not previously\n"
" exist. If the --tree option is used, then the blobs are written\n"
" into a hierarchy of directories, using names like 00/00/00,\n"
" 00/00/01, 00/00/02, and so forth. Without the --tree option, all\n"
" files are in the top-level directory with names like 000000, 000001,\n"
" 000002, and so forth.\n"
"\n"
" kvtest stat DBFILE\n"
" kvtest stat DBFILE [options]\n"
"\n"
" Display summary information about DBFILE\n"
" Display summary information about DBFILE. Options:\n"
"\n"
" --vacuum Run VACUUM on the database file\n"
"\n"
" kvtest run DBFILE [options]\n"
"\n"
@@ -90,12 +97,18 @@ static const char zHelp[] =
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --fsync Synchronous file writes\n"
" --integrity-check Run \"PRAGMA integrity_check\" after test\n"
" --max-id N Maximum blob key to use\n"
" --mmap N Mmap as much as N bytes of DBFILE\n"
" --multitrans Each read or write in its own transaction\n"
" --nocheckpoint Omit the checkpoint on WAL mode writes\n"
" --nosync Set \"PRAGMA synchronous=OFF\"\n"
" --jmode MODE Set MODE journal mode prior to starting\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
" --stats Output operating stats before exiting\n"
" --update Do an overwrite test\n"
;
/* Reference resources used */
@@ -111,6 +124,7 @@ static const char zHelp[] =
# include <unistd.h>
#else
/* Provide Windows equivalent for the needed parts of unistd.h */
# include <direct.h>
# include <io.h>
# define R_OK 2
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
@@ -118,6 +132,31 @@ static const char zHelp[] =
# define access _access
#endif
#include <stdint.h>
/*
** 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) ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
#else
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X) ((sqlite3_int64)(intptr_t)(X))
#endif
/*
** Show thqe help text and quit.
@@ -201,13 +240,23 @@ static int integerValue(const char *zArg){
/*
** Check the filesystem object zPath. Determine what it is:
**
** PATH_DIR A directory
** PATH_DIR A single directory holding many files
** PATH_TREE A directory hierarchy with files at the leaves
** PATH_DB An SQLite database
** PATH_NEXIST Does not exist
** PATH_OTHER Something else
**
** PATH_DIR means all of the separate files are grouped together
** into a single directory with names like 000000, 000001, 000002, and
** so forth. PATH_TREE means there is a hierarchy of directories so
** that no single directory has too many entries. The files have names
** like 00/00/00, 00/00/01, 00/00/02 and so forth. The decision between
** PATH_DIR and PATH_TREE is determined by the presence of a subdirectory
** named "00" at the top-level.
*/
#define PATH_DIR 1
#define PATH_DB 2
#define PATH_TREE 2
#define PATH_DB 3
#define PATH_NEXIST 0
#define PATH_OTHER 99
static int pathType(const char *zPath){
@@ -217,7 +266,15 @@ static int pathType(const char *zPath){
memset(&x, 0, sizeof(x));
rc = stat(zPath, &x);
if( rc<0 ) return PATH_OTHER;
if( S_ISDIR(x.st_mode) ) return PATH_DIR;
if( S_ISDIR(x.st_mode) ){
char *zLayer1 = sqlite3_mprintf("%s/00", zPath);
memset(&x, 0, sizeof(x));
rc = stat(zLayer1, &x);
sqlite3_free(zLayer1);
if( rc<0 ) return PATH_DIR;
if( S_ISDIR(x.st_mode) ) return PATH_TREE;
return PATH_DIR;
}
if( (x.st_size%512)==0 ) return PATH_DB;
return PATH_OTHER;
}
@@ -328,6 +385,7 @@ static int statMain(int argc, char **argv){
sqlite3 *db;
char *zSql;
sqlite3_stmt *pStmt;
int doVacuum = 0;
assert( strcmp(argv[1],"stat")==0 );
assert( argc>=3 );
@@ -336,12 +394,21 @@ static int statMain(int argc, char **argv){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
if( strcmp(z, "-vacuum")==0 ){
doVacuum = 1;
continue;
}
fatalError("unknown option: \"%s\"", argv[i]);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
if( doVacuum ){
printf("Vacuuming...."); fflush(stdout);
sqlite3_exec(db, "VACUUM", 0, 0, 0);
printf(" done\n");
}
zSql = sqlite3_mprintf(
"SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
" FROM kv"
@@ -374,39 +441,53 @@ static int statMain(int argc, char **argv){
printf("Page-count: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("PRAGMA freelist_count");
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Freelist-count: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check(10)", -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare integrity check: %s", sqlite3_errmsg(db));
while( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Integrity-check: %s\n", sqlite3_column_text(pStmt, 0));
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
return 0;
}
/*
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
** is written into file X. The number of bytes written is returned. Or
** NULL is returned if something goes wrong, such as being unable to open
** file X for writing.
** 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 writefileFunc(
sqlite3_context *context,
static void rememberFunc(
sqlite3_context *pCtx,
int argc,
sqlite3_value **argv
){
FILE *out;
const char *z;
sqlite3_int64 rc;
const char *zFile;
sqlite3_int64 v;
sqlite3_int64 ptr;
assert( argc==2 );
v = sqlite3_value_int64(argv[0]);
ptr = sqlite3_value_int64(argv[1]);
*(sqlite3_int64*)SQLITE_INT_TO_PTR(ptr) = v;
sqlite3_result_int64(pCtx, v);
}
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
out = fopen(zFile, "wb");
if( out==0 ) return;
z = (const char*)sqlite3_value_blob(argv[1]);
if( z==0 ){
rc = 0;
}else{
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
}
fclose(out);
printf("\r%s ", zFile); fflush(stdout);
sqlite3_result_int64(context, rc);
/*
** Make sure a directory named zDir exists.
*/
static void kvtest_mkdir(const char *zDir){
#if defined(_WIN32)
(void)mkdir(zDir);
#else
(void)mkdir(zDir, 0755);
#endif
}
/*
@@ -416,32 +497,77 @@ static int exportMain(int argc, char **argv){
char *zDb;
char *zDir;
sqlite3 *db;
char *zSql;
sqlite3_stmt *pStmt;
int rc;
char *zErrMsg = 0;
int ePathType;
int nFN;
char *zFN;
char *zTail;
size_t nWrote;
int i;
assert( strcmp(argv[1],"export")==0 );
assert( argc>=3 );
if( argc<4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY [OPTIONS]");
zDb = argv[2];
if( argc!=4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY");
zDir = argv[3];
if( pathType(zDir)!=PATH_DIR ){
kvtest_mkdir(zDir);
for(i=4; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' && z[1]=='-' ) z++;
if( strcmp(z,"-tree")==0 ){
zFN = sqlite3_mprintf("%s/00", zDir);
kvtest_mkdir(zFN);
sqlite3_free(zFN);
continue;
}
fatalError("unknown argument: \"%s\"\n", argv[i]);
}
ePathType = pathType(zDir);
if( ePathType!=PATH_DIR && ePathType!=PATH_TREE ){
fatalError("object \"%s\" is not a directory", zDir);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
zSql = sqlite3_mprintf(
"SELECT writefile(printf('%s/%%06d',k),v) FROM kv;",
zDir
);
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
if( rc ) fatalError("database create failed: %s", zErrMsg);
sqlite3_free(zSql);
rc = sqlite3_prepare_v2(db, "SELECT k, v FROM kv ORDER BY k", -1, &pStmt, 0);
if( rc ){
fatalError("prepare_v2 failed: %s\n", sqlite3_errmsg(db));
}
nFN = (int)strlen(zDir);
zFN = sqlite3_mprintf("%s/00/00/00.extra---------------------", zDir);
if( zFN==0 ){
fatalError("malloc failed\n");
}
zTail = zFN + nFN + 1;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int iKey = sqlite3_column_int(pStmt, 0);
sqlite3_int64 nData = sqlite3_column_bytes(pStmt, 1);
const void *pData = sqlite3_column_blob(pStmt, 1);
FILE *out;
if( ePathType==PATH_DIR ){
sqlite3_snprintf(20, zTail, "%06d", iKey);
}else{
sqlite3_snprintf(20, zTail, "%02d", iKey/10000);
kvtest_mkdir(zFN);
sqlite3_snprintf(20, zTail, "%02d/%02d", iKey/10000, (iKey/100)%100);
kvtest_mkdir(zFN);
sqlite3_snprintf(20, zTail, "%02d/%02d/%02d",
iKey/10000, (iKey/100)%100, iKey%100);
}
out = fopen(zFN, "wb");
nWrote = fwrite(pData, 1, nData, out);
fclose(out);
printf("\r%s ", zTail); fflush(stdout);
if( nWrote!=nData ){
fatalError("Wrote only %d of %d bytes to %s\n",
(int)nWrote, nData, zFN);
}
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
sqlite3_free(zFN);
printf("\n");
return 0;
}
@@ -461,7 +587,7 @@ static int exportMain(int argc, char **argv){
** NULL is returned if any error is encountered. The final value of *pnByte
** is undefined in this case.
*/
static unsigned char *readFile(const char *zName, int *pnByte){
static unsigned char *readFile(const char *zName, sqlite3_int64 *pnByte){
FILE *in; /* FILE from which to read content of zName */
sqlite3_int64 nIn; /* Size of zName in bytes */
size_t nRead; /* Number of bytes actually read */
@@ -479,10 +605,55 @@ static unsigned char *readFile(const char *zName, int *pnByte){
sqlite3_free(pBuf);
return 0;
}
if( pnByte ) *pnByte = (int)nIn;
if( pnByte ) *pnByte = nIn;
return pBuf;
}
/*
** Overwrite a file with randomness. Do not change the size of the
** file.
*/
static void updateFile(const char *zName, sqlite3_int64 *pnByte, int doFsync){
FILE *out; /* FILE from which to read content of zName */
sqlite3_int64 sz; /* Size of zName in bytes */
size_t nWritten; /* Number of bytes actually read */
unsigned char *pBuf; /* Content to store on disk */
const char *zMode = "wb"; /* Mode for fopen() */
sz = fileSize(zName);
if( sz<0 ){
fatalError("No such file: \"%s\"", zName);
}
*pnByte = sz;
if( sz==0 ) return;
pBuf = sqlite3_malloc64( sz );
if( pBuf==0 ){
fatalError("Cannot allocate %lld bytes\n", sz);
}
sqlite3_randomness((int)sz, pBuf);
#if defined(_WIN32)
if( doFsync ) zMode = "wbc";
#endif
out = fopen(zName, zMode);
if( out==0 ){
fatalError("Cannot open \"%s\" for writing\n", zName);
}
nWritten = fwrite(pBuf, 1, (size_t)sz, out);
if( doFsync ){
#if defined(_WIN32)
fflush(out);
#else
fsync(fileno(out));
#endif
}
fclose(out);
if( nWritten!=(size_t)sz ){
fatalError("Wrote only %d of %d bytes to \"%s\"\n",
(int)nWritten, (int)sz, zName);
}
sqlite3_free(pBuf);
}
/*
** Return the current time in milliseconds since the beginning of
** the Julian epoch.
@@ -637,16 +808,22 @@ static int runMain(int argc, char **argv){
int bBlobApi = 0; /* Use the incremental blob I/O API */
int bStats = 0; /* Print stats before exiting */
int eOrder = ORDER_ASC; /* Access order */
int isUpdateTest = 0; /* Do in-place updates rather than reads */
int doIntegrityCk = 0; /* Run PRAGMA integrity_check after the test */
int noSync = 0; /* Disable synchronous mode */
int doFsync = 0; /* Update disk files synchronously */
int doMultiTrans = 0; /* Each operation in its own transaction */
int noCheckpoint = 0; /* Omit the checkpoint in WAL mode */
sqlite3 *db = 0; /* Database connection */
sqlite3_stmt *pStmt = 0; /* Prepared statement for SQL access */
sqlite3_blob *pBlob = 0; /* Handle for incremental Blob I/O */
sqlite3_int64 tmStart; /* Start time */
sqlite3_int64 tmElapsed; /* Elapsed time */
int mmapSize = 0; /* --mmap N argument */
int nData = 0; /* Bytes of data */
sqlite3_int64 nData = 0; /* Bytes of data */
sqlite3_int64 nTotal = 0; /* Total data read */
unsigned char *pData = 0; /* Content of the blob */
int nAlloc = 0; /* Space allocated for pData[] */
sqlite3_int64 nAlloc = 0; /* Space allocated for pData[] */
const char *zJMode = 0; /* Journal mode */
@@ -660,12 +837,42 @@ static int runMain(int argc, char **argv){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
if( strcmp(z, "-asc")==0 ){
eOrder = ORDER_ASC;
continue;
}
if( strcmp(z, "-blob-api")==0 ){
bBlobApi = 1;
continue;
}
if( strcmp(z, "-cache-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iCache = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = integerValue(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-desc")==0 ){
eOrder = ORDER_DESC;
continue;
}
if( strcmp(z, "-fsync")==0 ){
doFsync = 1;
continue;
}
if( strcmp(z, "-integrity-check")==0 ){
doIntegrityCk = 1;
continue;
}
if( strcmp(z, "-jmode")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
zJMode = argv[++i];
continue;
}
if( strcmp(z, "-mmap")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
mmapSize = integerValue(argv[++i]);
@@ -677,44 +884,45 @@ static int runMain(int argc, char **argv){
iMax = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-start")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iKey = integerValue(argv[++i]);
if( iKey<1 ) fatalError("the --start must be positive");
if( strcmp(z, "-multitrans")==0 ){
doMultiTrans = 1;
continue;
}
if( strcmp(z, "-cache-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iCache = integerValue(argv[++i]);
if( strcmp(z, "-nocheckpoint")==0 ){
noCheckpoint = 1;
continue;
}
if( strcmp(z, "-jmode")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
zJMode = argv[++i];
if( strcmp(z, "-nosync")==0 ){
noSync = 1;
continue;
}
if( strcmp(z, "-random")==0 ){
eOrder = ORDER_RANDOM;
continue;
}
if( strcmp(z, "-asc")==0 ){
eOrder = ORDER_ASC;
continue;
}
if( strcmp(z, "-desc")==0 ){
eOrder = ORDER_DESC;
continue;
}
if( strcmp(z, "-blob-api")==0 ){
bBlobApi = 1;
if( strcmp(z, "-start")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iKey = integerValue(argv[++i]);
if( iKey<1 ) fatalError("the --start must be positive");
continue;
}
if( strcmp(z, "-stats")==0 ){
bStats = 1;
continue;
}
if( strcmp(z, "-update")==0 ){
isUpdateTest = 1;
continue;
}
fatalError("unknown option: \"%s\"", argv[i]);
}
if( eType==PATH_DB ){
/* Recover any prior crashes prior to starting the timer */
sqlite3_open(zDb, &db);
sqlite3_exec(db, "SELECT rowid FROM sqlite_master LIMIT 1", 0, 0, 0);
sqlite3_close(db);
db = 0;
}
tmStart = timeOfDay();
if( eType==PATH_DB ){
char *zSql;
@@ -724,9 +932,13 @@ static int runMain(int argc, char **argv){
}
zSql = sqlite3_mprintf("PRAGMA mmap_size=%d", mmapSize);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( noSync ){
sqlite3_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
}
pStmt = 0;
sqlite3_prepare_v2(db, "PRAGMA page_size", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -745,6 +957,9 @@ static int runMain(int argc, char **argv){
zSql = sqlite3_mprintf("PRAGMA journal_mode=%Q", zJMode);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( noCheckpoint ){
sqlite3_exec(db, "PRAGMA wal_autocheckpoint=0", 0, 0, 0);
}
}
sqlite3_prepare_v2(db, "PRAGMA journal_mode", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -761,22 +976,32 @@ static int runMain(int argc, char **argv){
sqlite3_finalize(pStmt);
}
pStmt = 0;
sqlite3_exec(db, "BEGIN", 0, 0, 0);
if( !doMultiTrans ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
if( iMax<=0 ) iMax = 1000;
for(i=0; i<nCount; i++){
if( eType==PATH_DIR ){
/* CASE 1: Reading blobs out of separate files */
if( eType==PATH_DIR || eType==PATH_TREE ){
/* CASE 1: Reading or writing blobs out of separate files */
char *zKey;
zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
if( eType==PATH_DIR ){
zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
}else{
zKey = sqlite3_mprintf("%s/%02d/%02d/%02d", zDb, iKey/10000,
(iKey/100)%100, iKey%100);
}
nData = 0;
pData = readFile(zKey, &nData);
if( isUpdateTest ){
updateFile(zKey, &nData, doFsync);
}else{
pData = readFile(zKey, &nData);
sqlite3_free(pData);
}
sqlite3_free(zKey);
sqlite3_free(pData);
}else if( bBlobApi ){
/* CASE 2: Reading from database using the incremental BLOB I/O API */
if( pBlob==0 ){
rc = sqlite3_blob_open(db, "main", "kv", "v", iKey, 0, &pBlob);
rc = sqlite3_blob_open(db, "main", "kv", "v", iKey,
isUpdateTest, &pBlob);
if( rc ){
fatalError("could not open sqlite3_blob handle: %s",
sqlite3_errmsg(db));
@@ -788,20 +1013,39 @@ static int runMain(int argc, char **argv){
nData = sqlite3_blob_bytes(pBlob);
if( nAlloc<nData+1 ){
nAlloc = nData+100;
pData = sqlite3_realloc(pData, nAlloc);
pData = sqlite3_realloc64(pData, nAlloc);
}
if( pData==0 ) fatalError("cannot allocate %d bytes", nData+1);
rc = sqlite3_blob_read(pBlob, pData, nData, 0);
if( rc!=SQLITE_OK ){
fatalError("could not read the blob at %d: %s", iKey,
sqlite3_errmsg(db));
if( isUpdateTest ){
sqlite3_randomness((int)nData, pData);
rc = sqlite3_blob_write(pBlob, pData, (int)nData, 0);
if( rc!=SQLITE_OK ){
fatalError("could not write the blob at %d: %s", iKey,
sqlite3_errmsg(db));
}
}else{
rc = sqlite3_blob_read(pBlob, pData, (int)nData, 0);
if( rc!=SQLITE_OK ){
fatalError("could not read the blob at %d: %s", iKey,
sqlite3_errmsg(db));
}
}
}
}else{
/* CASE 3: Reading from database using SQL */
if( pStmt==0 ){
rc = sqlite3_prepare_v2(db,
"SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
if( isUpdateTest ){
sqlite3_create_function(db, "remember", 2, SQLITE_UTF8, 0,
rememberFunc, 0, 0);
rc = sqlite3_prepare_v2(db,
"UPDATE kv SET v=randomblob(remember(length(v),?2))"
" WHERE k=?1", -1, &pStmt, 0);
sqlite3_bind_int64(pStmt, 2, SQLITE_PTR_TO_INT(&nData));
}else{
rc = sqlite3_prepare_v2(db,
"SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
}
if( rc ){
fatalError("cannot prepare query: %s", sqlite3_errmsg(db));
}
@@ -809,12 +1053,11 @@ static int runMain(int argc, char **argv){
sqlite3_reset(pStmt);
}
sqlite3_bind_int(pStmt, 1, iKey);
nData = 0;
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
nData = sqlite3_column_bytes(pStmt, 0);
pData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
}else{
nData = 0;
}
}
if( eOrder==ORDER_ASC ){
@@ -835,13 +1078,33 @@ static int runMain(int argc, char **argv){
if( bStats ){
display_stats(db, 0);
}
if( db ) sqlite3_close(db);
if( db ){
if( !doMultiTrans ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
if( !noCheckpoint ){
sqlite3_close(db);
db = 0;
}
}
tmElapsed = timeOfDay() - tmStart;
if( db && noCheckpoint ){
sqlite3_close(db);
db = 0;
}
if( nExtra ){
printf("%d cycles due to %d misses\n", nCount, nExtra);
}
if( eType==PATH_DB ){
printf("SQLite version: %s\n", sqlite3_libversion());
if( doIntegrityCk ){
sqlite3_open(zDb, &db);
sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pStmt, 0);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("integrity-check: %s\n", sqlite3_column_text(pStmt, 0));
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
db = 0;
}
}
printf("--count %d --max-id %d", nCount-nExtra, iMax);
switch( eOrder ){
@@ -852,11 +1115,17 @@ static int runMain(int argc, char **argv){
if( eType==PATH_DB ){
printf("--cache-size %d --jmode %s\n", iCache, zJMode);
printf("--mmap %d%s\n", mmapSize, bBlobApi ? " --blob-api" : "");
if( noSync ) printf("--nosync\n");
}
if( iPagesize ) printf("Database page size: %d\n", iPagesize);
printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
if( isUpdateTest ){
printf("Microseconds per BLOB write: %.3f\n", tmElapsed*1000.0/nCount);
printf("Content write rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
}else{
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
}
return 0;
}
+2 -2
View File
@@ -179,7 +179,7 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_LOCKING_STYLE=1
}
"Apple" {
-O1 # Avoid a compiler bug in gcc 4.2.1 build 5658
-Os
-DHAVE_GMTIME_R=1
-DHAVE_ISNAN=1
-DHAVE_LOCALTIME_R=1
@@ -1036,7 +1036,7 @@ proc main {argv} {
regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
if {$debug_idx < 0} {
incr NTEST
append config_options " -DSQLITE_DEBUG=1"
append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1"
add_test_suite all "${zConfig}_debug" $xtarget $config_options
} else {
incr NTEST
+22 -18
View File
@@ -216,24 +216,28 @@ if {$tcl_platform(platform)!="windows" || \
} {}
set pwd [pwd]
do_execsql_test 3.5 {
SELECT path, size FROM fstree WHERE path GLOB $pwd || '/subdir/*' ORDER BY 1
} [list \
"$pwd/subdir/x1.txt" 143 \
"$pwd/subdir/x2.txt" 153 \
]
do_execsql_test 3.6 {
SELECT path, size FROM fstree WHERE path LIKE $pwd || '/subdir/%' ORDER BY 1
} [list \
"$pwd/subdir/x1.txt" 143 \
"$pwd/subdir/x2.txt" 153 \
]
do_execsql_test 3.7 {
SELECT sum(size) FROM fstree WHERE path LIKE $pwd || '/subdir/%'
} 296
do_execsql_test 3.8 {
SELECT size FROM fstree WHERE path = $pwd || '/subdir/x1.txt'
} 143
if {![string match {*[_%]*} $pwd]} {
do_execsql_test 3.5 {
SELECT path, size FROM fstree
WHERE path GLOB $pwd || '/subdir/*' ORDER BY 1
} [list \
"$pwd/subdir/x1.txt" 143 \
"$pwd/subdir/x2.txt" 153 \
]
do_execsql_test 3.6 {
SELECT path, size FROM fstree
WHERE path LIKE $pwd || '/subdir/%' ORDER BY 1
} [list \
"$pwd/subdir/x1.txt" 143 \
"$pwd/subdir/x2.txt" 153 \
]
do_execsql_test 3.7 {
SELECT sum(size) FROM fstree WHERE path LIKE $pwd || '/subdir/%'
} 296
do_execsql_test 3.8 {
SELECT size FROM fstree WHERE path = $pwd || '/subdir/x1.txt'
} 143
}
}
+14
View File
@@ -990,5 +990,19 @@ do_execsql_test 18.2 {
SELECT 1 FROM xyz;
} 1
# EXPLAIN QUERY PLAN on a self-join of a CTE
#
do_execsql_test 19.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x);
EXPLAIN QUERY PLAN
WITH
x1(a) AS (values(100))
INSERT INTO t1(x)
SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
SELECT * FROM t1;
} {0 0 0 {SCAN SUBQUERY 1} 0 1 1 {SCAN SUBQUERY 1}}
finish_test
-1
View File
@@ -51,7 +51,6 @@ cp sqlite3.h $TMPSPACE
cp sqlite3ext.h $TMPSPACE
cp $TOP/sqlite3.1 $TMPSPACE
cp $TOP/sqlite3.pc.in $TMPSPACE
cp $TOP/src/msvc.h $TMPSPACE
cp $TOP/src/shell.c $TMPSPACE
cp $TOP/src/sqlite3.rc $TMPSPACE
cp $TOP/tool/Replace.cs $TMPSPACE
+311
View File
@@ -0,0 +1,311 @@
#!/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)]
}
+1 -1
View File
@@ -282,10 +282,10 @@ proc copy_file {filename} {
# inlining opportunities.
#
foreach file {
ctime.c
sqliteInt.h
global.c
ctime.c
status.c
date.c
os.c
+17
View File
@@ -424,6 +424,7 @@ proc subreport {title where showFrag} {
# 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}]
@@ -433,6 +434,10 @@ proc subreport {title where showFrag} {
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 "
@@ -460,9 +465,11 @@ proc subreport {title where showFrag} {
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
}
@@ -757,6 +764,16 @@ Bytes of payload
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
+1 -1
View File
@@ -1667,7 +1667,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
putc('T', out);
putsVarint(out, (sqlite3_uint64)nCol);
for(i=0; i<nCol; i++) putc(aiFlg[i]!=0, out);
for(i=0; i<nCol; i++) putc(aiFlg[i], out);
fwrite(zTab, 1, strlen(zTab), out);
putc(0, out);