Compare commits

...

77 Commits

Author SHA1 Message Date
dan c07a705430 Ensure each ALTER TABLE statement makes just a single SQLITE_ALTER_TABLE call
to the authorizer function.

FossilOrigin-Name: dac285474a4b09cb004b797567d050952cb12b952e5688bc4a6e4599faa21565
2018-10-06 14:33:41 +00:00
dan 07052d5535 Add test cases and assert() statements to ensure that the authorizer is being
called as expected from within ALTER TABLE.

FossilOrigin-Name: ff10d2c7de430c88167b1e6e4f5307eee5d69e22c8d24b2ef4fcb3aea25a92e1
2018-10-06 13:46:22 +00:00
drh bebf54438e Changes to geopoly to silience false-positive warnings coming out of clang.
FossilOrigin-Name: 11d9015f31d1ea2fd27174d4ceea08a145fdbb92a175bec0aae4b90f991694bc
2018-10-05 15:10:00 +00:00
drh f470c37a2b Add an ALWAYS on an unreachable branch in the ALTER TABLE logic.
FossilOrigin-Name: ebcd4523171f0988ff08e2bf36fb8a0caa40efe7ac7556b4eb206784969b03e4
2018-10-03 18:05:36 +00:00
dan 60bdcf5e56 Change a type in shell.c.in from "int" to "sqlite3_int64" in order to
avoid a compiler warning and possible integer overflow.

FossilOrigin-Name: bf0a6634cd8f9457992b8da522a6775a304156815bf6f4f64f96016356baa870
2018-10-03 11:13:30 +00:00
drh 9b7e8e10f2 Add an additional assert() verifying mutex invariants on the
unixShmSystemLock() routine in the unix VFS.

FossilOrigin-Name: cb1511065d5348c5b3015dc9d690fc5d519a14ffdfa7164bb552a4fa686ad142
2018-10-02 20:16:41 +00:00
drh 8820c8d3ee Additional field name changes and commit fixes associated with shared-memory
locking in the unix VFS, to improve maintainability.  No logic changes.

FossilOrigin-Name: 9280774a4bbc665d70f346d258768cbcca3e0e77791473aecfd7d0e87810ab31
2018-10-02 19:58:08 +00:00
drh 24efa5444d Fix comments and refactor some names associated with shared-memory locking
in the Unix VFS.  No logical changes.

FossilOrigin-Name: 3e9f1635271c92dce5324728b4ee1cc1a1856ec3c60b1b512a652c21e010e63e
2018-10-02 19:36:40 +00:00
drh ba160891de Add the "PRAGMA table_xinfo" command that works like table_info but also
shows hidden columns in virtual tables and adds the "hidden" boolean column.

FossilOrigin-Name: defa0515b8fd50ed9be699542f8c6695dd4a60c02f310665db6657ec5b6b67d0
2018-10-01 21:41:15 +00:00
drh bfbf7d9daa Test case for PRAGMA table_xinfo.
FossilOrigin-Name: 7694b9bc3003db6ba0b41c5029c8f7b84c07724e7a518e835e98b3c46e4ea227
2018-10-01 21:36:38 +00:00
drh bdc9744f60 Change the name of the pragma to PRAGMA table_xinfo. Improve the
mkpragmatab.tcl script to reuse column names where appropriate.

FossilOrigin-Name: 2fdd068987e59b979045d71ae64e700600ef07e54ae340f30c2064e5dcccb8ea
2018-10-01 21:26:30 +00:00
drh d7dc0a36cc Add the extra "hidden" column to the end of the PRAGMA table_vinfo output.
FossilOrigin-Name: cf1b76135f511530dcc7b82f78c952bf97ebcddb40be06f713f9f2326915fabe
2018-10-01 18:28:42 +00:00
dan 49f84ce1cd Speed up xAccess() calls made on an RBU VFS when there are lots of open
connections.

FossilOrigin-Name: 310b4b65b8c8ee080760c7efb4c7e20244c6063a5dba37a4f40490105aafd29f
2018-10-01 17:33:35 +00:00
drh 5612ef1057 Bring the PRAGMA table_vinfo statement up to date with trunk.
FossilOrigin-Name: 6f606f99231f88ae5ff719d0ce21afc4b844490102c27ac20aa606baaf78d8d6
2018-10-01 17:15:17 +00:00
drh 44d068532e Fix a potential crash that can occur while reading an index from a corrupt
database file.  The corruption is a record-header-size that is larger than
0x7fffffff.  Problem detected by OSSFuzz against GDAL and reported to us 
(with a suggested fix) by Even Rouault.  The test case is in TH3.

FossilOrigin-Name: 8ac2cdda68f92b0352bc7f0b4be5fca4bb58565ca65055fb34153cc284ed6922
2018-10-01 13:54:30 +00:00
dan 5351e884aa Fix a problem with ALTER TABLE commands when the schema features an INSTEAD of
trigger that uses NEW.* or OLD.*.

FossilOrigin-Name: c52f457e56eb9d573eb67093731eb231aaf6fd6dbdc397e6f948b82736fbe3ab
2018-10-01 07:04:12 +00:00
drh 15fc988ce0 Add the PRAGMA table_vinfo command (with an extra "v" before "info") that
works like PRAGMA table_info (without the "v") except that it also shows
hidden columns on virtual tables.

FossilOrigin-Name: 8bcd1a59560aa7ea73e6529e5c14ece8ac09bf7e99efdcfd388fead39846b6bf
2018-09-29 19:38:42 +00:00
drh ca9a5faf70 Fix test cases so that they work with ICU.
FossilOrigin-Name: d04b2013b5436430ebbf7053d637fd89c1b15affcb42787dcf1cf5ffc3ae54e2
2018-09-28 23:53:24 +00:00
dan f8248c42f9 Have sqlite3changegroup_output_strm() call its output function more regularly.
FossilOrigin-Name: 8467c31aa0bf24e597f680748460a99f425c49f5ab741c3574c339aa56857146
2018-09-28 20:46:41 +00:00
drh 09b523c99b Fix a bug in the sqlite_memstat virtual table that was causing it to report
the amount of memory used as zero bytes.

FossilOrigin-Name: 8a758a872175b0c74e631c231240c5c733fbec708d0cff23eb9c4025e4a800ec
2018-09-28 18:51:18 +00:00
drh 60afcb80ee Add the geopoly_regular(X,Y,R,N) function to the geopoly extension.
FossilOrigin-Name: 4505bbae58357eacab262b642b2a56d6dd380de72faceb5bbfd042eb94a12c06
2018-09-28 14:01:17 +00:00
drh 601c8f2829 Make most geopoly functions pure.
FossilOrigin-Name: 944e167a98e995c5750c1fcd44df857d6b10c1cbb91731fad2849415c42b2cfc
2018-09-28 13:18:24 +00:00
drh b2d83494d3 Rig geopoly to use sqlite3AtoF() if it is available, as that routine is much
faster than atof().

FossilOrigin-Name: 470c6c07d0eb70806ac257c1c8ad877e041bbc14ff9a5c490edb51b2956ae726
2018-09-28 00:16:57 +00:00
drh 17e65ae4c0 Small performance optimization in the JSON parser of Geopoly.
FossilOrigin-Name: fb520e71035258d5490be33ee28575df2caefa5d5a301c8bbdf1471551c96282
2018-09-27 23:57:45 +00:00
drh 50db3e8d51 Enhance the GeoPOLY extension so that it always stores its polygons in the
binary format, which is faster and more compact.

FossilOrigin-Name: dc35f7b1754a78fa0d70c92754de07bb3c28d0d31cb929ee8a3a47ac4f3d446e
2018-09-27 20:37:52 +00:00
drh 09d00b2f4f Ensure that the OP_VColumn opcode does set sqlite3_vtab_nochange() unless
the OPFLAG_NOCHNG bit is set in P5.  Fix for ticket
[69d642332d25aa3b7315a6d385]

FossilOrigin-Name: 322ab1fc613f616e9f07dc94ef74a29572a21cc476d88e97b4ce865500a47b62
2018-09-27 20:20:01 +00:00
dan 0efb6f5135 Another minor tweak to memstat.c so that it may be built against older versions
of SQLite.

FossilOrigin-Name: 4c1fed60b9b35ac2f5d2f2533b54db429d72bdbc0aad0dd5af52ff851789d4ae
2018-09-27 17:33:06 +00:00
drh 6dd5f07d3d Modify the memstat virtual table so that it works with SQLite version 3.9.2.
FossilOrigin-Name: 7171d8ae6b1e7c97b0cf06bcca2262674c9ce557c85666b4b77c16cbac508502
2018-09-27 17:15:21 +00:00
drh 982c1fac2b Add the sqlite_memstat extension - an eponymous virtual table that shows
memory usages statistics for SQLite.

FossilOrigin-Name: 954ef61f6a02532e72c815208ec839310f1e00d69e0003cc6f5426f0559229d1
2018-09-27 17:03:03 +00:00
drh d7134fe0c1 Enhancements to sqlite_memstat:
(1) Add an extra "schema" column to show the schema name for ZIPVFS stats.
(2) Only show ZIPVFS stats to schema that use ZIPVFS
(3) Put a NULL in unused columns of the output.

FossilOrigin-Name: 9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12
2018-09-27 16:57:42 +00:00
drh 7c5577acdc Add initial ZIPVFS support for the "main" database to the sqlite_memstat
virtual table.

FossilOrigin-Name: 9cd27350b0f62debfe3238c57c3ab51079699142e82c05a7ec8460a8429f55f2
2018-09-27 15:45:03 +00:00
drh d7fda6cfc5 Initial prototype of a eponymous virtual table that accesses sqlite3_status64()
and sqlite3_db_status().

FossilOrigin-Name: 0b44e1f68e0c8349367e3f929d4734c3df96338ec8d6fb652565bf894e8b8343
2018-09-27 15:21:13 +00:00
dan 6afa35c985 Disallow the use of window functions in the recursive part of a recursive CTE.
FossilOrigin-Name: 7fc2994434c7d9ed29c96a69c07e8eb4e97be776473c170c63f9a1bbaa09fa68
2018-09-27 12:14:15 +00:00
mistachkin 1c06b47864 Minor simplification: In OP_ParseSchema, read the p1 register once.
FossilOrigin-Name: bd250533a06e4a11c1f548c3de66b8562fc627383848570d7d030cf132fd336f
2018-09-27 00:04:31 +00:00
drh eb7f2a0fc5 Further improvements to the ".help" command in the CLI.
FossilOrigin-Name: edc3d18ecbda32d6a55de76ee7335342425c57d917e9b48814a7301a012263b2
2018-09-26 18:02:32 +00:00
drh 98aa2abc45 Begin revamping the ".help" command in the command-line shell so that it
can accept an argument and will do a search for commands that match that
argument.

FossilOrigin-Name: 209afb8d06466536863b89a8acb9a1a18477a06331d8cce95fc6380e1666b6f5
2018-09-26 16:53:51 +00:00
dan 2e5e0e10f2 Tweak spellfix.c so that if SQLITE_SPELLFIX_5BYTE_MAPPINGS is defined at
compile time the Transliteration structure has space for 5 byte (instead of 4
byte) mappings.

FossilOrigin-Name: cbaf5b6c1b07b29b2c83fa01618de856d81cc1174769cb9770cb5c894cc87ace
2018-09-26 16:05:07 +00:00
drh 6b26a7b950 Fix typos in the header comment for the sha1 and sha3 hash extensions
in the ext/misc folder.

FossilOrigin-Name: 4ed9d83a0b14a22b3ecf25785b03b5a824d260e01a608aea85231df9b816421d
2018-09-26 03:43:42 +00:00
dan 6705584a5b Fix a problem in releasetest.tcl causing configuration "Fast-One" to fail.
FossilOrigin-Name: 42e04fefbc241dd33f12abd66344a87720ae4cda6d82f2882217b3cb71be8733
2018-09-25 13:51:31 +00:00
drh 5398806889 Slightly smaller and faster alternative to [507d892c3a40a0bacbd47] that
fixes a problem with views that use window function as part of complex
expressions.

FossilOrigin-Name: d7c816ae15f05f21b9b213161e1044aaefc56f17e7bc4b7b551a9e04efc05855
2018-09-24 15:39:30 +00:00
dan 2fae150402 Fix a problem with views that use window functions as part of complex expressions.
FossilOrigin-Name: 507d892c3a40a0bacbd47ed3c4fe2d8925a82716ae08da8401750a42782ba454
2018-09-24 14:51:59 +00:00
drh 6314eeaeb3 Allow a writable virtual table to have a schema with an INTEGER PRIMARY KEY
and WITHOUT ROWID.  This fixes ticket
[f25d5ceebe1d710ff61a571e395356869d8272ef].

FossilOrigin-Name: 5a38d9281b4ad63b853efa5cdd5ad4a64b19dfaf8250ef8e0e186684df1211ea
2018-09-24 14:10:55 +00:00
drh 6fb5d358a8 Use compile-time options SQLITE_QUERY_PLANNER_LIMIT and
SQLITE_QUERY_PLANNER_LIMIT_INCR to control the value for
WhereLoopBuilder.iPlanLimit, rather than embedding magic numbers in the
code.

FossilOrigin-Name: 903e501894b2a5dd7055b5154d74d4a47a619f76e66485a4d62b6259f10723d6
2018-09-24 12:37:01 +00:00
drh 7ebb605c0a Increase the initial value of WhereLoopBuilder.iPlanLimit to 20K. Issue
a warning if the iPlanLimit reaches zero.

FossilOrigin-Name: 3dd35f51187574f47f860405309877cdbf9dc5710703dfd98cf98073b771140c
2018-09-24 10:47:33 +00:00
drh f8937f9034 Fix a faulty assert() in the validation logic for the LEFT JOIN strength
reduction optimization.  Problem found by OSSFuzz.

FossilOrigin-Name: 2fd62fccd13e326dbd7dd730112542c6faa56e466bf4f7b8e22ced543031280c
2018-09-23 02:01:42 +00:00
drh 2c3ba94969 Enhance WhereLoopBuilder.iPlanLimit to handle a case involving the OR
optimization discovered overnight by OSSFuzz.

FossilOrigin-Name: 7b59930a1d7b664b54d5a2bc9fa385925b5f4c8f34bf401c798307e3e2dae2c6
2018-09-22 15:05:32 +00:00
mistachkin 7cc5595a01 Fix harmless compiler warning when compiled with SQLITE_OMIT_AUTHORIZATION.
FossilOrigin-Name: 50f2fa19532e0f849d61d9e2a97427cfbf64cfb787ca481ef8c860d0f24f6cfe
2018-09-21 23:41:18 +00:00
drh 5eaebf3a63 Comment typo fixed. No code changes.
FossilOrigin-Name: 7e68cdab20f50cf776b92b2138bb4aba7cb070f2bd855dd4cbbf46d447f2dc88
2018-09-21 19:06:09 +00:00
drh fc9098a45e Put a limit counter on the query planner that restricts the number of
index+constraint options that can be considered for each table in a join.
This prevents certain pathological queries from taking up too much time
in the query planner.

FossilOrigin-Name: 8690b5a0cc08eeb175230de45d4ca9b9f7b9b22aeebea70b8b7151f10b130969
2018-09-21 18:43:51 +00:00
drh 0d7f0ccd96 Optimization to the OP_MakeRecord opcode makes speed-check.sh run about
1.1 million cycles faster, and results in a slightly smaller library.

FossilOrigin-Name: d10e63629183f6daf0c263cd4dae052a3786c8c1480b3b6a73124b3315e41951
2018-09-21 13:07:14 +00:00
drh 5db90714aa Minor code simplification.
FossilOrigin-Name: 22ae8a52dd2fb744f467c7dccf1d7fe7c7cef0e1dcc897dd492f897e84c9facb
2018-09-20 20:43:28 +00:00
drh 42eb070729 Add the "PRAGMA legacy_alter_table=ON" command to enable the pre-3.25.0
behavior of ALTER TABLE that does not modify the bodies of triggers or
views or the WHERE clause of a partial index.  Enable the legacy behavior
by default when running the xRename method of virtual tables.

FossilOrigin-Name: 7edd26ed27ed1e7eab603058f7d55f2eac45e7bd1908bfa5f32293611883b157
2018-09-20 20:15:02 +00:00
drh eda079cd2c Combine the Expr.pTab and Expr.pWin fields into a union named "y". Add a new
EP_WinFunc property that is only true if Expr.y.pWin is a valid pointer.
This reduces the size of the Expr object by 8 bytes, reduces the overall
amount of code, and shaves over 1 million cycles off of the speed test.

FossilOrigin-Name: ad130bb86e74e6ce165fdbdce3a19699510f0e62071c1c7923b5a4538d888c7c
2018-09-20 19:02:15 +00:00
dan 34566c4434 By default, make all "ALTER TABLE RENAME" statements executed within a virtual
table xRename() method exhibit the legacy behaviour.

FossilOrigin-Name: 71947337e98b90debb13b390119bc2a6b39dd41535151b836071ee327a31e45d
2018-09-20 17:21:21 +00:00
dan 674b894269 Add a PRAGMA that restores the legacy ALTER TABLE RENAME TO behaviour.
FossilOrigin-Name: 5acad2e92c11c209bedc6ac8a709595e8070eed028ffc82af61499e5ceaa5e2b
2018-09-20 08:28:01 +00:00
drh 504eba5f46 A minor code simplification, saved in a branch for future reference.
FossilOrigin-Name: 5e458f4a92743effb9a3d3249767424fed8b444a05ca136c4a55d60c4d70c2cc
2018-09-19 18:17:46 +00:00
dan 85c6892aa4 Fix a compilation issue in the "userauth" extension. Also fix a few test
script errors that occur with SQLITE_USER_AUTHENTICATION=1 builds.

FossilOrigin-Name: 221f3f572ed49d7af69a2e7c88741fa5206ea33ca59ee791eac7698bdd11ca4d
2018-09-19 17:09:09 +00:00
drh c6727c8342 Fix the "sqlite3" command in the TCL interface so that it correctly returns
an error if invoked with no arguments.

FossilOrigin-Name: 2034fa8089676132b5e2f71bdebf1af9ca141da2e173920c6e84fb974ab0f022
2018-09-19 15:08:21 +00:00
dan 16f39b6e5d Fix a problem building on Android with SQLITE_ENABLE_BATCH_ATOMIC_WRITE set.
FossilOrigin-Name: e41e50fe7430cb79f67369fe81ac9938665bfc5db59c4faaf429ceb8ca03f584
2018-09-18 19:40:18 +00:00
dan c4b1e5e758 Avoid incrementing the SQLITE_LOOKASIDE_MISS_SIZE stat before sqlite3_open()
returns. Fix test script problem in lookaside.test.

FossilOrigin-Name: e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634
2018-09-18 17:50:34 +00:00
dan 253c6ee1bf Enhance tester.tcl so that when "--malloctrace=1" is specified, the test
generates self-contained Tcl scripts that present GUIs instead of *.sql files
that require a separate program to interpret.

FossilOrigin-Name: de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc
2018-09-18 17:00:06 +00:00
dan b1e1a0fd2d Minor improvements to the permutations.test script. Most notably, a command
like "permutations.test alter%" now runs all test scripts with names that
match the LIKE pattern "alter%". Or, say, "permutations wal alter%" to run all
alter% tests in wal mode.

FossilOrigin-Name: 3e1a2f6614eacb65e1dffe64c6292c809fc5808be2d9d7d103cfc57d7b32fcd9
2018-09-18 16:06:42 +00:00
drh 40b4e7a692 Further optimizations to the UPDATE logic to avoid making changes to partial
indexes if none of the columns mentioned in the WHERE clause are modified by
the UPDATE.

FossilOrigin-Name: d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf
2018-09-17 20:47:38 +00:00
drh d4cb09e3d2 Disable the ORDER BY LIMIT optimization in queries using window functions.
This fixes a problem that was introduced by check-in [206720129ed2fa8875a286]
which attempted to fix ticket [9936b2fa443fec03ff25f9].  This changes is
a fix for the follow-in tocket [510cde277783b5fb5de628].

FossilOrigin-Name: c6c9585f294710829ca24b64d70a36fd9f409261dd0661367c6c4198cdbc4c81
2018-09-17 15:19:13 +00:00
drh 051a1022ff Fix a false-positive in the post-ALTER-TABLE schema verification logic that
prevents ALTER TABLE from working if the table being altered has a trigger
that references any column of a virtual table. Ticket [b41031ea2b537237].

FossilOrigin-Name: 84105ea4af98bd8bddbdf9dc6674bdf73c110c0685afe868ce9681da110144d7
2018-09-17 14:13:48 +00:00
drh e597c47545 Restore an assert() that was present on trunk.
FossilOrigin-Name: a7b572ca7867a95f49888dc95c0dc6d726afa9fea26283be147ba422639d1307
2018-09-17 13:55:18 +00:00
dan de79e094bc Minor modification to the fix on this branch to avoid adding extra conditional
compilation macros.

FossilOrigin-Name: 4d8be404dab265b51e5a6a95e83be85c22512e19a437191690c7d845c87ff259
2018-09-17 13:38:45 +00:00
mistachkin 746127e734 Fix missing space in 'configure.ac' reported on the mailing list.
FossilOrigin-Name: 96b00a3cd2273dd3baa8e5b7a441458b142d4d2daabc679e4fcb5ab706674e76
2018-09-17 12:49:21 +00:00
dan 0208337c16 Add extra test for the fix on this branch. Also fix a
pointer-compare-after-free problem that occurs in similar cases.

FossilOrigin-Name: 1856ea63b3186c2c8fa716ffe01c731397bdbbc3fbb56dc72ad0686cb7f152ca
2018-09-17 08:27:23 +00:00
drh e68fe9665a Add assert()s to the new code in the previous check-in.
FossilOrigin-Name: b12f23a5c484cab3654721299ea0f05230eef6b14012b557f3bf2592fac0f00e
2018-09-17 00:15:21 +00:00
drh 95f78d98b9 First proposed fix for the ALTER TABLE problem described by ticket
[b41031ea2b5372378cb3d2d]

FossilOrigin-Name: 05a9d129254e01a5f6b5e4033c105190eae386575a94b020ef3e0cbd30bbf056
2018-09-16 23:27:37 +00:00
drh 86f3492650 Remove an unreachable branch from the index-on-expression optimization.
FossilOrigin-Name: 2df2cf4f179dd88fb2530dfd338f344ac48dd052ef954dc95a136884523f7aee
2018-09-16 18:23:48 +00:00
drh 6557a07ca8 Fix a memory leak in the explain extension.
FossilOrigin-Name: d0c92b047a5355726aea87f38038e5bda3adf6137492919be94bd29bb847eddb
2018-09-16 16:34:31 +00:00
drh 9b84f03556 Add the new "explain" virtual table in ext/misc. Use this virtual table
for additional test cases for the optimization that avoids updating indexes
on expressions when none of the columns changed by the UPDATE are in the
expression.

FossilOrigin-Name: 2404304cc15eaeee2744cf3c8f9cac0a544631c4f1060c5a17a78b43ca86edf0
2018-09-16 16:18:01 +00:00
drh 2b7cdf6f6b Improved presentation on the new code that prevents unnecessary writes to
expressions on indexes during an UPDATE when the expression does not reference
any of the columns that are changing.

FossilOrigin-Name: c9f045295c4577752b0847ff2027b44661e6cb15bb08b942ccb3a0ef396f3dec
2018-09-16 15:01:25 +00:00
drh 6a9afa918b Increase the version number to 3.26.0 as we start the next development cycle.
FossilOrigin-Name: 885f0f8252aae776a86c64bcc7da582f0ed58f2caae8ebff810a83ca339da820
2018-09-15 21:43:14 +00:00
drh e9816d82a7 Optimization: when doing an UPDATE on a table with indexes on an expression,
do not update the expression indexes if they do not refer to any of the
columns of the table being updated.

FossilOrigin-Name: a71b101635ed28a4c99734dabb20bd65ef1018c1d63ac143b7321cdb0fafa5d7
2018-09-15 21:38:48 +00:00
85 changed files with 3161 additions and 771 deletions
+1
View File
@@ -437,6 +437,7 @@ TESTSRC += \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/eval.c \
$(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/fts5/fts5_tcl.c \
+1
View File
@@ -1515,6 +1515,7 @@ TESTEXT = \
$(TOP)\ext\misc\closure.c \
$(TOP)\ext\misc\csv.c \
$(TOP)\ext\misc\eval.c \
$(TOP)\ext\misc\explain.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\fuzzer.c \
$(TOP)\ext\fts5\fts5_tcl.c \
+1 -1
View File
@@ -1 +1 @@
3.25.0
3.26.0
+1 -1
View File
@@ -172,7 +172,7 @@ AC_ARG_ENABLE(session, [AS_HELP_STRING(
[--enable-session], [enable the session extension [default=no]])],
[], [])
if test x"$enable_session" = "xyes"; then
BUILD_CFLAGS="$BUILD_CFLAGS-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#-----------------------------------------------------------------------
Vendored
+9 -9
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.25.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.26.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.25.0'
PACKAGE_STRING='sqlite 3.25.0'
PACKAGE_VERSION='3.26.0'
PACKAGE_STRING='sqlite 3.26.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1466,7 +1466,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.25.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.25.0:";;
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
esac
cat <<\_ACEOF
@@ -1657,7 +1657,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.25.0
sqlite configure 3.26.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2076,7 +2076,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.25.0, which was
It was created by sqlite $as_me 3.26.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12232,7 +12232,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.25.0, which was
This file was extended by sqlite $as_me 3.26.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12298,7 +12298,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.25.0
sqlite config.status 3.26.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+309
View File
@@ -0,0 +1,309 @@
/*
** 2018-09-16
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file demonstrates an eponymous virtual table that returns the
** EXPLAIN output from an SQL statement.
**
** Usage example:
**
** .load ./explain
** SELECT p2 FROM explain('SELECT * FROM sqlite_master')
** WHERE opcode='OpenRead';
*/
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* explain_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a explain virtual table
*/
typedef struct explain_vtab explain_vtab;
struct explain_vtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this explain vtab */
};
/* explain_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 from an EXPLAIN operation.
*/
typedef struct explain_cursor explain_cursor;
struct explain_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
char *zSql; /* Value for the EXPLN_COLUMN_SQL column */
sqlite3_stmt *pExplain; /* Statement being explained */
int rc; /* Result of last sqlite3_step() on pExplain */
};
/*
** The explainConnect() method is invoked to create a new
** explain_vtab that describes the explain virtual table.
**
** Think of this routine as the constructor for explain_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the explain_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against explain will look like.
*/
static int explainConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
explain_vtab *pNew;
int rc;
/* Column numbers */
#define EXPLN_COLUMN_ADDR 0 /* Instruction address */
#define EXPLN_COLUMN_OPCODE 1 /* Opcode */
#define EXPLN_COLUMN_P1 2 /* Operand 1 */
#define EXPLN_COLUMN_P2 3 /* Operand 2 */
#define EXPLN_COLUMN_P3 4 /* Operand 3 */
#define EXPLN_COLUMN_P4 5 /* Operand 4 */
#define EXPLN_COLUMN_P5 6 /* Operand 5 */
#define EXPLN_COLUMN_COMMENT 7 /* Comment */
#define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)");
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 explain_cursor objects.
*/
static int explainDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new explain_cursor object.
*/
static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
explain_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((explain_vtab*)p)->db;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Destructor for a explain_cursor.
*/
static int explainClose(sqlite3_vtab_cursor *cur){
explain_cursor *pCur = (explain_cursor*)cur;
sqlite3_finalize(pCur->pExplain);
sqlite3_free(pCur->zSql);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Advance a explain_cursor to its next row of output.
*/
static int explainNext(sqlite3_vtab_cursor *cur){
explain_cursor *pCur = (explain_cursor*)cur;
pCur->rc = sqlite3_step(pCur->pExplain);
if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the explain_cursor
** is currently pointing.
*/
static int explainColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
explain_cursor *pCur = (explain_cursor*)cur;
if( i==EXPLN_COLUMN_SQL ){
sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i));
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
explain_cursor *pCur = (explain_cursor*)cur;
*pRowid = sqlite3_column_int64(pCur->pExplain, 0);
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int explainEof(sqlite3_vtab_cursor *cur){
explain_cursor *pCur = (explain_cursor*)cur;
return pCur->rc!=SQLITE_ROW;
}
/*
** This method is called to "rewind" the explain_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to explainColumn() or explainRowid() or
** explainEof().
**
** The argv[0] is the SQL statement that is to be explained.
*/
static int explainFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
explain_cursor *pCur = (explain_cursor *)pVtabCursor;
char *zSql = 0;
int rc;
sqlite3_finalize(pCur->pExplain);
pCur->pExplain = 0;
if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){
pCur->rc = SQLITE_DONE;
return SQLITE_OK;
}
sqlite3_free(pCur->zSql);
pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
if( pCur->zSql ){
zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql);
}
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0);
sqlite3_free(zSql);
}
if( rc ){
sqlite3_finalize(pCur->pExplain);
pCur->pExplain = 0;
sqlite3_free(pCur->zSql);
pCur->zSql = 0;
}else{
pCur->rc = sqlite3_step(pCur->pExplain);
rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
}
return rc;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the explain virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int explainBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i;
pIdxInfo->estimatedCost = (double)1000000;
pIdxInfo->estimatedRows = 500;
for(i=0; i<pIdxInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
if( p->usable
&& p->iColumn==EXPLN_COLUMN_SQL
&& p->op==SQLITE_INDEX_CONSTRAINT_EQ
){
pIdxInfo->estimatedCost = 10.0;
pIdxInfo->idxNum = 1;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
}
}
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** explain virtual table.
*/
static sqlite3_module explainModule = {
0, /* iVersion */
0, /* xCreate */
explainConnect, /* xConnect */
explainBestIndex, /* xBestIndex */
explainDisconnect, /* xDisconnect */
0, /* xDestroy */
explainOpen, /* xOpen - open a cursor */
explainClose, /* xClose - close a cursor */
explainFilter, /* xFilter - configure scan constraints */
explainNext, /* xNext - advance a cursor */
explainEof, /* xEof - check for end of scan */
explainColumn, /* xColumn - read data */
explainRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
int sqlite3ExplainVtabInit(sqlite3 *db){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3_create_module(db, "explain", &explainModule, 0);
#endif
return rc;
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_explain_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3ExplainVtabInit(db);
#endif
return rc;
}
+427
View File
@@ -0,0 +1,427 @@
/*
** 2018-09-27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file demonstrates an eponymous virtual table that returns information
** from sqlite3_status64() and sqlite3_db_status().
**
** Usage example:
**
** .load ./memstat
** .mode quote
** .header on
** SELECT * FROM memstat;
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* memstat_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a memstat virtual table
*/
typedef struct memstat_vtab memstat_vtab;
struct memstat_vtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this memstat vtab */
};
/* memstat_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 memstat_cursor memstat_cursor;
struct memstat_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
int iRowid; /* Current row in aMemstatColumn[] */
int iDb; /* Which schema we are looking at */
int nDb; /* Number of schemas */
char **azDb; /* Names of all schemas */
sqlite3_int64 aVal[2]; /* Result values */
};
/*
** The memstatConnect() method is invoked to create a new
** memstat_vtab that describes the memstat virtual table.
**
** Think of this routine as the constructor for memstat_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the memstat_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against memstat will look like.
*/
static int memstatConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
memstat_vtab *pNew;
int rc;
/* Column numbers */
#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */
#define MSV_COLUMN_SCHEMA 1 /* schema name */
#define MSV_COLUMN_VALUE 2 /* Current value */
#define MSV_COLUMN_HIWTR 3 /* Highwater mark */
rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)");
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 memstat_cursor objects.
*/
static int memstatDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new memstat_cursor object.
*/
static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
memstat_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((memstat_vtab*)p)->db;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Clear all the schema names from a cursor
*/
static void memstatClearSchema(memstat_cursor *pCur){
int i;
if( pCur->azDb==0 ) return;
for(i=0; i<pCur->nDb; i++){
sqlite3_free(pCur->azDb[i]);
}
sqlite3_free(pCur->azDb);
pCur->azDb = 0;
pCur->nDb = 0;
}
/*
** Fill in the azDb[] array for the cursor.
*/
static int memstatFindSchemas(memstat_cursor *pCur){
sqlite3_stmt *pStmt = 0;
int rc;
if( pCur->nDb ) return SQLITE_OK;
rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char **az, *z;
az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
if( az==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
}
pCur->azDb = az;
z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
if( z==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
}
pCur->azDb[pCur->nDb] = z;
pCur->nDb++;
}
sqlite3_finalize(pStmt);
return SQLITE_OK;
}
/*
** Destructor for a memstat_cursor.
*/
static int memstatClose(sqlite3_vtab_cursor *cur){
memstat_cursor *pCur = (memstat_cursor*)cur;
memstatClearSchema(pCur);
sqlite3_free(cur);
return SQLITE_OK;
}
/*
** Allowed values for aMemstatColumn[].eType
*/
#define MSV_GSTAT 0 /* sqlite3_status64() information */
#define MSV_DB 1 /* sqlite3_db_status() information */
#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */
/*
** An array of quantities that can be measured and reported by
** this virtual table
*/
static const struct MemstatColumns {
const char *zName; /* Symbolic name */
unsigned char eType; /* Type of interface */
unsigned char mNull; /* Bitmask of which columns are NULL */
/* 2: dbname, 4: current, 8: hiwtr */
int eOp; /* Opcode */
} aMemstatColumn[] = {
{"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED },
{"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE },
{"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT },
{"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED },
{"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW },
{"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE },
{"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK },
{"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED },
{"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT },
{"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
{"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
{"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED },
#if SQLITE_VERSION_NUMBER >= 3140000
{"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED },
#endif
{"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED },
{"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED },
{"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT },
{"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS },
{"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE },
#if SQLITE_VERSION_NUMBER >= 3230000
{"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL },
#endif
{"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS },
#ifdef SQLITE_ENABLE_ZIPVFS
{"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 },
{"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 },
{"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 },
{"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 },
{"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 },
{"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 },
#endif /* SQLITE_ENABLE_ZIPVFS */
};
#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0]))
/*
** Advance a memstat_cursor to its next row of output.
*/
static int memstatNext(sqlite3_vtab_cursor *cur){
memstat_cursor *pCur = (memstat_cursor*)cur;
int i;
assert( pCur->iRowid<=MSV_NROW );
while(1){
i = (int)pCur->iRowid - 1;
if( (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
pCur->iRowid++;
if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
pCur->iDb = 0;
i++;
}
pCur->aVal[0] = 0;
pCur->aVal[1] = 0;
switch( aMemstatColumn[i].eType ){
case MSV_GSTAT: {
if( sqlite3_libversion_number()>=3010000 ){
sqlite3_status64(aMemstatColumn[i].eOp,
&pCur->aVal[0], &pCur->aVal[1],0);
}else{
int xCur, xHiwtr;
sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
pCur->aVal[0] = xCur;
pCur->aVal[1] = xHiwtr;
}
break;
}
case MSV_DB: {
int xCur, xHiwtr;
sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
pCur->aVal[0] = xCur;
pCur->aVal[1] = xHiwtr;
break;
}
case MSV_ZIPVFS: {
int rc;
rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb],
aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]);
if( rc!=SQLITE_OK ) continue;
break;
}
}
break;
}
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the memstat_cursor
** is currently pointing.
*/
static int memstatColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int iCol /* Which column to return */
){
memstat_cursor *pCur = (memstat_cursor*)cur;
int i;
assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW );
i = (int)pCur->iRowid - 1;
if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){
return SQLITE_OK;
}
switch( iCol ){
case MSV_COLUMN_NAME: {
sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
break;
}
case MSV_COLUMN_SCHEMA: {
sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0);
break;
}
case MSV_COLUMN_VALUE: {
sqlite3_result_int64(ctx, pCur->aVal[0]);
break;
}
case MSV_COLUMN_HIWTR: {
sqlite3_result_int64(ctx, pCur->aVal[1]);
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 memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
memstat_cursor *pCur = (memstat_cursor*)cur;
*pRowid = pCur->iRowid*1000 + pCur->iDb;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int memstatEof(sqlite3_vtab_cursor *cur){
memstat_cursor *pCur = (memstat_cursor*)cur;
return pCur->iRowid>MSV_NROW;
}
/*
** This method is called to "rewind" the memstat_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to memstatColumn() or memstatRowid() or
** memstatEof().
*/
static int memstatFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
memstat_cursor *pCur = (memstat_cursor *)pVtabCursor;
int rc = memstatFindSchemas(pCur);
if( rc ) return rc;
pCur->iRowid = 0;
pCur->iDb = 0;
return memstatNext(pVtabCursor);
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the memstat virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int memstatBestIndex(
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
** memstat virtual table.
*/
static sqlite3_module memstatModule = {
0, /* iVersion */
0, /* xCreate */
memstatConnect, /* xConnect */
memstatBestIndex, /* xBestIndex */
memstatDisconnect, /* xDisconnect */
0, /* xDestroy */
memstatOpen, /* xOpen - open a cursor */
memstatClose, /* xClose - close a cursor */
memstatFilter, /* xFilter - configure scan constraints */
memstatNext, /* xNext - advance a cursor */
memstatEof, /* xEof - check for end of scan */
memstatColumn, /* xColumn - read data */
memstatRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
int sqlite3MemstatVtabInit(sqlite3 *db){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0);
#endif
return rc;
}
#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_memstat_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3MemstatVtabInit(db);
#endif
return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */
+1 -1
View File
@@ -10,7 +10,7 @@
**
******************************************************************************
**
** This SQLite extension implements a functions that compute SHA1 hashes.
** This SQLite extension implements functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha1(X)
+1 -1
View File
@@ -10,7 +10,7 @@
**
******************************************************************************
**
** This SQLite extension implements a functions that compute SHA1 hashes.
** This SQLite extension implements functions that compute SHA3 hashes.
** Two SQL functions are implemented:
**
** sha3(X,SIZE)
+12
View File
@@ -1295,6 +1295,9 @@ typedef struct Transliteration Transliteration;
struct Transliteration {
unsigned short int cFrom;
unsigned char cTo0, cTo1, cTo2, cTo3;
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
unsigned char cTo4;
#endif
};
/*
@@ -1708,7 +1711,11 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
** should be freed by the caller.
*/
static unsigned char *transliterate(const unsigned char *zIn, int nIn){
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 );
#else
unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
#endif
int c, sz, nOut;
if( zOut==0 ) return 0;
nOut = 0;
@@ -1732,6 +1739,11 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){
zOut[nOut++] = tbl[x].cTo2;
if( tbl[x].cTo3 ){
zOut[nOut++] = tbl[x].cTo3;
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
if( tbl[x].cTo4 ){
zOut[nOut++] = tbl[x].cTo4;
}
#endif /* SQLITE_SPELLFIX_5BYTE_MAPPINGS */
}
}
}
+74 -26
View File
@@ -405,7 +405,8 @@ struct rbu_vfs {
sqlite3_vfs *pRealVfs; /* Underlying VFS */
sqlite3_mutex *mutex; /* Mutex to protect pMain */
sqlite3rbu *pRbu; /* Owner RBU object */
rbu_file *pMain; /* Linked list of main db files */
rbu_file *pMain; /* List of main db files */
rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */
};
/*
@@ -434,6 +435,7 @@ struct rbu_file {
const char *zWal; /* Wal filename for this main db file */
rbu_file *pWalFd; /* Wal file descriptor for this main db */
rbu_file *pMainNext; /* Next MAIN_DB file */
rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */
};
/*
@@ -4030,6 +4032,69 @@ static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
return SQLITE_OK;
}
/*
** Add an item to the main-db lists, if it is not already present.
**
** There are two main-db lists. One for all file descriptors, and one
** for all file descriptors with rbu_file.pDb!=0. If the argument has
** rbu_file.pDb!=0, then it is assumed to already be present on the
** main list and is only added to the pDb!=0 list.
*/
static void rbuMainlistAdd(rbu_file *p){
rbu_vfs *pRbuVfs = p->pRbuVfs;
rbu_file *pIter;
assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) );
sqlite3_mutex_enter(pRbuVfs->mutex);
if( p->pRbu==0 ){
for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext);
p->pMainNext = pRbuVfs->pMain;
pRbuVfs->pMain = p;
}else{
for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){}
if( pIter==0 ){
p->pMainRbuNext = pRbuVfs->pMainRbu;
pRbuVfs->pMainRbu = p;
}
}
sqlite3_mutex_leave(pRbuVfs->mutex);
}
/*
** Remove an item from the main-db lists.
*/
static void rbuMainlistRemove(rbu_file *p){
rbu_file **pp;
sqlite3_mutex_enter(p->pRbuVfs->mutex);
for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){}
if( *pp ) *pp = p->pMainNext;
p->pMainNext = 0;
for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){}
if( *pp ) *pp = p->pMainRbuNext;
p->pMainRbuNext = 0;
sqlite3_mutex_leave(p->pRbuVfs->mutex);
}
/*
** Given that zWal points to a buffer containing a wal file name passed to
** either the xOpen() or xAccess() VFS method, search the main-db list for
** a file-handle opened by the same database connection on the corresponding
** database file.
**
** If parameter bRbu is true, only search for file-descriptors with
** rbu_file.pDb!=0.
*/
static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){
rbu_file *pDb;
sqlite3_mutex_enter(pRbuVfs->mutex);
if( bRbu ){
for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){}
}else{
for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
}
sqlite3_mutex_leave(pRbuVfs->mutex);
return pDb;
}
/*
** Close an rbu file.
*/
@@ -4047,17 +4112,14 @@ static int rbuVfsClose(sqlite3_file *pFile){
sqlite3_free(p->zDel);
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
rbu_file **pp;
sqlite3_mutex_enter(p->pRbuVfs->mutex);
for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
*pp = p->pMainNext;
sqlite3_mutex_leave(p->pRbuVfs->mutex);
rbuMainlistRemove(p);
rbuUnlockShm(p);
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
}
else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
rbuUpdateTempSize(p, 0);
}
assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p );
/* Close the underlying file handle */
rc = p->pReal->pMethods->xClose(p->pReal);
@@ -4316,6 +4378,9 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( rc==SQLITE_NOTFOUND ){
pRbu->pTargetFd = p;
p->pRbu = pRbu;
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
rbuMainlistAdd(p);
}
if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
rc = SQLITE_OK;
}
@@ -4477,20 +4542,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
return rc;
}
/*
** Given that zWal points to a buffer containing a wal file name passed to
** either the xOpen() or xAccess() VFS method, return a pointer to the
** file-handle opened by the same database connection on the corresponding
** database file.
*/
static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
rbu_file *pDb;
sqlite3_mutex_enter(pRbuVfs->mutex);
for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
sqlite3_mutex_leave(pRbuVfs->mutex);
return pDb;
}
/*
** A main database named zName has just been opened. The following
** function returns a pointer to a buffer owned by SQLite that contains
@@ -4569,7 +4620,7 @@ static int rbuVfsOpen(
pFd->zWal = rbuMainToWal(zName, flags);
}
else if( flags & SQLITE_OPEN_WAL ){
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
/* This call is to open a *-wal file. Intead, open the *-oal. This
@@ -4621,10 +4672,7 @@ static int rbuVfsOpen(
** mutex protected linked list of all such files. */
pFile->pMethods = &rbuvfs_io_methods;
if( flags & SQLITE_OPEN_MAIN_DB ){
sqlite3_mutex_enter(pRbuVfs->mutex);
pFd->pMainNext = pRbuVfs->pMain;
pRbuVfs->pMain = pFd;
sqlite3_mutex_leave(pRbuVfs->mutex);
rbuMainlistAdd(pFd);
}
}else{
sqlite3_free(pFd->zDel);
@@ -4672,7 +4720,7 @@ static int rbuVfsAccess(
** file opened instead.
*/
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath);
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1);
if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
if( *pResOut ){
rc = SQLITE_CANTOPEN;
+109 -21
View File
@@ -106,14 +106,24 @@ typedef float GeoCoord;
**
** encoding (1 byte) 0=big-endian, 1=little-endian
** nvertex (3 bytes) Number of vertexes as a big-endian integer
**
** Enough space is allocated for 4 coordinates, to work around over-zealous
** warnings coming from some compiler (notably, clang). In reality, the size
** of each GeoPoly memory allocate is adjusted as necessary so that the
** GeoPoly.a[] array at the end is the appropriate size.
*/
typedef struct GeoPoly GeoPoly;
struct GeoPoly {
int nVertex; /* Number of vertexes */
unsigned char hdr[4]; /* Header for on-disk representation */
GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */
};
/* The size of a memory allocation needed for a GeoPoly object sufficient
** to hold N coordinate pairs.
*/
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
/*
** State of a parse of a GeoJSON input.
*/
@@ -138,7 +148,7 @@ static void geopolySwab32(unsigned char *a){
/* Skip whitespace. Return the next non-whitespace character. */
static char geopolySkipSpace(GeoParse *p){
while( p->z[0] && safe_isspace(p->z[0]) ) p->z++;
while( safe_isspace(p->z[0]) ) p->z++;
return p->z[0];
}
@@ -158,7 +168,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0;
for(;; j++){
c = z[j];
if( c>='0' && c<='9' ) continue;
if( safe_isdigit(c) ) continue;
if( c=='.' ){
if( z[j-1]=='-' ) return 0;
if( seenDP ) return 0;
@@ -180,7 +190,17 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
break;
}
if( z[j-1]<'0' ) return 0;
if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z);
if( pVal ){
#ifdef SQLITE_AMALGAMATION
/* The sqlite3AtoF() routine is much much faster than atof(), if it
** is available */
double r;
(void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
*pVal = r;
#else
*pVal = (GeoCoord)atof((const char*)p->z);
#endif
}
p->z += j;
return 1;
}
@@ -238,12 +258,10 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
&& s.a[1]==s.a[s.nVertex*2-1]
&& (s.z++, geopolySkipSpace(&s)==0)
){
int nByte;
GeoPoly *pOut;
int x = 1;
s.nVertex--; /* Remove the redundant vertex at the end */
nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
pOut = sqlite3_malloc64( nByte );
pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
x = 1;
if( pOut==0 ) goto parse_json_err;
pOut->nVertex = s.nVertex;
@@ -476,6 +494,64 @@ static void geopolyAreaFunc(
}
}
#define GEOPOLY_PI 3.1415926535897932385
/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi
*/
static double geopolyCosine(double r){
assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
if( r>=1.5*GEOPOLY_PI ){
r -= 2.0*GEOPOLY_PI;
}
if( r>=0.5*GEOPOLY_PI ){
return -geopolyCosine(r-GEOPOLY_PI);
}else{
double r2 = r*r;
double r3 = r2*r;
double r5 = r3*r2;
return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5;
}
}
/*
** Function: geopoly_regular(X,Y,R,N)
**
** Construct a simple, convex, regular polygon centered at X, Y
** with circumradius R and with N sides.
*/
static void geopolyRegularFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
double x = sqlite3_value_double(argv[0]);
double y = sqlite3_value_double(argv[1]);
double r = sqlite3_value_double(argv[2]);
int n = sqlite3_value_int(argv[3]);
int i;
GeoPoly *p;
if( n<3 || r<=0.0 ) return;
if( n>1000 ) n = 1000;
p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
if( p==0 ){
sqlite3_result_error_nomem(context);
return;
}
i = 1;
p->hdr[0] = *(unsigned char*)&i;
p->hdr[1] = 0;
p->hdr[2] = (n>>8)&0xff;
p->hdr[3] = n&0xff;
for(i=0; i<n; i++){
double rAngle = 2.0*GEOPOLY_PI*i/n;
p->a[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI);
p->a[i*2+1] = y + r*geopolyCosine(rAngle);
}
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
sqlite3_free(p);
}
/*
** If pPoly is a polygon, compute its bounding box. Then:
**
@@ -520,7 +596,7 @@ static GeoPoly *geopolyBBox(
if( pRc ) *pRc = SQLITE_OK;
if( aCoord==0 ){
geopolyBboxFill:
pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
if( pOut==0 ){
sqlite3_free(p);
if( context ) sqlite3_result_error_nomem(context);
@@ -1548,7 +1624,16 @@ static int geopolyUpdate(
if( sqlite3_value_nochange(aData[2]) ){
sqlite3_bind_null(pUp, 2);
}else{
sqlite3_bind_value(pUp, 2, aData[2]);
GeoPoly *p = 0;
if( sqlite3_value_type(aData[2])==SQLITE_TEXT
&& (p = geopolyFuncParam(0, aData[2], &rc))!=0
&& rc==SQLITE_OK
){
sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT);
}else{
sqlite3_bind_value(pUp, 2, aData[2]);
}
sqlite3_free(p);
nChange = 1;
}
for(jj=1; jj<pRtree->nAux; jj++){
@@ -1621,19 +1706,21 @@ static int sqlite3_geopoly_init(sqlite3 *db){
int rc = SQLITE_OK;
static const struct {
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
int nArg;
signed char nArg;
unsigned char bPure;
const char *zName;
} aFunc[] = {
{ geopolyAreaFunc, 1, "geopoly_area" },
{ geopolyBlobFunc, 1, "geopoly_blob" },
{ geopolyJsonFunc, 1, "geopoly_json" },
{ geopolySvgFunc, -1, "geopoly_svg" },
{ geopolyWithinFunc, 2, "geopoly_within" },
{ geopolyContainsPointFunc, 3, "geopoly_contains_point" },
{ geopolyOverlapFunc, 2, "geopoly_overlap" },
{ geopolyDebugFunc, 1, "geopoly_debug" },
{ geopolyBBoxFunc, 1, "geopoly_bbox" },
{ geopolyXformFunc, 7, "geopoly_xform" },
{ geopolyAreaFunc, 1, 1, "geopoly_area" },
{ geopolyBlobFunc, 1, 1, "geopoly_blob" },
{ geopolyJsonFunc, 1, 1, "geopoly_json" },
{ geopolySvgFunc, -1, 1, "geopoly_svg" },
{ geopolyWithinFunc, 2, 1, "geopoly_within" },
{ geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" },
{ geopolyOverlapFunc, 2, 1, "geopoly_overlap" },
{ geopolyDebugFunc, 1, 0, "geopoly_debug" },
{ geopolyBBoxFunc, 1, 1, "geopoly_bbox" },
{ geopolyXformFunc, 7, 1, "geopoly_xform" },
{ geopolyRegularFunc, 4, 1, "geopoly_regular" },
};
static const struct {
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
@@ -1644,8 +1731,9 @@ static int sqlite3_geopoly_init(sqlite3 *db){
};
int i;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
SQLITE_UTF8, 0,
enc, 0,
aFunc[i].xFunc, 0, 0);
}
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
+13
View File
@@ -586,4 +586,17 @@ SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"')
ROLLBACK;
.print '</svg>'
.print '<h1>Regular Polygons</h1>'
.print '<svg width="1000" height="200" style="border:1px solid black">'
SELECT geopoly_svg(geopoly_regular(100,100,40,3),'style="fill:none;stroke:red;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(200,100,40,4),'style="fill:none;stroke:orange;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(300,100,40,5),'style="fill:none;stroke:green;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(400,100,40,6),'style="fill:none;stroke:blue;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(500,100,40,7),'style="fill:none;stroke:purple;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(600,100,40,8),'style="fill:none;stroke:red;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(700,100,40,10),'style="fill:none;stroke:orange;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(800,100,40,20),'style="fill:none;stroke:green;stroke-width:1"');
SELECT geopoly_svg(geopoly_regular(900,100,40,30),'style="fill:none;stroke:blue;stroke-width:1"');
.print '</svg>'
.print '</html>'
+4 -5
View File
@@ -4866,13 +4866,12 @@ static int sessionChangegroupOutput(
sessionAppendByte(&buf, p->op, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc);
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
rc = xOutput(pOut, buf.aBuf, buf.nBuf);
buf.nBuf = 0;
}
}
}
if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
rc = xOutput(pOut, buf.aBuf, buf.nBuf);
buf.nBuf = 0;
}
}
if( rc==SQLITE_OK ){
+1 -1
View File
@@ -210,7 +210,7 @@ int sqlite3_user_authenticate(
db->auth.nAuthPW = nPW;
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
db->auth.authLevel = authLevel;
sqlite3ExpirePreparedStatements(db);
sqlite3ExpirePreparedStatements(db, 0);
if( rc ){
return rc; /* OOM error, I/O error, etc. */
}
+1
View File
@@ -361,6 +361,7 @@ TESTSRC += \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/eval.c \
$(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/misc/ieee754.c \
+92 -86
View File
@@ -1,12 +1,12 @@
C Version\s3.25.0
D 2018-09-15T04:01:47.208
C Ensure\seach\sALTER\sTABLE\sstatement\smakes\sjust\sa\ssingle\sSQLITE_ALTER_TABLE\scall\nto\sthe\sauthorizer\sfunction.
D 2018-10-06T14:33:41.324
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995
F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a
F Makefile.msc b946f8806a5d401a299453f61de80dfd1a9df14fa4902b299e6465e3c3134872
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d
F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -17,7 +17,7 @@ F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a
F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 573b98629d6963e6d9bf2897c3f4708fb94ce49897822526ad268181875e1736
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -33,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure e80ab4e1f5c63a6979971712d35142ad69ef40da6ee4e4df3456be1a77439124 x
F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -281,10 +281,12 @@ F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f0
F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
F ext/misc/explain.c 5851a1a4a1bba6e078da4103fcafc84aa54adfd8edbba419f5cf1eba9f000d50
F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363
F ext/misc/memstat.c 2780712e90765b810645227578438d972b76a089210901bfe9ec88f6a45b0570
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
@@ -295,10 +297,10 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd
F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5
F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e
@@ -346,7 +348,7 @@ F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22
F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819
F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -359,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c 415a8ca5dfab54eea779e0bf31a859afb0b869a5147a726df4aec4b57c1bad57
F ext/rtree/geopoly.c 04db01e24dca675c5ab75110709aed054325f7474b2f567dd98361c373dcff3c
F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
@@ -387,7 +389,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/rtree/visual01.txt 17c3afefc208c375607aa82242e97fa79c316e539bcd0b7b3e59344c69445d05
F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
@@ -414,16 +416,16 @@ F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc45
F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8
F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d
F ext/session/sqlite3session.c ba76c7f01d4c71ab4d134cfda0ba43faae04bff01b8e81d1279a6101c706e3b5
F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf
F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 1db6df4bff24ed6684917e3fe311ce28f5924d6417c698fe4326f7cadf02df31
F main.mk ff82d38126f8f0668b7990e0f1f3dcd74fa2d477c19b2e3feaaba586051e9b48
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -435,17 +437,17 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3800f24c922dfcab2e7a05b49123e2f9c903c26fccea71a5f9ac765e91949355
F src/alter.c 27281c6ed70154c3184d8d775270a61cf3b9cdf169097348abbdbb1f855b2a4f
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
F src/build.c 90571aa2a9eb44e04291ffe9984c814883b9eb371f89898accec384520369597
F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
@@ -453,19 +455,19 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
F src/expr.c 92dc4e104b06d06ffeacbd1a4dc0a520daf37f6156278fb6ece5e90e2ca6b610
F src/expr.c 5cee8fb79b1952689af80ed71ed16ad295f29d85de30c7592993b05cf1ec1e06
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c c723716f0de7aa0a679300f7d3541c89645f4a9882161cecdb3093fc07f8cc4b
F src/insert.c 0a214201afec77880a31a59c33d86b473a160fc5cc31981eab2041ae03d8bf2f
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2
F src/main.c 1f54ee71990bfbf4cdc2dc79bdc33e7c4f54eef6922447b4c910f9b5885a4478
F src/main.c 6275ece0699a957c4709a7ebe29476f132adbe459d18a6b497e234e4669abf91
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -485,33 +487,33 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c d8e37bc3af9b15a52c3fecd366c95416251aa8d89481dd56170bad538b421721
F src/os_unix.c d483d738183c822cc96ec5539424eee5b9847c882dee57f93b880aaf46a7af19
F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
F src/pcache.c 4196eb6ed3bbf00b80596c8e0b4f50e57eb7d890c19fb27a7354306abb7f983d
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/pragma.c a656ff043a03bd94153e6d731a3fbf1bb420207edc969d8fc04b4d2448387901
F src/pragma.h 0ea639401ed7b8275c145e3a814119831e296118b545421e76ae2e1516f10ad8
F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b
F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a
F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
F src/select.c 33aacf1c17c64a00788c779b23d0875dd0d90eb4c08f867ebc31139ef3a67c95
F src/shell.c.in 6046da2a92998b8fe004ed4eadd4d7f53d6a8e4d99e5e25a0cc7de6de5f6b26b
F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
F src/sqliteInt.h ce34da1aacca2cd4b63803db697f682af95c02d1e1750f240438b0d96a59bdb8
F src/sqliteInt.h 75d8266b27c287aeada717a541cf7b7543383fccdb1d7d45a5620f666e864c55
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5
F src/test1.c 31c491ccb536bd9916a084e732ffe783b3c8973f2586d5a56aed0e3a9701dfff
F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
F src/test1.c 9bb042e4afedc570f78638993fc9cc1760d897d3b27dd72c20618044b2a8fa5e
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -526,7 +528,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d
F src/test_config.c 3bbc5e593f308cbff426bb88c9dbf75deab551e5ddcece1251b8d9a40e55aef5
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
@@ -565,32 +567,32 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
F src/treeview.c 0ef7dc77d6fe03172ba65dddfd3b3c557b7b7e217ca1963b7665beb266a0e2c0
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
F src/update.c 345ce35eb1332eb4829857aa8b1f65a614b07dae91d0346c0dc2baacafbcc51b
F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337
F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
F src/vdbeaux.c c3c397274380f13db702baa3506ba87379446a4d71135a1177b624f73dd3c830
F src/vdbeaux.c 9fe7760a6b9739f21f3e19ad5364330b0f681998fc52c32358243b0060423474
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd
F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
F src/where.c a54a3d639bcd751d1474deff58e239b2e475a96e1b8f9178aa7864df8782a4e3
F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893
F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00
F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -598,15 +600,18 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
F test/alter.test cf28c2f35253d3395cf16334fb9dde1d8c4b035cb7c89204353ee1f47feaec1b
F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
F test/alterauth.test dc50064e3d57d60cf8708decefed15cfa154242f6d44069858d4c6c9b1aea961
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test 9480bdf43499b589ca3f80e38ccb6ac6a00b41c702e89fabc366e4b755a432de
F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae
F test/altertab.test fe08624ef1554b85c943ac6289f591e2e9984704a6b35b94613af42cc92ba474
F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altertab.test fb8a9a2ab6deb5f860d27675f6213d14ab79b705e0d6350eead4ef3a3f73bf3e
F test/altertab2.test 159fd5f7b23ddc841fe678f579f9b1b8e69f44296f3ff75d1b4c155d37a59832
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
@@ -636,8 +641,8 @@ F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be82
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test f0c1a8fc7f07d94e3e26ba7f77eb4a5cedda67b10d9a49275b154ab03749b6c0
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
@@ -692,9 +697,9 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b
F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706
F test/capi3.test b299c89d80891c6c9b7f0e4b199df002b8b9f11c19f07d4a6eb7b325f1244de0
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
F test/capi3c.test e853c6c1f9a596e0bc58153be08706813bf5795d479d6f81581e3bda3f9d0909
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
@@ -748,7 +753,7 @@ F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
@@ -958,13 +963,13 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
F test/fuzzdata5.db 7a3467a24e7112c1f1041ae9ad1e7060c2074da82d420ce786953cc3d3dd20b5
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
@@ -989,7 +994,7 @@ F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152
@@ -1007,7 +1012,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216
F test/indexexpr2.test d8f56b6cf4e5663486129bc18c6bde4cef9f8876942b001bfdd692a2b1a42668
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
@@ -1051,7 +1056,7 @@ F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test cf0ff2d06c9d8456283aeff405b911642298441206306aeaeaa93973233b1195
F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
@@ -1064,7 +1069,7 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083
F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
@@ -1090,6 +1095,7 @@ F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c0837
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0fe5e411264c8a9
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
@@ -1165,7 +1171,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test fdcb2d733fc21396e0300206023795463ba0d0ee5eda2042863b044933391da3
F test/permutations.test 8749e292c8f7e98072049543da8c0fe60e1625f0a9f49068623060984c176bbf
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1173,7 +1179,7 @@ F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -1191,7 +1197,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 7e90ec5d2854d80e2574f70df834ef9cae705d21fe43a19dc217a3ce33a3798c x
F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x
F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
@@ -1261,7 +1267,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3
F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
@@ -1329,11 +1335,11 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
F test/tabfunc01.test 5ddfdcda81f362d54cf301a65678edea2a02a570760a4c88051fc2730aafcd81
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b
F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1341,7 +1347,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl d5138d226cc2aaacb6934cdd79acaa5edd17cad862482895b833bbf62c49aca0
F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1514,7 +1520,7 @@ F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
F test/trigger7.test 93cfa9b48ab9104b2b3d87bc544ac8021405643e36f23ee84635fbfaf9b8fef5
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
@@ -1554,7 +1560,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 226fb71e37be61854f3a01929ae0a7e14584d6aef5c459bb0a22318f0b6dd210
F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f
F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1574,7 +1580,7 @@ F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be4
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_err.test 1c476cac24c9c730f83cd7c8bf66482a30151be08d36a2283f87fc38a2dacbb1
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
@@ -1639,17 +1645,17 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 7cb260079cd88d6d6177b0f592686f2bbbc2d10f4f415c8a37cd153eb83c87ca
F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
F test/window4.tcl 871364059b7d320d556ec6ef804d604a4e8cc1547a3102c5d56067371bb200af
F test/window4.test 323b118eb592932036388643ca6dcaead87f699bbea2984bbca49ba4ad6c2509
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3
F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612
F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
@@ -1698,7 +1704,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
F tool/mkpragmatab.tcl fc895d5a40e725b19b866b058b3994bfc45db3e7fef40db9e6c6fd921bf8a337
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1765,10 +1771,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628
R cd1dec78fa9aef334fc060d76165a055
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.25.0 *
U drh
Z 7af864335c95fcb0688b7f5b8af875de
P ff10d2c7de430c88167b1e6e4f5307eee5d69e22c8d24b2ef4fcb3aea25a92e1
R 39888c280f11777f99cfb547c69d2aa6
T *branch * alter-auth-callbacks
T *sym-alter-auth-callbacks *
T -sym-trunk *
U dan
Z 0aa866dd88e8ea8e5fcdd3c207d5f8ef
+1 -1
View File
@@ -1 +1 @@
b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760
dac285474a4b09cb004b797567d050952cb12b952e5688bc4a6e4599faa21565
+73 -35
View File
@@ -98,6 +98,9 @@ void sqlite3AlterRenameTable(
Vdbe *v;
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
u32 savedDbFlags; /* Saved value of db->mDbFlags */
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
#endif
savedDbFlags = db->mDbFlags;
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
@@ -145,6 +148,7 @@ void sqlite3AlterRenameTable(
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
goto exit_rename_table;
}
db->xAuth = 0;
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -169,20 +173,6 @@ void sqlite3AlterRenameTable(
goto exit_rename_table;
}
/* If this is a virtual table, invoke the xRename() function if
** one is defined. The xRename() callback will modify the names
** of any resources used by the v-table implementation (including other
** SQLite tables) that are identified by the name of the virtual table.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pVTab ){
int i = ++pParse->nMem;
sqlite3VdbeLoadString(v, i, zName);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif
/* figure out how many UTF-8 characters are in zName */
zTabName = pTab->zName;
nTabName = sqlite3Utf8CharLen(zTabName, -1);
@@ -240,10 +230,27 @@ void sqlite3AlterRenameTable(
, zDb, zTabName, zName, zTabName, zDb, zName);
}
/* If this is a virtual table, invoke the xRename() function if
** one is defined. The xRename() callback will modify the names
** of any resources used by the v-table implementation (including other
** SQLite tables) that are identified by the name of the virtual table.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pVTab ){
int i = ++pParse->nMem;
sqlite3VdbeLoadString(v, i, zName);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif
renameReloadSchema(pParse, iDb);
renameTestSchema(pParse, zDb, iDb==1);
exit_rename_table:
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zName);
db->mDbFlags = savedDbFlags;
@@ -347,6 +354,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
u32 savedDbFlags = db->mDbFlags;
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
db->xAuth = 0;
#endif
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
@@ -360,6 +371,9 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
);
sqlite3DbFree(db, zCol);
db->mDbFlags = savedDbFlags;
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
}
/* Make sure the schema version is at least 3. But do not upgrade
@@ -520,6 +534,9 @@ void sqlite3AlterRenameColumn(
const char *zDb; /* Name of schema containing the table */
int iSchema; /* Index of the schema */
int bQuote; /* True to quote the new name */
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
#endif
/* Locate the table to be altered */
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
@@ -539,6 +556,7 @@ void sqlite3AlterRenameColumn(
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
goto exit_rename_column;
}
db->xAuth = 0;
#endif
/* Make sure the old name really is a column name in the table to be
@@ -584,6 +602,9 @@ void sqlite3AlterRenameColumn(
renameTestSchema(pParse, zDb, iSchema==1);
exit_rename_column:
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zOld);
sqlite3DbFree(db, zNew);
@@ -803,7 +824,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
&& p->pTab==pExpr->pTab
&& p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
@@ -1061,9 +1082,14 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
);
pParse->eTriggerOp = pNew->op;
/* ALWAYS() because if the table of the trigger does not exist, the
** error would have been hit before this point */
if( ALWAYS(pParse->pTriggerTab) ){
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
}
/* Resolve symbols in WHEN clause */
if( pNew->pWhen ){
if( rc==SQLITE_OK && pNew->pWhen ){
rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen);
}
@@ -1076,7 +1102,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
if( pTarget==0 ){
rc = SQLITE_ERROR;
}else{
}else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
SrcList sSrc;
memset(&sSrc, 0, sizeof(sSrc));
sSrc.nSrc = 1;
@@ -1341,8 +1367,8 @@ renameColumnFunc_done:
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
}
return WRC_Continue;
}
@@ -1422,17 +1448,20 @@ static void renameTableFunc(
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
if( sParse.pNewTable ){
Table *pTab = sParse.pNewTable;
if( pTab->pSelect ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
if( isLegacy==0 ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
}
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -1451,7 +1480,9 @@ static void renameTableFunc(
** "CREATE [VIRTUAL] TABLE" bit. */
if( sqlite3_stricmp(zOld, pTab->zName)==0 ){
sCtx.pTab = pTab;
sqlite3WalkExprList(&sWalker, pTab->pCheck);
if( isLegacy==0 ){
sqlite3WalkExprList(&sWalker, pTab->pCheck);
}
renameTokenFind(&sParse, &sCtx, pTab->zName);
}
}
@@ -1459,7 +1490,9 @@ static void renameTableFunc(
else if( sParse.pNewIndex ){
renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName);
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
if( isLegacy==0 ){
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
}
}
#ifndef SQLITE_OMIT_TRIGGER
@@ -1472,12 +1505,14 @@ static void renameTableFunc(
renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table);
}
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
}
}
}
@@ -1535,6 +1570,7 @@ static void renameTableTest(
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
@@ -1547,7 +1583,7 @@ static void renameTableTest(
Parse sParse;
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
if( rc==SQLITE_OK ){
if( sParse.pNewTable && sParse.pNewTable->pSelect ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
@@ -1556,7 +1592,9 @@ static void renameTableTest(
}
else if( sParse.pNewTrigger ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
}
if( rc==SQLITE_OK ){
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
int i2 = sqlite3FindDbName(db, zDb);
+2
View File
@@ -151,6 +151,7 @@ void sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->xAuth==0 ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
@@ -207,6 +208,7 @@ int sqlite3AuthCheck(
/* Don't do any authorization checks if the database is initialising
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
+7 -4
View File
@@ -1771,10 +1771,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
}
/* The remaining transformations only apply to b-tree tables, not to
** virtual tables */
if( IN_DECLARE_VTAB ) return;
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
@@ -2287,6 +2283,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->pSelect );
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
#ifndef SQLITE_OMIT_ALTERTABLE
u8 eParseMode = pParse->eParseMode;
pParse->eParseMode = PARSE_MODE_NORMAL;
#endif
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
@@ -2332,6 +2332,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
db->lookaside.bDisable--;
#ifndef SQLITE_OMIT_ALTERTABLE
pParse->eParseMode = eParseMode;
#endif
} else {
nErr++;
}
+51 -51
View File
@@ -58,8 +58,8 @@ char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft->flags&EP_xIsSelect );
@@ -143,13 +143,13 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
if( p->flags & EP_Generic ) break;
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|| op==TK_REGISTER || op==TK_TRIGGER)
&& p->pTab!=0
&& p->y.pTab!=0
){
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
int j = p->iColumn;
if( j>=0 ){
const char *zColl = p->pTab->aCol[j].zColl;
const char *zColl = p->y.pTab->aCol[j].zColl;
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
}
break;
@@ -1052,6 +1052,10 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
|| p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
@@ -1070,8 +1074,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
if( !ExprHasProperty(p, EP_Reduced) ){
sqlite3WindowDelete(db, p->pWin);
if( ExprHasProperty(p, EP_WinFunc) ){
assert( p->op==TK_FUNCTION );
sqlite3WindowDelete(db, p->y.pWin);
}
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
@@ -1135,7 +1140,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==flags || p->op==TK_SELECT_COLUMN
#ifndef SQLITE_OMIT_WINDOWFUNC
|| p->pWin
|| ExprHasProperty(p, EP_WinFunc)
#endif
){
nSize = EXPR_FULLSIZE;
@@ -1265,7 +1270,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){
zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
@@ -1273,17 +1278,16 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(p, EP_WinFunc) ){
pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin);
assert( ExprHasProperty(pNew, EP_WinFunc) );
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}else{
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
pNew->pWin = 0;
}else{
pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
@@ -2089,8 +2093,8 @@ int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
p->pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
p->y.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -3378,7 +3382,7 @@ expr_code_doover:
** constant.
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
if( aff!=SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
@@ -3402,7 +3406,7 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
}
@@ -3616,8 +3620,8 @@ expr_code_doover:
CollSeq *pColl = 0; /* A collating sequence */
#ifndef SQLITE_OMIT_WINDOWFUNC
if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
return pExpr->pWin->regResult;
if( ExprHasProperty(pExpr, EP_WinFunc) ){
return pExpr->y.pWin->regResult;
}
#endif
@@ -3860,7 +3864,7 @@ expr_code_doover:
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->pTab;
Table *pTab = pExpr->y.pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
assert( pExpr->iTable==0 || pExpr->iTable==1 );
@@ -3871,7 +3875,7 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
(pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -4722,6 +4726,20 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
if( pA->op==TK_FUNCTION ){
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
#ifndef SQLITE_OMIT_WINDOWFUNC
/* Justification for the assert():
** window functions have p->op==TK_FUNCTION but aggregate functions
** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
** function and a window function should have failed before reaching
** this point. And, it is not possible to have a window function and
** a scalar function with the same name and number of arguments. So
** if we reach this point, either A and B both window functions or
** neither are a window functions. */
assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
if( ExprHasProperty(pA,EP_WinFunc) ){
if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
}
#endif
}else if( pA->op==TK_COLLATE ){
if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
}else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
@@ -4741,21 +4759,6 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
/* Justification for the assert():
** window functions have p->op==TK_FUNCTION but aggregate functions
** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
** function and a window function should have failed before reaching
** this point. And, it is not possible to have a window function and
** a scalar function with the same name and number of arguments. So
** if we reach this point, either A and B both window functions or
** neither are a window functions. */
assert( (pA->pWin==0)==(pB->pWin==0) );
if( pA->pWin!=0 ){
if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2;
}
#endif
}
return 0;
}
@@ -4846,18 +4849,15 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
/*
** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
** If the expression node requires that the table at pWalker->iCur
** have a non-NULL column, then set pWalker->eCode to 1 and abort.
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
**
** This routine controls an optimization. False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
/* This routine is only called for WHERE clause expressions and so it
** cannot have any TK_AGG_COLUMN entries because those are only found
** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
** but that is an illegal construct and the query will be rejected at
** a later stage of processing, so the TK_AGG_FUNCTION case does not
** need to be considered here. */
assert( pExpr->op!=TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
@@ -4899,8 +4899,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
){
return WRC_Prune;
}
@@ -5131,7 +5131,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
+1 -1
View File
@@ -502,7 +502,7 @@ static Expr *exprTableColumn(
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
pExpr->pTab = pTab;
pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
+25 -9
View File
@@ -1126,14 +1126,15 @@ insert_cleanup:
#endif
/*
** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged()
** Meanings of bits in of pWalker->eCode for
** sqlite3ExprReferencesUpdatedColumn()
*/
#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */
#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */
/* This is the Walker callback from checkConstraintUnchanged(). Set
** bit 0x01 of pWalker->eCode if
** pWalker->eCode to 0 if this expression node references any of the
/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn().
* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this
** expression node references any of the
** columns that are being modifed by an UPDATE statement.
*/
static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
@@ -1155,12 +1156,21 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
** only columns that are modified by the UPDATE are those for which
** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true.
**
** Return true if CHECK constraint pExpr does not use any of the
** Return true if CHECK constraint pExpr uses any of the
** changing columns (or the rowid if it is changing). In other words,
** return true if this CHECK constraint can be skipped when validating
** return true if this CHECK constraint must be validated for
** the new row in the UPDATE statement.
**
** 2018-09-15: pExpr might also be an expression for an index-on-expressions.
** The operation of this routine is the same - return true if an only if
** the expression uses one or more of columns identified by the second and
** third arguments.
*/
static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
int sqlite3ExprReferencesUpdatedColumn(
Expr *pExpr, /* The expression to be checked */
int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */
int chngRowid /* True if UPDATE changes the rowid */
){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 0;
@@ -1175,7 +1185,7 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
testcase( w.eCode==CKCNSTRNT_COLUMN );
testcase( w.eCode==CKCNSTRNT_ROWID );
testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
return !w.eCode;
return w.eCode!=0;
}
/*
@@ -1381,7 +1391,13 @@ void sqlite3GenerateConstraintChecks(
for(i=0; i<pCheck->nExpr; i++){
int allOk;
Expr *pExpr = pCheck->a[i].pExpr;
if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
if( aiChng
&& !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
){
/* The check constraints do not reference any of the columns being
** updated so there is no point it verifying the check constraint */
continue;
}
allOk = sqlite3VdbeMakeLabel(v);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
+1
View File
@@ -3021,6 +3021,7 @@ static int openDatabase(
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
+63 -57
View File
@@ -136,12 +136,10 @@
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
** If we are to be thread-safe, include the pthreads header.
*/
#if SQLITE_THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
/*
@@ -521,7 +519,11 @@ static struct unix_syscall {
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
# ifdef __ANDROID__
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
# else
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
# endif
#else
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
#endif
@@ -1115,8 +1117,7 @@ struct unixFileId {
/*
** An instance of the following structure is allocated for each open
** inode. Or, on LinuxThreads, there is one of these structures for
** each inode opened by each thread.
** inode.
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
@@ -1162,13 +1163,16 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
**
** Must hold unixBigLock in order to read or write this variable.
*/
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
#ifdef SQLITE_DEBUG
/*
** True if the inode mutex is held, or not. Used only within assert()
** to help verify correct mutex usage.
** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
** This routine is used only within assert() to help verify correct mutex
** usage.
*/
int unixFileMutexHeld(unixFile *pFile){
assert( pFile->pInode );
@@ -1296,8 +1300,8 @@ static void closePendingFds(unixFile *pFile){
/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
** The global mutex must be held when this routine is called, but the mutex
** on the inode being deleted must NOT be held.
*/
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
@@ -1332,8 +1336,7 @@ static void releaseInodeInfo(unixFile *pFile){
** describes that file descriptor. Create a new one if necessary. The
** return value might be uninitialized if an error occurs.
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
** The global mutex must held when calling this routine.
**
** Return an appropriate error code.
*/
@@ -1394,6 +1397,7 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
assert( unixMutexHeld() );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -1413,6 +1417,7 @@ static int findInodeInfo(
}
}
pInode->nRef = 1;
assert( unixMutexHeld() );
pInode->pNext = inodeList;
pInode->pPrev = 0;
if( inodeList ) inodeList->pPrev = pInode;
@@ -4210,18 +4215,18 @@ static int unixGetpagesize(void){
**
** The following fields are read-only after the object is created:
**
** fid
** hShm
** zFilename
**
** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
sqlite3_mutex *mutex; /* Mutex to access this object */
sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
int h; /* Open file descriptor */
int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
@@ -4243,16 +4248,16 @@ struct unixShmNode {
** The following fields are initialized when this object is created and
** are read-only thereafter:
**
** unixShm.pFile
** unixShm.pShmNode
** unixShm.id
**
** All other fields are read/write. The unixShm.pFile->mutex must be held
** while accessing any read/write fields.
** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
** be held while accessing any read/write fields.
*/
struct unixShm {
unixShmNode *pShmNode; /* The underlying unixShmNode object */
unixShm *pNext; /* Next unixShm with the same unixShmNode */
u8 hasMutex; /* True if holding the unixShmNode mutex */
u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
u8 id; /* Id of this connection within its unixShmNode */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
@@ -4282,7 +4287,8 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
assert( pShmNode->nRef>0 || unixMutexHeld() );
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
@@ -4290,13 +4296,13 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
if( pShmNode->h>=0 ){
if( pShmNode->hShm>=0 ){
/* Initialize the locking parameters */
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
}
@@ -4368,18 +4374,18 @@ static void unixShmPurge(unixFile *pFd){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->mutex);
sqlite3_mutex_free(p->pShmMutex);
for(i=0; i<p->nRegion; i+=nShmPerMap){
if( p->h>=0 ){
if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
sqlite3_free(p->apRegion);
if( p->h>=0 ){
robust_close(pFd, p->h, __LINE__);
p->h = -1;
if( p->hShm>=0 ){
robust_close(pFd, p->hShm, __LINE__);
p->hShm = -1;
}
p->pInode->pShmNode = 0;
sqlite3_free(p);
@@ -4421,7 +4427,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
lock.l_start = UNIX_SHM_DMS;
lock.l_len = 1;
lock.l_type = F_WRLCK;
if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
@@ -4429,7 +4435,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
}
}
@@ -4535,12 +4541,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShm);
#endif
pShmNode->h = -1;
pShmNode->hShm = -1;
pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->mutex==0 ){
pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
@@ -4548,11 +4554,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
}
if( pShmNode->h<0 ){
pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
if( pShmNode->h<0 ){
if( pShmNode->hShm<0 ){
pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
if( pShmNode->hShm<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
goto shm_open_err;
}
@@ -4563,7 +4569,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** is owned by the same user that owns the original database. Otherwise,
** the original owner will not be able to connect.
*/
robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
@@ -4583,13 +4589,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** the cover of the unixEnterMutex() mutex and the pointer from the
** new (struct unixShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
** mutex.
** at pShmNode->pFirst. This must be done while holding the
** pShmNode->pShmMutex.
*/
sqlite3_mutex_enter(pShmNode->mutex);
sqlite3_mutex_enter(pShmNode->pShmMutex);
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
sqlite3_mutex_leave(pShmNode->mutex);
sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
/* Jump here on any error */
@@ -4641,7 +4647,7 @@ static int unixShmMap(
p = pDbFd->pShm;
pShmNode = p->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
sqlite3_mutex_enter(pShmNode->pShmMutex);
if( pShmNode->isUnlocked ){
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
@@ -4649,8 +4655,8 @@ static int unixShmMap(
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
@@ -4662,12 +4668,12 @@ static int unixShmMap(
pShmNode->szRegion = szRegion;
if( pShmNode->h>=0 ){
if( pShmNode->hShm>=0 ){
/* The requested region is not mapped into this processes address space.
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
if( osFstat(pShmNode->h, &sStat) ){
if( osFstat(pShmNode->hShm, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
@@ -4695,7 +4701,7 @@ static int unixShmMap(
assert( (nByte % pgsz)==0 );
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
int x = 0;
if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
const char *zFile = pShmNode->zFilename;
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
goto shmpage_out;
@@ -4718,10 +4724,10 @@ static int unixShmMap(
int nMap = szRegion*nShmPerMap;
int i;
void *pMem;
if( pShmNode->h>=0 ){
if( pShmNode->hShm>=0 ){
pMem = osMmap(0, nMap,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
@@ -4750,7 +4756,7 @@ shmpage_out:
*pp = 0;
}
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
sqlite3_mutex_leave(pShmNode->mutex);
sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
}
@@ -4784,12 +4790,12 @@ static int unixShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
sqlite3_mutex_enter(pShmNode->mutex);
sqlite3_mutex_enter(pShmNode->pShmMutex);
if( flags & SQLITE_SHM_UNLOCK ){
u16 allMask = 0; /* Mask of locks held by siblings */
@@ -4862,7 +4868,7 @@ static int unixShmLock(
}
}
}
sqlite3_mutex_leave(pShmNode->mutex);
sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
@@ -4912,14 +4918,14 @@ static int unixShmUnmap(
/* Remove connection p from the set of connections associated
** with pShmNode */
sqlite3_mutex_enter(pShmNode->mutex);
sqlite3_mutex_enter(pShmNode->pShmMutex);
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
*pp = p->pNext;
/* Free the connection p */
sqlite3_free(p);
pDbFd->pShm = 0;
sqlite3_mutex_leave(pShmNode->mutex);
sqlite3_mutex_leave(pShmNode->pShmMutex);
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
@@ -4928,7 +4934,7 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
if( deleteFlag && pShmNode->h>=0 ){
if( deleteFlag && pShmNode->hShm>=0 ){
osUnlink(pShmNode->zFilename);
}
unixShmPurge(pDbFd);
+1 -4
View File
@@ -941,13 +941,10 @@ idlist(A) ::= nm(Y).
p->pLeft = p->pRight = 0;
p->x.pList = 0;
p->pAggInfo = 0;
p->pTab = 0;
p->y.pTab = 0;
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
p->pWin = 0;
#endif
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
+1 -1
View File
@@ -32,7 +32,7 @@
** The PCache.pSynced variable is used to optimize searching for a dirty
** page to eject from the cache mid-transaction. It is better to eject
** a page that does not require a journal sync than one that does.
** Therefore, pSynced is maintained to that it *almost* always points
** Therefore, pSynced is maintained so that it *almost* always points
** to either the oldest page in the pDirty/pDirtyTail list that has a
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
** (so that the right page to eject can be found by following pDirtyPrev
+6 -4
View File
@@ -1090,11 +1090,12 @@ void sqlite3Pragma(
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 6;
pParse->nMem = 7;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
if( IsHiddenColumn(pCol) ){
int isHidden = IsHiddenColumn(pCol);
if( isHidden && pPragma->iArg==0 ){
nHidden++;
continue;
}
@@ -1106,13 +1107,14 @@ void sqlite3Pragma(
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
sqlite3VdbeMultiLoad(v, 1, "issisi",
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
k);
k,
isHidden);
}
}
}
+70 -61
View File
@@ -68,58 +68,57 @@
** result column is different from the name of the pragma
*/
static const char *const pragCName[] = {
/* 0 */ "cache_size", /* Used by: default_cache_size */
/* 1 */ "cid", /* Used by: table_info */
/* 2 */ "name",
/* 3 */ "type",
/* 4 */ "notnull",
/* 5 */ "dflt_value",
/* 6 */ "pk",
/* 7 */ "tbl", /* Used by: stats */
/* 8 */ "idx",
/* 9 */ "wdth",
/* 10 */ "hght",
/* 11 */ "flgs",
/* 12 */ "seqno", /* Used by: index_info */
/* 13 */ "cid",
/* 14 */ "name",
/* 0 */ "id", /* Used by: foreign_key_list */
/* 1 */ "seq",
/* 2 */ "table",
/* 3 */ "from",
/* 4 */ "to",
/* 5 */ "on_update",
/* 6 */ "on_delete",
/* 7 */ "match",
/* 8 */ "cid", /* Used by: table_xinfo */
/* 9 */ "name",
/* 10 */ "type",
/* 11 */ "notnull",
/* 12 */ "dflt_value",
/* 13 */ "pk",
/* 14 */ "hidden",
/* table_info reuses 8 */
/* 15 */ "seqno", /* Used by: index_xinfo */
/* 16 */ "cid",
/* 17 */ "name",
/* 18 */ "desc",
/* 19 */ "coll",
/* 20 */ "key",
/* 21 */ "seq", /* Used by: index_list */
/* 22 */ "name",
/* 23 */ "unique",
/* 24 */ "origin",
/* 25 */ "partial",
/* 26 */ "seq", /* Used by: database_list */
/* 21 */ "tbl", /* Used by: stats */
/* 22 */ "idx",
/* 23 */ "wdth",
/* 24 */ "hght",
/* 25 */ "flgs",
/* 26 */ "seq", /* Used by: index_list */
/* 27 */ "name",
/* 28 */ "file",
/* 29 */ "name", /* Used by: function_list */
/* 30 */ "builtin",
/* 31 */ "name", /* Used by: module_list pragma_list */
/* 32 */ "seq", /* Used by: collation_list */
/* 33 */ "name",
/* 34 */ "id", /* Used by: foreign_key_list */
/* 35 */ "seq",
/* 36 */ "table",
/* 37 */ "from",
/* 38 */ "to",
/* 39 */ "on_update",
/* 40 */ "on_delete",
/* 41 */ "match",
/* 42 */ "table", /* Used by: foreign_key_check */
/* 43 */ "rowid",
/* 44 */ "parent",
/* 45 */ "fkid",
/* 46 */ "busy", /* Used by: wal_checkpoint */
/* 47 */ "log",
/* 48 */ "checkpointed",
/* 49 */ "timeout", /* Used by: busy_timeout */
/* 50 */ "database", /* Used by: lock_status */
/* 51 */ "status",
/* 28 */ "unique",
/* 29 */ "origin",
/* 30 */ "partial",
/* 31 */ "table", /* Used by: foreign_key_check */
/* 32 */ "rowid",
/* 33 */ "parent",
/* 34 */ "fkid",
/* index_info reuses 15 */
/* 35 */ "seq", /* Used by: database_list */
/* 36 */ "name",
/* 37 */ "file",
/* 38 */ "busy", /* Used by: wal_checkpoint */
/* 39 */ "log",
/* 40 */ "checkpointed",
/* 41 */ "name", /* Used by: function_list */
/* 42 */ "builtin",
/* collation_list reuses 26 */
/* 43 */ "database", /* Used by: lock_status */
/* 44 */ "status",
/* 45 */ "cache_size", /* Used by: default_cache_size */
/* module_list pragma_list reuses 9 */
/* 46 */ "timeout", /* Used by: busy_timeout */
};
/* Definitions of all built-in pragmas */
@@ -165,7 +164,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 49, 1,
/* ColNames: */ 46, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -202,7 +201,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 32, 2,
/* ColNames: */ 26, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -237,14 +236,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
/* ColNames: */ 26, 3,
/* ColNames: */ 35, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 1,
/* ColNames: */ 45, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -274,14 +273,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
/* ColNames: */ 42, 4,
/* ColNames: */ 31, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 34, 8,
/* ColNames: */ 0, 8,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -317,7 +316,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 29, 2,
/* ColNames: */ 41, 2,
/* iArg: */ 0 },
#endif
#endif
@@ -353,12 +352,12 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 12, 3,
/* ColNames: */ 15, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 21, 5,
/* ColNames: */ 26, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
@@ -393,6 +392,11 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "legacy_alter_table",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_LegacyAlter },
{/* zName: */ "legacy_file_format",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
@@ -410,7 +414,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 50, 2,
/* ColNames: */ 43, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -436,7 +440,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "module_list",
/* ePragTyp: */ PragTyp_MODULE_LIST,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 31, 1,
/* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#endif
@@ -469,7 +473,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "pragma_list",
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 31, 1,
/* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -556,7 +560,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ColNames: */ 7, 5,
/* ColNames: */ 21, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -570,8 +574,13 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "table_info",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 1, 6,
/* ColNames: */ 8, 6,
/* iArg: */ 0 },
{/* zName: */ "table_xinfo",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 8, 7,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "temp_store",
@@ -635,7 +644,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
/* ColNames: */ 46, 3,
/* ColNames: */ 38, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -646,4 +655,4 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema },
#endif
};
/* Number of pragmas: 60 on by default, 77 total. */
/* Number of pragmas: 62 on by default, 79 total. */
+26 -29
View File
@@ -159,7 +159,7 @@ int sqlite3MatchSpanName(
** (even if X is implied).
** pExpr->iTable Set to the cursor number for the table obtained
** from pSrcList.
** pExpr->pTab Points to the Table structure of X.Y (even if
** pExpr->y.pTab Points to the Table structure of X.Y (even if
** X and/or Y are implied.)
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
@@ -203,7 +203,6 @@ static int lookupName(
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
@@ -265,7 +264,7 @@ static int lookupName(
continue;
}
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
if( 0==(cntTab++) ){
@@ -291,13 +290,13 @@ static int lookupName(
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->pTab = pMatch->pTab;
pExpr->y.pTab = pMatch->pTab;
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->pTab->pSchema;
pSchema = pExpr->y.pTab->pSchema;
}
} /* if( pSrcList ) */
@@ -354,7 +353,7 @@ static int lookupName(
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->pTab = pTab;
pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
@@ -376,7 +375,7 @@ static int lookupName(
testcase( iCol==32 );
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
}
pExpr->pTab = pTab;
pExpr->y.pTab = pTab;
pExpr->iColumn = (i16)iCol;
eNewExprOp = TK_TRIGGER;
#endif /* SQLITE_OMIT_TRIGGER */
@@ -476,7 +475,7 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
pExpr->op = TK_STRING;
pExpr->pTab = 0;
pExpr->y.pTab = 0;
return WRC_Prune;
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
@@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
struct SrcList_item *pItem = &pSrc->a[iSrc];
p->pTab = pItem->pTab;
p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->pTab->iPKey==iCol ){
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
@@ -646,7 +645,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
pExpr->op = TK_COLUMN;
pExpr->pTab = pItem->pTab;
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn = -1;
pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -690,9 +689,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zColumn = pRight->u.zToken;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
@@ -782,18 +779,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
if( pDef && pDef->xValue==0 && pExpr->pWin ){
if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
pNC->nErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
|| (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
|| (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
){
const char *zType;
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
zType = "window";
}else{
zType = "aggregate";
@@ -823,7 +820,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
#else
pNC->ncFlags &= ~NC_AllowAgg;
#endif
@@ -832,17 +829,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pExpr->pWin ){
if( pExpr->y.pWin ){
Select *pSel = pNC->pWinSelect;
sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);
sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter);
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
if( 0==pSel->pWin
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
pExpr->pWin->pNextWin = pSel->pWin;
pSel->pWin = pExpr->pWin;
pExpr->y.pWin->pNextWin = pSel->pWin;
pSel->pWin = pExpr->y.pWin;
}
pNC->ncFlags |= NC_AllowWin;
}else
@@ -1265,13 +1262,13 @@ static int resolveOrderGroupBy(
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pE->pWin ){
if( ExprHasProperty(pE, EP_WinFunc) ){
/* Since this window function is being changed into a reference
** to the same window function the result set, remove the instance
** of this window function from the Select.pWin list. */
Window **pp;
for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
if( *pp==pE->pWin ){
if( *pp==pE->y.pWin ){
*pp = (*pp)->pNextWin;
}
}
+15 -7
View File
@@ -803,7 +803,7 @@ static void selectExprDefer(
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
Table *pTab = pExpr->pTab;
Table *pTab = pExpr->y.pTab;
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
){
@@ -826,12 +826,12 @@ static void selectExprDefer(
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
pNew->pTab = pExpr->pTab;
pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
pSort->aDefer[nDefer].pTab = pExpr->pTab;
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
@@ -1680,7 +1680,7 @@ static const char *columnTypeImpl(
break;
}
assert( pTab && pExpr->pTab==pTab );
assert( pTab && pExpr->y.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
@@ -1865,7 +1865,7 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
if( pEList->a[i].zName ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
@@ -1873,7 +1873,7 @@ static void generateColumnNames(
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
pTab = p->pTab;
pTab = p->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
@@ -1964,7 +1964,7 @@ int sqlite3ColumnsFromExprList(
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
Table *pTab = pColExpr->pTab;
Table *pTab = pColExpr->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
@@ -2318,6 +2318,13 @@ static void generateWithRecursiveQuery(
Expr *pLimit; /* Saved LIMIT and OFFSET */
int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries");
return;
}
#endif
/* Obtain authorization to do a recursive query */
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
@@ -6086,6 +6093,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
sqlite3VdbeResolveLabel(v, addrGosub);
VdbeNoopComment((v, "inner-loop subroutine"));
sSort.labelOBLopt = 0;
selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp1(v, OP_Return, regGosub);
+216 -138
View File
@@ -1273,7 +1273,7 @@ static void editFunc(
if( bBin ){
sqlite3_result_blob64(context, p, sz, sqlite3_free);
}else{
int i, j;
sqlite3_int64 i, j;
if( hasCRNL ){
/* If the original contains \r\n then do no conversions back to \n */
j = sz;
@@ -3335,137 +3335,229 @@ static int run_schema_dump_query(
}
/*
** Text of a help message
** Text of help messages.
**
** The help text for each individual command begins with a line that starts
** with ".". Subsequent lines are supplimental information.
**
** There must be two or more spaces between the end of the command and the
** start of the description of what that command does.
*/
static char zHelp[] =
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
".archive ... Manage SQL archives: \".archive --help\" for details\n"
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Update or add files to an existing archive",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Operate on archive FILE (default is current db)",
" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
" -C DIR, --directory DIR Change to directory DIR to read/extract files",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
" .ar -tf archive.sar # List members of archive.sar",
" .ar -xvf archive.sar # Verbosely extract files from archive.sar",
" See also:",
" http://sqlite.org/cli.html#sqlar_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
".auth ON|OFF Show authorizer callbacks\n"
".auth ON|OFF Show authorizer callbacks",
#endif
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
" Add \"--append\" to open using appendvfs.\n"
".bail on|off Stop after hitting an error. Default OFF\n"
".binary on|off Turn binary output on or off. Default OFF\n"
".cd DIRECTORY Change the working directory to DIRECTORY\n"
".changes on|off Show number of rows changed by SQL\n"
".check GLOB Fail if output since .testcase does not match\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n"
".dbinfo ?DB? Show status information about the database\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
" LIKE pattern TABLE.\n"
".echo on|off Turn command echo on or off\n"
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
".excel Display the output of next command in a spreadsheet\n"
".exit Exit this program\n"
".expert EXPERIMENTAL. Suggest indexes for specified queries\n"
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
".cd DIRECTORY Change the working directory to DIRECTORY",
".changes on|off Show number of rows changed by SQL",
".check GLOB Fail if output since .testcase does not match",
".clone NEWDB Clone data into NEWDB from the existing database",
".databases List names and files of attached databases",
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
".dbinfo ?DB? Show status information about the database",
".dump ?TABLE? ... Render all database content as SQL",
" Options:",
" --preserve-rowids Include ROWID values in the output",
" --newlines Allow unescaped newline characters in output",
" TABLE is LIKE pattern for the tables to dump",
".echo on|off Turn command echo on or off",
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
".excel Display the output of next command in a spreadsheet",
".exit ?CODE? Exit this program with return-code CODE",
".expert EXPERIMENTAL. Suggest indexes for specified queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen. It is still supported for legacy, however */
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
".headers on|off Turn display of headers on or off\n"
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
".headers on|off Turn display of headers on or off",
".help ?-all? ?PATTERN? Show help text for PATTERN",
".import FILE TABLE Import data from FILE into TABLE",
#ifndef SQLITE_OMIT_TEST_CONTROL
".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
#endif
".indexes ?TABLE? Show names of all indexes\n"
" If TABLE specified, only show indexes for tables\n"
" matching LIKE pattern TABLE.\n"
".indexes ?TABLE? Show names of indexes",
" If TABLE is specified, only show indexes for",
" tables matching TABLE using the LIKE operator.",
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
".iotrace FILE Enable I/O diagnostic logging to FILE",
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
".lint OPTIONS Report potential schema issues. Options:\n"
" fkey-indexes Find missing foreign key indexes\n"
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
".lint OPTIONS Report potential schema issues.",
" Options:",
" fkey-indexes Find missing foreign key indexes",
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
".load FILE ?ENTRY? Load an extension library",
#endif
".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" ascii Columns/rows delimited by 0x1F and 0x1E\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
" html HTML <table> code\n"
" insert SQL insert statements for TABLE\n"
" line One value per line\n"
" list Values delimited by \"|\"\n"
" quote Escape answers as for SQL\n"
" tabs Tab-separated values\n"
" tcl TCL list elements\n"
".nullvalue STRING Use STRING in place of NULL values\n"
".once (-e|-x|FILE) Output for the next SQL command only to FILE\n"
" or invoke system text editor (-e) or spreadsheet (-x)\n"
" on the output.\n"
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
" The --new option starts with an empty file\n"
" Other options: --readonly --append --zip\n"
".output ?FILE? Send output to FILE or stdout\n"
".print STRING... Print literal STRING\n"
".prompt MAIN CONTINUE Replace the standard prompts\n"
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
".save FILE Write in-memory database into FILE\n"
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
" Add --indent for pretty-printing\n"
".selftest ?--init? Run tests defined in the SELFTEST table\n"
".separator COL ?ROW? Change the column separator and optionally the row\n"
" separator for both the output mode and .import\n"
".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
".mode MODE ?TABLE? Set output mode",
" MODE is one of:",
" ascii Columns/rows delimited by 0x1F and 0x1E",
" csv Comma-separated values",
" column Left-aligned columns. (See .width)",
" html HTML <table> code",
" insert SQL insert statements for TABLE",
" line One value per line",
" list Values delimited by \"|\"",
" quote Escape answers as for SQL",
" tabs Tab-separated values",
" tcl TCL list elements",
".nullvalue STRING Use STRING in place of NULL values",
".once (-e|-x|FILE) Output for the next SQL command only to FILE",
" If FILE begins with '|' then open as a pipe",
" Other options:",
" -e Invoke system text editor",
" -x Open in a spreadsheet",
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
" Options:",
" --append Use appendvfs to append database to the end of FILE",
" --new Initialize FILE to an empty database",
" --readonly Open FILE readonly",
" --zip FILE is a ZIP archive",
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
" If FILE begins with '|' then open it as a pipe.",
".print STRING... Print literal STRING",
".prompt MAIN CONTINUE Replace the standard prompts",
".quit Exit this program",
".read FILE Read input from FILE",
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
".save FILE Write in-memory database into FILE",
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
" Options:",
" --indent Try to pretty-print the schema",
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
" Options:",
" --init Create a new SELFTEST table",
" -v Verbose output",
".separator COL ?ROW? Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
".session CMD ... Create or control sessions\n"
".session ?NAME? CMD ... Create or control sessions",
" Subcommands:",
" attach TABLE Attach TABLE",
" changeset FILE Write a changeset into FILE",
" close Close one session",
" enable ?BOOLEAN? Set or query the enable bit",
" filter GLOB... Reject tables matching GLOBs",
" indirect ?BOOLEAN? Mark or query the indirect status",
" isempty Query whether the session is empty",
" list List currently open session names",
" open DB NAME Open a new session on DB",
" patchset FILE Write a patchset into FILE",
" If ?NAME? is omitted, the first defined session is used.",
#endif
".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
".sha3sum ... Compute a SHA3 hash of database content",
" Options:",
" --schema Also hash the sqlite_master table",
" --sha3-224 Use the sha3-224 algorithm",
" --sha3-256 Use the sha3-256 algorithm. This is the default.",
" --sha3-384 Use the sha3-384 algorithm",
" --sha3-512 Use the sha3-512 algorithm",
" Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
".show Show the current values for various settings\n"
".stats ?on|off? Show stats or turn stats on or off\n"
".show Show the current values for various settings",
".stats ?on|off? Show stats or turn stats on or off",
#ifndef SQLITE_NOHAVE_SYSTEM
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
".system CMD ARGS... Run CMD ARGS... in a system shell",
#endif
".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n"
".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
".timeout MS Try opening locked tables for MS milliseconds\n"
".timer on|off Turn SQL timer on or off\n"
".trace FILE|off Output each SQL statement as it is run\n"
".vfsinfo ?AUX? Information about the top-level VFS\n"
".vfslist List all available VFSes\n"
".vfsname ?AUX? Print the name of the VFS stack\n"
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
" Negative values right-justify\n"
;
".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
".testcase NAME Begin redirecting output to 'testcase-out.txt'",
".timeout MS Try opening locked tables for MS milliseconds",
".timer on|off Turn SQL timer on or off",
".trace FILE|off Output each SQL statement as it is run",
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
".width NUM1 NUM2 ... Set column widths for \"column\" mode",
" Negative values right-justify",
};
#if defined(SQLITE_ENABLE_SESSION)
/*
** Print help information for the ".sessions" command
** Output help text.
**
** zPattern describes the set of commands for which help text is provided.
** If zPattern is NULL, then show all commands, but only give a one-line
** description of each.
**
** Return the number of matches.
*/
void session_help(ShellState *p){
raw_printf(p->out,
".session ?NAME? SUBCOMMAND ?ARGS...?\n"
"If ?NAME? is omitted, the first defined session is used.\n"
"Subcommands:\n"
" attach TABLE Attach TABLE\n"
" changeset FILE Write a changeset into FILE\n"
" close Close one session\n"
" enable ?BOOLEAN? Set or query the enable bit\n"
" filter GLOB... Reject tables matching GLOBs\n"
" indirect ?BOOLEAN? Mark or query the indirect status\n"
" isempty Query whether the session is empty\n"
" list List currently open session names\n"
" open DB NAME Open a new session on DB\n"
" patchset FILE Write a patchset into FILE\n"
);
static int showHelp(FILE *out, const char *zPattern){
int i, j;
int n = 0;
char *zPat;
if( zPattern==0 || zPattern[0]=='0' ){
/* Show all commands, but only one line per command */
for(i=0; i<ArraySize(azHelp); i++){
if( azHelp[i][0]=='.' ){
utf8_printf(out, "%s\n", azHelp[i]);
n++;
}
}
}else{
/* Look for commands that for which zPattern is an exact prefix */
zPat = sqlite3_mprintf(".%s*", zPattern);
for(i=0; i<ArraySize(azHelp); i++){
if( sqlite3_strglob(zPat, azHelp[i])==0 ){
utf8_printf(out, "%s\n", azHelp[i]);
j = i+1;
n++;
}
}
sqlite3_free(zPat);
if( n ){
if( n==1 ){
/* when zPattern is a prefix of exactly one command, then include the
** details of that command, which should begin at offset j */
while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
utf8_printf(out, "%s\n", azHelp[j]);
j++;
}
}
return n;
}
/* Look for commands that contain zPattern anywhere. Show the complete
** text of all commands that match. */
zPat = sqlite3_mprintf("%%%s%%", zPattern);
for(i=0; i<ArraySize(azHelp); i++){
if( azHelp[i][0]=='.' ) j = i;
if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
utf8_printf(out, "%s\n", azHelp[j]);
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
j++;
utf8_printf(out, "%s\n", azHelp[j]);
}
i = j;
n++;
}
}
sqlite3_free(zPat);
}
return n;
}
#endif
/* Forward reference */
static int process_input(ShellState *p, FILE *in);
@@ -4941,32 +5033,7 @@ struct ArCommand {
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
*/
static int arUsage(FILE *f){
raw_printf(f,
"\n"
"Usage: .ar [OPTION...] [FILE...]\n"
"The .ar command manages sqlar archives.\n"
"\n"
"Examples:\n"
" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
" .ar -tf archive.sar # List members of archive.sar\n"
" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
"\n"
"Each command line must feature exactly one command option:\n"
" -c, --create Create a new archive\n"
" -u, --update Update or add files to an existing archive\n"
" -t, --list List contents of archive\n"
" -x, --extract Extract files from archive\n"
"\n"
"And zero or more optional options:\n"
" -v, --verbose Print each filename as it is processed\n"
" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n"
" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
" -n, --dryrun Show the SQL that would have occurred\n"
"\n"
"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
"\n"
);
showHelp(f,"archive");
return SQLITE_ERROR;
}
@@ -5073,6 +5140,7 @@ static int arParseCommand(
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
}else{
char *z = azArg[1];
@@ -5844,7 +5912,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = {
static const struct DbConfigChoices {
const char *zName;
int op;
} aDbConfig[] = {
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
@@ -6091,7 +6162,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
utf8_printf(p->out, "%s", zHelp);
if( nArg>=2 ){
int n = showHelp(p->out, azArg[1]);
if( n==0 ){
utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
}
}else{
showHelp(p->out, 0);
}
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
@@ -7095,7 +7173,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
session_help(p);
showHelp(p->out, "session");
}else
#endif
+9 -5
View File
@@ -1536,6 +1536,7 @@ struct sqlite3 {
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -2459,11 +2460,11 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
** for a column of an index on an expression */
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin; /* Window definition for window functions */
#endif
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* TK_FUNCTION: Window definition for the func */
} y;
};
/*
@@ -2493,6 +2494,7 @@ struct Expr {
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -3178,6 +3180,7 @@ struct AuthContext {
*/
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
@@ -4002,6 +4005,7 @@ void sqlite3GenerateRowDelete(
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*,Upsert*);
#ifdef SQLITE_ENABLE_NULL_TRIM
+1
View File
@@ -3497,6 +3497,7 @@ static int SQLITE_TCLAPI DbMain(
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
#endif
if( objc==1 ) return sqliteCmdUsage(interp, objv);
if( objc==2 ){
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( strcmp(zArg,"-version")==0 ){
+2
View File
@@ -7038,6 +7038,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -7062,6 +7063,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "closure", sqlite3_closure_init },
{ "csv", sqlite3_csv_init },
{ "eval", sqlite3_eval_init },
{ "explain", sqlite3_explain_init },
{ "fileio", sqlite3_fileio_init },
{ "fuzzer", sqlite3_fuzzer_init },
{ "ieee754", sqlite3_ieee_init },
+1 -1
View File
@@ -124,7 +124,7 @@ static void set_options(Tcl_Interp *interp){
STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY
);
#if 1 /* def SQLITE_MEMDEBUG */
#ifdef SQLITE_MEMDEBUG
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
+1 -1
View File
@@ -497,7 +497,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = pExpr->pWin;
pWin = pExpr->y.pWin;
#else
pWin = 0;
#endif
+56 -6
View File
@@ -79,6 +79,57 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
#endif
}
/*
** Check to see if column iCol of index pIdx references any of the
** columns defined by aXRef and chngRowid. Return true if it does
** and false if not. This is an optimization. False-positives are a
** performance degradation, but false-negatives can result in a corrupt
** index and incorrect answers.
**
** aXRef[j] will be non-negative if column j of the original table is
** being updated. chngRowid will be true if the rowid of the table is
** being updated.
*/
static int indexColumnIsBeingUpdated(
Index *pIdx, /* The index to check */
int iCol, /* Which column of the index to check */
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
int chngRowid /* true if the rowid is being updated */
){
i16 iIdxCol = pIdx->aiColumn[iCol];
assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */
if( iIdxCol>=0 ){
return aXRef[iIdxCol]>=0;
}
assert( iIdxCol==XN_EXPR );
assert( pIdx->aColExpr!=0 );
assert( pIdx->aColExpr->a[iCol].pExpr!=0 );
return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr,
aXRef,chngRowid);
}
/*
** Check to see if index pIdx is a partial index whose conditional
** expression might change values due to an UPDATE. Return true if
** the index is subject to change and false if the index is guaranteed
** to be unchanged. This is an optimization. False-positives are a
** performance degradation, but false-negatives can result in a corrupt
** index and incorrect answers.
**
** aXRef[j] will be non-negative if column j of the original table is
** being updated. chngRowid will be true if the rowid of the table is
** being updated.
*/
static int indexWhereClauseMightChange(
Index *pIdx, /* The index to check */
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
int chngRowid /* true if the rowid is being updated */
){
if( pIdx->pPartIdxWhere==0 ) return 0;
return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
aXRef, chngRowid);
}
/*
** Process an UPDATE statement.
**
@@ -302,19 +353,18 @@ void sqlite3Update(
/* There is one entry in the aRegIdx[] array for each index on the table
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
**
** FIXME: Be smarter about omitting indexes that use expressions.
*/
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
if( chngKey || hasFK>1 || pIdx==pPk
|| indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; i<pIdx->nKeyCol; i++){
i16 iIdxCol = pIdx->aiColumn[i];
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
if( (onError==OE_Replace)
@@ -863,7 +913,7 @@ static void updateVirtualTable(
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
}
}
if( HasRowid(pTab) ){
+26 -12
View File
@@ -2894,17 +2894,25 @@ case OP_MakeRecord: {
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
}
nByte = nHdr+nData;
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
/* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
*/
if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
goto no_mem;
if( nByte+nZero<=pOut->szMalloc ){
/* The output register is already large enough to hold the record.
** No error checks or buffer enlargement is required */
pOut->z = pOut->zMalloc;
}else{
/* Need to make sure that the output is not too big and then enlarge
** the output register to hold the full result */
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
goto no_mem;
}
}
zNewRecord = (u8 *)pOut->z;
@@ -5760,7 +5768,7 @@ case OP_ParseSchema: {
{
zMaster = MASTER_NAME;
initData.db = db;
initData.iDb = pOp->p1;
initData.iDb = iDb;
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
@@ -6957,10 +6965,11 @@ case OP_VFilter: { /* jump */
**
** If the VColumn opcode is being used to fetch the value of
** an unchanging column during an UPDATE operation, then the P5
** value is 1. Otherwise, P5 is 0. The P5 value is returned
** by sqlite3_vtab_nochange() routine and can be used
** by virtual table implementations to return special "no-change"
** marks which can be more efficient, depending on the virtual table.
** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange()
** function to return true inside the xColumn method of the virtual
** table implementation. The P5 column might also contain other
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
** unused by OP_VColumn.
*/
case OP_VColumn: {
sqlite3_vtab *pVtab;
@@ -6982,7 +6991,8 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
if( pOp->p5 ){
testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
@@ -7059,7 +7069,10 @@ case OP_VNext: { /* jump */
case OP_VRename: {
sqlite3_vtab *pVtab;
Mem *pName;
int isLegacy;
isLegacy = (db->flags & SQLITE_LegacyAlter);
db->flags |= SQLITE_LegacyAlter;
pVtab = pOp->p4.pVtab->pVtab;
pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
@@ -7073,6 +7086,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
+3 -1
View File
@@ -4557,7 +4557,9 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
(void)getVarint32((u8*)m.z, szHdr);
testcase( szHdr==3 );
testcase( szHdr==m.n );
if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
testcase( szHdr>0x7fffffff );
assert( m.n>=0 );
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
goto idx_rowid_corruption;
}
+3 -4
View File
@@ -328,7 +328,6 @@ void sqlite3VtabBeginParse(
Token *pModuleName, /* Name of the module for the virtual table */
int ifNotExists /* No error if the table already exists */
){
int iDb; /* The database the table is being created in */
Table *pTable; /* The new virtual table */
sqlite3 *db; /* Database connection */
@@ -338,8 +337,6 @@ void sqlite3VtabBeginParse(
assert( 0==pTable->pIndex );
db = pParse->db;
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
assert( pTable->nModuleArg==0 );
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
@@ -359,6 +356,8 @@ void sqlite3VtabBeginParse(
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 ); /* The database the table is being created in */
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
}
@@ -1053,7 +1052,7 @@ FuncDef *sqlite3VtabOverloadFunction(
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
pTab = pExpr->y.pTab;
if( pTab==0 ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
+2 -2
View File
@@ -55,8 +55,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
Window *pWin = pExpr->pWin;
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window *pWin = pExpr->y.pWin;
if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+19 -1
View File
@@ -2126,6 +2126,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
sqlite3 *db = pWInfo->pParse->db;
int rc;
/* Stop the search once we hit the query planner search limit */
if( pBuilder->iPlanLimit==0 ){
WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n"));
if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0;
return SQLITE_DONE;
}
pBuilder->iPlanLimit--;
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
@@ -3532,9 +3540,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
Bitmask mUnusable = 0;
pNew->iTab = iTab;
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
/* This condition is true when pItem is the FROM clause term on the
@@ -3560,7 +3570,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
if( rc || db->mallocFailed ) break;
if( rc || db->mallocFailed ){
if( rc==SQLITE_DONE ){
/* We hit the query planner search limit set by iPlanLimit */
sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search");
rc = SQLITE_OK;
}else{
break;
}
}
}
whereLoopClear(db, pNew);
+21
View File
@@ -402,12 +402,33 @@ struct WhereLoopBuilder {
int nRecValid; /* Number of valid fields currently in pRec */
#endif
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
unsigned int iPlanLimit; /* Search limiter */
};
/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
** index+constraint combinations the query planner will consider for a
** particular query. If this parameter is unlimited, then certain
** pathological queries can spend excess time in the sqlite3WhereBegin()
** routine. The limit is high enough that is should not impact real-world
** queries.
**
** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is
** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM
** clause is processed, so that every table in a join is guaranteed to be
** able to propose a some index+constraint combinations even if the initial
** baseline limit was exhausted by prior tables of the join.
*/
#ifndef SQLITE_QUERY_PLANNER_LIMIT
# define SQLITE_QUERY_PLANNER_LIMIT 20000
#endif
#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR
# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
#endif
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
+1 -1
View File
@@ -1117,7 +1117,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->pTab = 0;
pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
+7 -7
View File
@@ -281,7 +281,7 @@ static int isLikeOrGlob(
){
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
|| IsVirtual(pLeft->y.pTab) /* Value might be numeric */
){
sqlite3ExprDelete(db, pPrefix);
sqlite3ValueFree(pVal);
@@ -382,7 +382,7 @@ static int isAuxiliaryVtabOperator(
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
for(i=0; i<ArraySize(aOp); i++){
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
@@ -404,12 +404,12 @@ static int isAuxiliaryVtabOperator(
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
@@ -427,10 +427,10 @@ static int isAuxiliaryVtabOperator(
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
res++;
}
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
res++;
SWAP(Expr*, pLeft, pRight);
}
@@ -1583,7 +1583,7 @@ void sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
pColRef->pTab = pTab;
pColRef->y.pTab = pTab;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
+6 -4
View File
@@ -624,12 +624,12 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
switch( pExpr->op ){
case TK_FUNCTION:
if( pExpr->pWin==0 ){
if( !ExprHasProperty(pExpr, EP_WinFunc) ){
break;
}else{
Window *pWin;
for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
if( pExpr->pWin==pWin ){
if( pExpr->y.pWin==pWin ){
assert( pWin->pOwner==pExpr );
return WRC_Prune;
}
@@ -959,11 +959,13 @@ windowAllocErr:
*/
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
if( p ){
assert( p->op==TK_FUNCTION );
/* This routine is only called for the parser. If pWin was not
** allocated due to an OOM, then the parser would fail before ever
** invoking this routine */
if( ALWAYS(pWin) ){
p->pWin = pWin;
p->y.pWin = pWin;
ExprSetProperty(p, EP_WinFunc);
pWin->pOwner = p;
if( p->flags & EP_Distinct ){
sqlite3ErrorMsg(pParse,
@@ -2126,7 +2128,7 @@ static void windowCodeDefaultStep(
*/
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
Window *pNew = 0;
if( p ){
if( ALWAYS(p) ){
pNew = sqlite3DbMallocZero(db, sizeof(Window));
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
+19 -1
View File
@@ -875,5 +875,23 @@ do_execsql_test alter-16.2 {
SELECT * FROM t16a_rn ORDER BY a;
} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
finish_test
# 2018-09-16 ticket b41031ea2b5372378cb3d2d43cf9fe2a4a5c2510
#
ifcapable rtree {
db close
sqlite3 db :memory:
do_execsql_test alter-17.100 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1);
INSERT INTO t1 VALUES(1,'apple'),(2,'fig'),(3,'pear');
INSERT INTO t2 VALUES(1,1.0,2.0),(2,2.0,3.0),(3,1.5,3.5);
CREATE TRIGGER r1 AFTER UPDATE ON t1 BEGIN
DELETE FROM t2 WHERE id = OLD.a;
END;
ALTER TABLE t1 RENAME TO t3;
UPDATE t3 SET b='peach' WHERE a=2;
SELECT * FROM t2 ORDER BY 1;
} {1 1.0 2.0 3 1.5 3.5}
}
finish_test
+1 -1
View File
@@ -24,7 +24,7 @@ set testprefix alterauth
set ::auth [list]
proc xAuth {type args} {
if {$type == "SQLITE_ALTER_TABLE"} {
lappend ::auth [concat $type $args]
lappend ::auth [concat $type [lrange $args 0 3]]
}
return SQLITE_OK
}
+79
View File
@@ -0,0 +1,79 @@
# 2018 October 6
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
finish_test
return
}
set testprefix alterauth2
set ::auth [list]
proc xAuth {type args} {
lappend ::auth [concat $type [lrange $args 0 3]]
if {$type=="SQLITE_READ" && [lindex $args 0] == "t2"} breakpoint
return SQLITE_OK
}
db auth xAuth
proc do_auth_test {tn sql authcode} {
set script "
set ::auth \[list\]
execsql {$sql}
lsort -unique \[set ::auth\]
"
set normal [list {*}$authcode]
uplevel [list do_test $tn $script $normal]
}
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
DELETE FROM t1 WHERE a<new.a;
END;
CREATE TEMP TRIGGER tr2 AFTER UPDATE OF a, b ON t1 BEGIN
UPDATE t1 SET a=a+1 WHERE new.b<b;
END;
}
do_auth_test 1.1 {
ALTER TABLE t1 RENAME TO t2;
} {
{SQLITE_ALTER_TABLE main t1 {} {}}
}
do_auth_test 1.2 {
ALTER TABLE t2 RENAME a TO aaa;
} {
{SQLITE_ALTER_TABLE main t2 {} {}}
}
do_auth_test 1.3 {
ALTER TABLE t2 ADD COLUMN d;
} {
{SQLITE_ALTER_TABLE main t2 {} {}}
}
do_auth_test 1.4 {
ALTER TABLE t2 RENAME TO t3;
} {
{SQLITE_ALTER_TABLE main t2 {} {}}
}
finish_test
+470
View File
@@ -0,0 +1,470 @@
# 2018 September 20
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix alterlegacy
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
finish_test
return
}
do_execsql_test 1.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE t1(a, b, CHECK(t1.a != t1.b));
CREATE TABLE t2(a, b);
CREATE INDEX t2expr ON t2(a) WHERE t2.b>0;
}
do_execsql_test 1.1 {
SELECT sql FROM sqlite_master
} {
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
{CREATE TABLE t2(a, b)}
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
}
# Legacy behavior is to corrupt the schema in this case, as the table name in
# the CHECK constraint is incorrect after "t1" is renamed. This version is
# slightly different - it rejects the change and rolls back the transaction.
do_catchsql_test 1.2 {
ALTER TABLE t1 RENAME TO t1new;
} {1 {no such column: t1.a}}
do_execsql_test 1.3 {
CREATE TABLE t3(c, d);
ALTER TABLE t3 RENAME TO t3new;
DROP TABLE t3new;
}
do_execsql_test 1.4 {
SELECT sql FROM sqlite_master
} {
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
{CREATE TABLE t2(a, b)}
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
}
do_catchsql_test 1.3 {
ALTER TABLE t2 RENAME TO t2new;
} {1 {no such column: t2.b}}
do_execsql_test 1.4 {
SELECT sql FROM sqlite_master
} {
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
{CREATE TABLE t2(a, b)}
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
}
#-------------------------------------------------------------------------
reset_db
ifcapable vtab {
register_echo_module db
do_execsql_test 2.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE abc(a, b, c);
INSERT INTO abc VALUES(1, 2, 3);
CREATE VIRTUAL TABLE eee USING echo('abc');
SELECT * FROM eee;
} {1 2 3}
do_execsql_test 2.1 {
ALTER TABLE eee RENAME TO fff;
SELECT * FROM fff;
} {1 2 3}
db close
sqlite3 db test.db
do_catchsql_test 2.2 {
ALTER TABLE fff RENAME TO ggg;
} {1 {no such module: echo}}
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE txx(a, b, c);
INSERT INTO txx VALUES(1, 2, 3);
CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx;
CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one;
CREATE VIEW temp.ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx;
}
do_execsql_test 3.1.1 {
SELECT * FROM vvv;
} {1 2 3}
do_execsql_test 3.1.2a {
ALTER TABLE txx RENAME TO "t xx";
}
do_catchsql_test 3.1.2b {
SELECT * FROM vvv;
} {1 {no such table: main.txx}}
do_execsql_test 3.1.3 {
SELECT sql FROM sqlite_master WHERE name='vvv';
} {{CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx}}
do_catchsql_test 3.2.1 {
SELECT * FROM uuu;
} {1 {no such table: main.txx}}
do_execsql_test 3.2.2 {
SELECT sql FROM sqlite_master WHERE name='uuu';;
} {{CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one}}
do_catchsql_test 3.3.1 {
SELECT * FROM ttt;
} {1 {no such table: txx}}
do_execsql_test 3.3.2 {
SELECT sql FROM sqlite_temp_master WHERE name='ttt';
} {{CREATE VIEW ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
PRAGMA legacy_alter_table = 1;
CREATE table t1(x, y);
CREATE table t2(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
SELECT t1.x, * FROM t1, t2;
INSERT INTO t2 VALUES(new.x, new.y);
END;
}
do_execsql_test 4.1 {
INSERT INTO t1 VALUES(1, 1);
ALTER TABLE t1 RENAME TO t11;
}
do_catchsql_test 4.1a {
INSERT INTO t11 VALUES(2, 2);
} {1 {no such table: main.t1}}
do_execsql_test 4.1b {
ALTER TABLE t11 RENAME TO t1;
ALTER TABLE t2 RENAME TO t22;
}
do_catchsql_test 4.1c {
INSERT INTO t1 VALUES(3, 3);
} {1 {no such table: main.t2}}
proc squish {a} {
string trim [regsub -all {[[:space:]][[:space:]]*} $a { }]
}
db func squish squish
do_test 4.2 {
execsql { SELECT squish(sql) FROM sqlite_master WHERE name = 'tr1' }
} [list [squish {
CREATE TRIGGER tr1 AFTER INSERT ON "t1" BEGIN
SELECT t1.x, * FROM t1, t2;
INSERT INTO t2 VALUES(new.x, new.y);
END
}]]
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE t9(a, b, c);
CREATE TABLE t10(a, b, c);
CREATE TEMP TABLE t9(a, b, c);
CREATE TRIGGER temp.t9t AFTER INSERT ON temp.t9 BEGIN
INSERT INTO t10 VALUES(new.a, new.b, new.c);
END;
INSERT INTO temp.t9 VALUES(1, 2, 3);
SELECT * FROM t10;
} {1 2 3}
do_execsql_test 5.1 {
ALTER TABLE temp.t9 RENAME TO 't1234567890'
}
do_execsql_test 5.2 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t2 VALUES(3, 4);
CREATE VIEW v AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2;
SELECT * FROM v;
} {1 2 3 4}
do_execsql_test 5.3 {
ALTER TABLE t2 RENAME TO one;
} {}
do_catchsql_test 5.4 {
SELECT * FROM v
} {1 {no such table: main.t2}}
do_execsql_test 5.5 {
ALTER TABLE one RENAME TO t2;
DROP VIEW v;
CREATE VIEW temp.vv AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2;
SELECT * FROM vv;
} {1 2 3 4}
do_execsql_test 5.6 {
ALTER TABLE t2 RENAME TO one;
} {}
do_catchsql_test 5.7 {
SELECT * FROM vv
} {1 {no such table: t2}}
#-------------------------------------------------------------------------
ifcapable vtab {
register_tcl_module db
proc tcl_command {method args} {
switch -- $method {
xConnect {
return "CREATE TABLE t1(a, b, c)"
}
}
return {}
}
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE x1 USING tcl(tcl_command);
}
do_execsql_test 6.1 {
ALTER TABLE x1 RENAME TO x2;
SELECT sql FROM sqlite_master WHERE name = 'x2'
} {{CREATE VIRTUAL TABLE "x2" USING tcl(tcl_command)}}
do_execsql_test 7.1 {
CREATE TABLE ddd(db, sql, zOld, zNew, bTemp);
INSERT INTO ddd VALUES(
'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', 'ddd', NULL, 0
), (
'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', NULL, 'eee', 0
), (
'main', NULL, 'ddd', 'eee', 0
);
} {}
}
#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 8.1 {
PRAGMA legacy_alter_table = 1;
ATTACH 'test.db2' AS aux;
PRAGMA foreign_keys = on;
CREATE TABLE aux.p1(a INTEGER PRIMARY KEY, b);
CREATE TABLE aux.c1(x INTEGER PRIMARY KEY, y REFERENCES p1(a));
INSERT INTO aux.p1 VALUES(1, 1);
INSERT INTO aux.p1 VALUES(2, 2);
INSERT INTO aux.c1 VALUES(NULL, 2);
CREATE TABLE aux.c2(x INTEGER PRIMARY KEY, y REFERENCES c1(a));
}
do_execsql_test 8.2 {
ALTER TABLE aux.p1 RENAME TO ppp;
}
do_execsql_test 8.2 {
INSERT INTO aux.c1 VALUES(NULL, 1);
SELECT sql FROM aux.sqlite_master WHERE name = 'c1';
} {{CREATE TABLE c1(x INTEGER PRIMARY KEY, y REFERENCES "ppp"(a))}}
reset_db
do_execsql_test 9.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE t1(a, b, c);
CREATE VIEW v1 AS SELECT * FROM t2;
}
do_execsql_test 9.1 {
ALTER TABLE t1 RENAME TO t3;
} {}
do_execsql_test 9.1b {
ALTER TABLE t3 RENAME TO t1;
} {}
do_execsql_test 9.2 {
DROP VIEW v1;
CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN
INSERT INTO t2 VALUES(new.a);
END;
}
do_execsql_test 9.3 {
ALTER TABLE t1 RENAME TO t3;
} {}
forcedelete test.db2
do_execsql_test 9.4 {
ALTER TABLE t3 RENAME TO t1;
DROP TRIGGER tr;
ATTACH 'test.db2' AS aux;
CREATE TRIGGER tr AFTER INSERT ON t1 WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END;
CREATE TABLE aux.t1(x);
CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END;
}
do_execsql_test 9.5 {
ALTER TABLE main.t1 RENAME TO t3;
}
do_execsql_test 9.6 {
SELECT sql FROM sqlite_temp_master;
SELECT sql FROM sqlite_master WHERE type='trigger';
} {
{CREATE TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END}
{CREATE TRIGGER tr AFTER INSERT ON "t3" WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END}
}
#-------------------------------------------------------------------------
reset_db
ifcapable fts5 {
do_execsql_test 10.0 {
PRAGMA legacy_alter_table = 1;
CREATE VIRTUAL TABLE fff USING fts5(x, y, z);
}
do_execsql_test 10.1 {
BEGIN;
INSERT INTO fff VALUES('a', 'b', 'c');
ALTER TABLE fff RENAME TO ggg;
COMMIT;
}
do_execsql_test 10.2 {
SELECT * FROM ggg;
} {a b c}
}
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
db func trigger trigger
set ::trigger [list]
proc trigger {args} {
lappend ::trigger $args
}
do_execsql_test 11.0 {
PRAGMA legacy_alter_table = 1;
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t1(a, b, c);
CREATE TABLE main.t1(a, b, c);
CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN
SELECT trigger(new.a, new.b, new.c);
END;
}
do_execsql_test 11.1 {
INSERT INTO main.t1 VALUES(1, 2, 3);
INSERT INTO aux.t1 VALUES(4, 5, 6);
}
do_test 11.2 { set ::trigger } {{4 5 6}}
do_execsql_test 11.3 {
SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t1}
do_execsql_test 11.4 {
ALTER TABLE main.t1 RENAME TO t2;
SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t1}
do_execsql_test 11.5 {
ALTER TABLE aux.t1 RENAME TO t2;
SELECT name, tbl_name FROM sqlite_temp_master;
} {tr t2}
do_execsql_test 11.6 {
INSERT INTO aux.t2 VALUES(7, 8, 9);
}
do_test 11.7 { set ::trigger } {{4 5 6} {7 8 9}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 12.0 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE t1(a);
CREATE TABLE t2(w);
CREATE TRIGGER temp.r1 AFTER INSERT ON main.t2 BEGIN
INSERT INTO t1(a) VALUES(new.w);
END;
CREATE TEMP TABLE t2(x);
}
do_execsql_test 12.1 {
ALTER TABLE main.t2 RENAME TO t3;
}
do_execsql_test 12.2 {
INSERT INTO t3 VALUES('WWW');
SELECT * FROM t1;
} {WWW}
#-------------------------------------------------------------------------
reset_db
ifcapable rtree {
do_execsql_test 14.0 {
PRAGMA legacy_alter_table = 1;
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB);
CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable"
WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN
DELETE FROM rt WHERE id = OLD."fid";
END;
INSERT INTO mytable VALUES(1, X'abcd');
}
do_execsql_test 14.1 {
UPDATE mytable SET geom = X'1234'
}
do_execsql_test 14.2 {
ALTER TABLE mytable RENAME TO mytable_renamed;
}
do_execsql_test 14.3 {
CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN
DELETE FROM rt WHERE id=(SELECT min(id) FROM rt);
END;
}
do_execsql_test 14.4 {
ALTER TABLE mytable_renamed RENAME TO mytable2;
}
}
reset_db
do_execsql_test 14.5 {
PRAGMA legacy_alter_table = 1;
CREATE TABLE t1(a, b, c);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN
SELECT a, b FROM v1;
END;
}
do_execsql_test 14.6 {
ALTER TABLE t1 RENAME TO tt1;
}
finish_test
+1 -1
View File
@@ -19,7 +19,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable||!memdebug {
ifcapable !altertable {
finish_test
return
}
+26
View File
@@ -72,4 +72,30 @@ do_faultsim_test 3 -prep {
} -test {
faultsim_test_result {0 {}}
}
reset_db
do_execsql_test 4.0 {
CREATE TABLE rr(a, b);
CREATE VIEW vv AS SELECT * FROM rr;
CREATE TRIGGER vv1 INSTEAD OF INSERT ON vv BEGIN
SELECT 1, 2, 3;
END;
CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
INSERT INTO vv VALUES(new.a, new.b);
END;
} {}
faultsim_save_and_close
do_faultsim_test 4 -faults oom-* -prep {
faultsim_restore_and_reopen
execsql { SELECT * FROM sqlite_master }
} -body {
execsql {
ALTER TABLE rr RENAME a TO c;
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
+93
View File
@@ -411,5 +411,98 @@ do_catchsql_test 13.2 {
ALTER TABLE t2 RENAME b TO y;
} {1 {error in trigger tr1 after rename: ambiguous column name: y}}
#-------------------------------------------------------------------------
reset_db
ifcapable rtree {
do_execsql_test 14.0 {
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB);
CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable"
WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN
DELETE FROM rt WHERE id = OLD."fid";
END;
INSERT INTO mytable VALUES(1, X'abcd');
}
do_execsql_test 14.1 {
UPDATE mytable SET geom = X'1234'
}
do_execsql_test 14.2 {
ALTER TABLE mytable RENAME TO mytable_renamed;
}
do_execsql_test 14.3 {
CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN
DELETE FROM rt WHERE id=(SELECT min(id) FROM rt);
END;
}
do_execsql_test 14.4 {
ALTER TABLE mytable_renamed RENAME TO mytable2;
}
}
reset_db
do_execsql_test 14.5 {
CREATE TABLE t1(a, b, c);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN
SELECT a, b FROM v1;
END;
}
do_execsql_test 14.6 {
ALTER TABLE t1 RENAME TO tt1;
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 15.0 {
CREATE TABLE t1(a integer NOT NULL PRIMARY KEY);
CREATE VIEW v1 AS SELECT a FROM t1;
CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
UPDATE t1 SET a = NEW.a;
END;
CREATE TRIGGER tr2 INSTEAD OF INSERT ON v1 BEGIN
SELECT new.a;
END;
CREATE TABLE t2 (b);
}
do_execsql_test 15.1 {
INSERT INTO v1 VALUES(1);
ALTER TABLE t2 RENAME TO t3;
}
do_execsql_test 15.2 {
CREATE TABLE x(f1 integer NOT NULL);
CREATE VIEW y AS SELECT f1 AS f1 FROM x;
CREATE TRIGGER t INSTEAD OF UPDATE OF f1 ON y BEGIN
UPDATE x SET f1 = NEW.f1;
END;
CREATE TABLE z (f1 integer NOT NULL PRIMARY KEY);
ALTER TABLE z RENAME TO z2;
}
do_execsql_test 15.3 {
INSERT INTO x VALUES(1), (2), (3);
ALTER TABLE x RENAME f1 TO f2;
SELECT * FROM x;
} {1 2 3}
do_execsql_test 15.4 {
UPDATE y SET f1 = 'x' WHERE f1 = 1;
SELECT * FROM x;
} {x x x}
do_execsql_test 15.5 {
SELECT sql FROM sqlite_master WHERE name = 'y';
} {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}}
finish_test
+46
View File
@@ -0,0 +1,46 @@
# 2018 September 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altertab
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
finish_test
return
}
ifcapable fts5 {
do_execsql_test 1.0 {
CREATE TABLE rr(a, b);
CREATE VIRTUAL TABLE ff USING fts5(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
INSERT INTO ff VALUES(new.a, new.b);
END;
INSERT INTO rr VALUES('hello', 'world');
SELECT * FROM ff;
} {hello world}
do_execsql_test 1.1 {
ALTER TABLE ff RENAME TO ffff;
}
do_execsql_test 1.2 {
INSERT INTO rr VALUES('in', 'tcl');
SELECT * FROM ffff;
} {hello world in tcl}
}
finish_test
+1 -1
View File
@@ -18,7 +18,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !memdebug||!attach {
ifcapable !attach {
finish_test
return
}
+2 -1
View File
@@ -2598,7 +2598,8 @@ do_test auth-8.2 {
# invocation with no column name specified, compilation fails.
#
set ::authargs [list]
proc auth {op a b c d} {
proc auth {op args} {
foreach {a b c d} $args break
lappend ::authargs $op $a $b $c $d
if {$op == "SQLITE_READ"} { return "SQLITE_DENY" }
return "SQLITE_OK"
-2
View File
@@ -811,7 +811,6 @@ foreach {code english} $code2english {
# Test the error message when a "real" out of memory occurs.
if { [permutation] != "nofaultsim" } {
ifcapable memdebug {
do_test capi3-10-1 {
sqlite3 db test.db
set DB [sqlite3_connection_pointer db]
@@ -849,7 +848,6 @@ ifcapable memdebug {
db close
sqlite3_memdebug_fail -1
}
}
# The following tests - capi3-11.* - test that a COMMIT or ROLLBACK
# statement issued while there are still outstanding VMs that are part of
-2
View File
@@ -757,7 +757,6 @@ foreach {code english} $code2english {
# Test the error message when a "real" out of memory occurs.
if { [permutation] != "nofaultsim" } {
ifcapable memdebug {
do_test capi3c-10-1 {
sqlite3 db test.db
set DB [sqlite3_connection_pointer db]
@@ -777,7 +776,6 @@ ifcapable memdebug {
db close
sqlite3_memdebug_fail -1
}
}
# The following tests - capi3c-11.* - test that a COMMIT or ROLLBACK
# statement issued while there are still outstanding VMs that are part of
+1 -1
View File
@@ -20,7 +20,7 @@ source $testdir/tester.tcl
# Only run these tests if memory debugging is turned on.
#
ifcapable !memdebug||!crashtest||!memorymanage {
ifcapable !crashtest||!memorymanage {
puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..."
finish_test
return
-5
View File
@@ -17,11 +17,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !memdebug {
finish_test
return
}
source $testdir/malloc_common.tcl
source $testdir/fuzz_common.tcl
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -16,7 +16,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix incrblob_err
ifcapable {!incrblob || !memdebug || !tclvar} {
ifcapable {!incrblob || !tclvar} {
finish_test
return
}
+70
View File
@@ -159,5 +159,75 @@ do_execsql_test 3.4.6 {
SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary;
} {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4}
# 2014-09-15: Verify that UPDATEs of columns not referenced by a
# index on expression do not modify the index.
#
unset -nocomplain cnt
set cnt 0
proc refcnt {x} {
global cnt
incr cnt
return $x
}
db close
sqlite3 db :memory:
db function refcnt -deterministic refcnt
do_test 4.100 {
db eval {
CREATE TABLE t1(a,b,c,d,e,f);
CREATE INDEX t1abc ON t1(refcnt(a+b+c));
}
set ::cnt
} {0}
do_test 4.110 {
db eval {INSERT INTO t1 VALUES(1,2,3,4,5,6);}
set ::cnt
# The refcnt() function is invoked once to compute the index value
} {1}
do_test 4.120 {
set ::cnt 0
db eval {UPDATE t1 SET b=b+1;}
set ::cnt
# The refcnt() function is invoked twice, once to remove the old index
# entry and a second time to insert the new one.
} {2}
do_test 4.130 {
set ::cnt 0
db eval {UPDATE t1 SET d=d+1;}
set ::cnt
# Refcnt() should not be invoked because that index does not change.
} {0}
# Additional test cases to show that UPDATE does not modify indexes that
# do not involve unchanged columns.
#
load_static_extension db explain
do_execsql_test 4.200 {
CREATE TABLE t2(a,b,c,d,e,f);
INSERT INTO t2 VALUES(2,3,4,5,6,7);
CREATE INDEX t2abc ON t2(a+b+c);
CREATE INDEX t2cd ON t2(c*d);
CREATE INDEX t2def ON t2(d,e+25*f);
SELECT sqlite_master.name
FROM sqlite_master, explain('UPDATE t2 SET b=b+1')
WHERE explain.opcode LIKE 'Open%'
AND sqlite_master.rootpage=explain.p2
ORDER BY 1;
} {t2 t2abc}
do_execsql_test 4.210 {
SELECT sqlite_master.name
FROM sqlite_master, explain('UPDATE t2 SET c=c+1')
WHERE explain.opcode LIKE 'Open%'
AND sqlite_master.rootpage=explain.p2
ORDER BY 1;
} {t2 t2abc t2cd}
do_execsql_test 4.220 {
SELECT sqlite_master.name
FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL')
WHERE explain.opcode LIKE 'Open%'
AND sqlite_master.rootpage=explain.p2
ORDER BY 1;
} {t2 t2abc t2cd t2def}
finish_test
+2
View File
@@ -130,12 +130,14 @@ do_eqp_test like3-5.101 {
do_execsql_test like3-5.110 {
SELECT x FROM t5a WHERE x LIKE '/a%';
} {/abc}
ifcapable !icu {
do_eqp_test like3-5.111 {
SELECT x FROM t5a WHERE x LIKE '/a%';
} {
QUERY PLAN
`--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x<?)
}
}
do_execsql_test like3-5.120 {
SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {123}
+4 -1
View File
@@ -24,7 +24,7 @@ ifcapable !lookaside {
# The tests in this file configure the lookaside allocator after a
# connection is opened. This will not work if there is any "presql"
# configured (SQL run within the [sqlite3] wrapper in tester.tcl).
if {[info exists ::G(perm:presql)]} {
if {[info exists ::G(perm:dbconfig)] && $::G(perm:dbconfig)!=""} {
finish_test
return
}
@@ -35,7 +35,9 @@ catch {db close}
sqlite3_shutdown
sqlite3_initialize
autoinstall_test_functions
sqlite3 db test.db
db cache size 4
# Make sure sqlite3_db_config() and sqlite3_db_status are working.
#
@@ -99,6 +101,7 @@ do_test lookaside-2.2 {
expr {$x==0 && $y<$z && $z>10 && $z<100}
} {1}
do_test lookaside-2.3 {
db eval {SELECT 1}
sqlite3_db_config_lookaside db 0 50 50
} {5} ;# SQLITE_BUSY
do_test lookaside-2.4 {
+253
View File
@@ -0,0 +1,253 @@
package require sqlite3
package require Tk
#############################################################################
# Code to set up scrollbars for widgets. This is generic, boring stuff.
#
namespace eval autoscroll {
proc scrollable {widget path args} {
::ttk::frame $path
set w [$widget ${path}.widget {*}$args]
set vs [::ttk::scrollbar ${path}.vs]
set hs [::ttk::scrollbar ${path}.hs -orient horizontal]
grid $w -row 0 -column 0 -sticky nsew
grid rowconfigure $path 0 -weight 1
grid columnconfigure $path 0 -weight 1
set grid [list grid $vs -row 0 -column 1 -sticky nsew]
$w configure -yscrollcommand [list ::autoscroll::scrollcommand $grid $vs]
$vs configure -command [list $w yview]
set grid [list grid $hs -row 1 -column 0 -sticky nsew]
$w configure -xscrollcommand [list ::autoscroll::scrollcommand $grid $hs]
$hs configure -command [list $w xview]
return $w
}
proc scrollcommand {grid sb args} {
$sb set {*}$args
set isRequired [expr {[lindex $args 0] != 0.0 || [lindex $args 1] != 1.0}]
if {$isRequired && ![winfo ismapped $sb]} {
{*}$grid
}
if {!$isRequired && [winfo ismapped $sb]} {
grid forget $sb
}
}
namespace export scrollable
}
namespace import ::autoscroll::*
#############################################################################
proc populate_text_widget {db} {
$::O(text) configure -state normal
set id [lindex [$::O(tree) selection] 0]
set frame [lindex $id end]
set line [$db one {SELECT line FROM frame WHERE frame = $frame}]
if {$line ne ""} {
foreach {file line} [split $line :] {}
set content [$db one "SELECT content FROM file WHERE name = '$file'"]
$::O(text) delete 0.0 end
set iLine 1
foreach L [split $content "\n"] {
if {$iLine == $line} {
$::O(text) insert end "$L\n" highlight
} else {
$::O(text) insert end "$L\n"
}
incr iLine
}
$::O(text) yview -pickplace ${line}.0
}
$::O(text) configure -state disabled
}
proc populate_index {db} {
$::O(text) configure -state normal
$::O(text) delete 0.0 end
$::O(text) insert end "\n\n"
set L [format " % -40s%12s%12s\n" "Test Case" "Allocations" "Bytes"]
$::O(text) insert end $L
$::O(text) insert end " [string repeat - 64]\n"
$db eval {
SELECT 'TOTAL' AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes
FROM malloc
UNION ALL
SELECT ztest AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes
FROM malloc
GROUP BY ztest
ORDER BY 3 DESC
} {
set tags [list $ztest]
if {$ztest eq $::O(current)} {
lappend tags highlight
}
set L [format " % -40s%12s%12s\n" $ztest $calls $bytes]
$::O(text) insert end $L $tags
$::O(text) tag bind $ztest <1> [list populate_tree_widget $db $ztest]
$::O(text) tag bind $ztest <Enter> [list $::O(text) configure -cursor hand2]
$::O(text) tag bind $ztest <Leave> [list $::O(text) configure -cursor ""]
}
$::O(text) configure -state disabled
}
proc sort_tree_compare {iLeft iRight} {
global O
switch -- [expr (int($O(tree_sort)/2))] {
0 {
set left [$O(tree) item $iLeft -text]
set right [$O(tree) item $iRight -text]
set res [string compare $left $right]
}
1 {
set left [lindex [$O(tree) item $iLeft -values] 0]
set right [lindex [$O(tree) item $iRight -values] 0]
set res [expr $left - $right]
}
2 {
set left [lindex [$O(tree) item $iLeft -values] 1]
set right [lindex [$O(tree) item $iRight -values] 1]
set res [expr $left - $right]
}
}
if {$O(tree_sort)&0x01} {
set res [expr -1 * $res]
}
return $res
}
proc sort_tree {iMode} {
global O
if {$O(tree_sort) == $iMode} {
incr O(tree_sort)
} else {
set O(tree_sort) $iMode
}
set T $O(tree)
set items [$T children {}]
set items [lsort -command sort_tree_compare $items]
for {set ii 0} {$ii < [llength $items]} {incr ii} {
$T move [lindex $items $ii] {} $ii
}
}
proc trim_frames {stack} {
while {[info exists ::O(ignore.[lindex $stack 0])]} {
set stack [lrange $stack 1 end]
}
return $stack
}
proc populate_tree_widget {db zTest} {
$::O(tree) delete [$::O(tree) children {}]
for {set ii 0} {$ii < 15} {incr ii} {
$db eval {
SELECT
sum(ncall) AS calls,
sum(nbyte) AS bytes,
trim_frames(lrange(lstack, 0, $ii)) AS stack
FROM malloc
WHERE (zTest = $zTest OR $zTest = 'TOTAL') AND llength(lstack)>$ii
GROUP BY stack
HAVING stack != ''
} {
set parent_id [lrange $stack 0 end-1]
set frame [lindex $stack end]
set line [$db one {SELECT line FROM frame WHERE frame = $frame}]
set line [lindex [split $line /] end]
set v [list $calls $bytes]
catch {
$::O(tree) insert $parent_id end -id $stack -text $line -values $v
}
}
}
set ::O(current) $zTest
populate_index $db
}
set O(tree_sort) 0
::ttk::panedwindow .pan -orient horizontal
set O(tree) [scrollable ::ttk::treeview .pan.tree]
frame .pan.right
set O(text) [scrollable text .pan.right.text]
button .pan.right.index -command {populate_index mddb} -text "Show Index"
pack .pan.right.index -side top -fill x
pack .pan.right.text -fill both -expand true
$O(text) tag configure highlight -background wheat
$O(text) configure -wrap none -height 35
.pan add .pan.tree
.pan add .pan.right
$O(tree) configure -columns {calls bytes}
$O(tree) heading #0 -text Line -anchor w -command {sort_tree 0}
$O(tree) heading calls -text Calls -anchor w -command {sort_tree 2}
$O(tree) heading bytes -text Bytes -anchor w -command {sort_tree 4}
$O(tree) column #0 -width 150
$O(tree) column calls -width 100
$O(tree) column bytes -width 100
pack .pan -fill both -expand 1
#--------------------------------------------------------------------
# Open the database containing the malloc data. The user specifies the
# database to use by passing the file-name on the command line.
#
proc open_database {} {
if {[info exists ::BUILTIN]} {
sqlite3 mddb :memory:
mddb eval $::BUILTIN
wm title . $::argv0
} else {
set zFilename [lindex $::argv 0]
if {$zFilename eq ""} {
set zFilename mallocs.sql
}
set fd [open $zFilename]
set zHdr [read $fd 15]
if {$zHdr eq "SQLite format 3"} {
close $fd
sqlite3 mddb $zFilename
} else {
seek $fd 0
sqlite3 mddb :memory:
mddb eval [read $fd]
close $fd
}
wm title . $zFilename
}
mddb function lrange -argcount 3 lrange
mddb function llength -argcount 1 llength
mddb function trim_frames -argcount 1 trim_frames
mddb eval {
SELECT frame FROM frame
WHERE line LIKE '%malloc.c:%' OR line LIKE '%mem2.c:%'
} {
set ::O(ignore.$frame) 1
}
}
open_database
bind $O(tree) <<TreeviewSelect>> [list populate_text_widget mddb]
populate_tree_widget mddb [mddb one {SELECT zTest FROM malloc LIMIT 1}]
+67 -63
View File
@@ -48,6 +48,13 @@ proc test_suite {name args} {
set options([lindex $o 0]) $v
}
# Transform "-presql" into a "dbconfig" script
#
if {[info exists options(-presql)]} {
append options(-dbconfig) "\n\$::dbhandle eval { $options(-presql) }"
unset options(-presql)
}
set ::testspec($name) [array get options]
lappend ::testsuitelist $name
}
@@ -289,12 +296,6 @@ test_suite "window" -prefix "" -description {
test_set [glob -nocomplain $::testdir/window*.test]
]
test_suite "alter" -prefix "" -description {
All ALTER function related tests .
} -files [
test_set [glob -nocomplain $::testdir/alter*.test]
]
test_suite "lsm1" -prefix "" -description {
All LSM1 tests.
} -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test]
@@ -560,21 +561,12 @@ test_suite "singlethread" -description {
test_suite "nomutex" -description {
Tests run with the SQLITE_OPEN_MULTITHREADED flag passed to sqlite3_open().
} -initialize {
rename sqlite3 sqlite3_nomutex
proc sqlite3 {args} {
if {[string range [lindex $args 0] 0 0] ne "-"} {
lappend args -fullmutex 0 -nomutex 1
}
uplevel [concat sqlite3_nomutex $args]
}
set ::G(perm:sqlite3_args) [list -fullmutex 0 -nomutex 1]
} -files {
delete.test delete2.test insert.test rollback.test select1.test
select2.test trans.test update.test vacuum.test types.test
types2.test types3.test
} -shutdown {
rename sqlite3 {}
rename sqlite3_nomutex sqlite3
}
}
# Run some tests in SQLITE_CONFIG_MULTITHREAD mode.
#
@@ -603,20 +595,11 @@ test_suite "multithread" -description {
test_suite "fullmutex" -description {
Tests run in SQLITE_OPEN_FULLMUTEX mode
} -initialize {
rename sqlite3 sqlite3_fullmutex
proc sqlite3 {args} {
if {[string range [lindex $args 0] 0 0] ne "-"} {
lappend args -nomutex 0 -fullmutex 1
}
uplevel [concat sqlite3_fullmutex $args]
}
set ::G(perm:sqlite3_args) [list -nomutex 0 -fullmutex 1]
} -files {
delete.test delete2.test insert.test rollback.test select1.test
select2.test trans.test update.test vacuum.test types.test
types2.test types3.test
} -shutdown {
rename sqlite3 {}
rename sqlite3_fullmutex sqlite3
}
# Run some tests using the "onefile" demo.
@@ -624,19 +607,10 @@ test_suite "fullmutex" -description {
test_suite "onefile" -description {
Run some tests using the "test_onefile.c" demo
} -initialize {
rename sqlite3 sqlite3_onefile
proc sqlite3 {args} {
if {[string range [lindex $args 0] 0 0] ne "-"} {
lappend args -vfs fs
}
uplevel [concat sqlite3_onefile $args]
}
set ::G(perm:sqlite3_args) [list -vfs fs]
} -files {
conflict.test insert.test insert2.test insert3.test
rollback.test select1.test select2.test select3.test
} -shutdown {
rename sqlite3 {}
rename sqlite3_onefile sqlite3
}
# Run some tests using UTF-16 databases.
@@ -938,17 +912,8 @@ ifcapable threadsafe {
test_suite "safe_append" -description {
Run some tests on a SAFE_APPEND file-system.
} -initialize {
rename sqlite3 sqlite3_safeappend
proc sqlite3 {args} {
if {[string range [lindex $args 0] 0 0] ne "-"} {
lappend args -vfs devsym
}
uplevel [concat sqlite3_safeappend $args]
}
set ::G(perm:sqlite3_args) [list -vfs devsym]
sqlite3_simulate_device -char safe_append
} -shutdown {
rename sqlite3 {}
rename sqlite3_shutdown sqlite3
} -files [
test_set $::allquicktests shared_err.test -exclude async3.test
]
@@ -1115,16 +1080,20 @@ test_suite "sorterref" -prefix "" -description {
# -description TITLE
# -initialize SCRIPT
# -shutdown SCRIPT
# -presql SQL
# -files LIST-OF-FILES
# -prefix NAME
# -dbconfig SCRIPT
#
proc run_tests {name args} {
set options(-initialize) ""
set options(-shutdown) ""
set options(-prefix) ""
set options(-dbconfig) ""
array set options $args
set ::G(perm:name) $name
set ::G(perm:prefix) $options(-prefix)
set ::G(perm:presql) $options(-presql)
set ::G(isquick) 1
set ::G(perm:dbconfig) $options(-dbconfig)
@@ -1133,11 +1102,12 @@ proc run_tests {name args} {
if {[file tail $file] == $file} { set file [file join $::testdir $file] }
slave_test_file $file
uplevel $options(-shutdown)
unset -nocomplain ::G(perm:sqlite3_args)
}
unset ::G(perm:name)
unset ::G(perm:prefix)
unset ::G(perm:presql)
unset ::G(perm:dbconfig)
}
@@ -1152,19 +1122,29 @@ proc help {} {
puts "Usage: $::argv0 TESTSUITE ?TESTFILE?"
puts ""
puts "Available test-suites are:"
set iPos 0
foreach k $::testsuitelist {
if {[info exists ::testspec($k)]==0} {
puts " ----------------------------------------"
puts ""
} else {
array set o $::testspec($k)
puts "Test suite: \"$k\""
set d [string trim $o(-description)]
set d [regsub {\n *} $d "\n "]
puts " $d"
puts ""
if {[info exists ::testspec($k)]} {
switch $iPos {
0 {
puts ""
puts -nonewline " [format %-30s $k]"
}
1 {
puts -nonewline [format %-30s $k]
}
2 {
puts -nonewline $k
}
}
set iPos [expr (($iPos+1) % 3)]
}
}
puts ""
exit -1
}
@@ -1173,11 +1153,35 @@ if {[file tail $argv0] == "permutations.test"} {
if {[llength $argv]==0} {
help
} else {
# See if the first argument is a named test-suite.
#
set suite [file tail [lindex $argv 0]]
if {[info exists ::testspec($suite)]==0} help
if {[info exists ::testspec($suite)]} {
set S $::testspec($suite)
set i 1
} else {
set S [list]
set i 0
}
set extra ""
if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] }
eval run_tests $suite $::testspec($suite) $extra
if {$i < [llength $argv] && [string range [lindex $argv $i] 0 0]!="-" } {
set files [list]
for {} {$i < [llength $argv]} {incr i} {
set pattern [string map {% *} [lindex $argv $i]]
if {[string range $pattern 0 0]=="-"} break
foreach f $::alltests {
set tail [file tail $f]
if {[lsearch $files $f]<0 && [string match $pattern $tail]} {
lappend files $f
}
}
}
set extra [list -files $files]
}
eval run_tests $suite $S $extra
}
}
main $argv
+17 -19
View File
@@ -3757,25 +3757,23 @@ do_test printf-15.3 {
# Now test malloc() failure within a sqlite3_mprintf():
#
ifcapable memdebug {
foreach var {a b c d} {
set $var [string repeat $var 400]
}
set str1 "[string repeat A 360]%d%d%s"
set str2 [string repeat B 5000]
set zSuccess "[string repeat A 360]11[string repeat B 5000]"
foreach ::iRepeat {0 1} {
set nTestNum 1
while {1} {
sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat
set z [sqlite3_mprintf_str $str1 1 1 $str2]
set nFail [sqlite3_memdebug_fail -1 -benign nBenign]
do_test printf-malloc-$::iRepeat.$nTestNum {
expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)}
} {1}
if {$nFail == 0} break
incr nTestNum
}
foreach var {a b c d} {
set $var [string repeat $var 400]
}
set str1 "[string repeat A 360]%d%d%s"
set str2 [string repeat B 5000]
set zSuccess "[string repeat A 360]11[string repeat B 5000]"
foreach ::iRepeat {0 1} {
set nTestNum 1
while {1} {
sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat
set z [sqlite3_mprintf_str $str1 1 1 $str2]
set nFail [sqlite3_memdebug_fail -1 -benign nBenign]
do_test printf-malloc-$::iRepeat.$nTestNum {
expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)}
} {1}
if {$nFail == 0} break
incr nTestNum
}
}
+1
View File
@@ -79,6 +79,7 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_UNLOCK_NOTIFY
-DSQLITE_THREADSAFE
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
-DSQLITE_USER_AUTHENTICATION=1
}
"Secure-Delete" {
-O2
+1 -1
View File
@@ -378,7 +378,7 @@ do_test shell1-3.10.1 {
} {1 1 1}
do_test shell1-3.10.2 {
# we allow .help to take extra args (it is help after all)
set res [catchcmd "test.db" ".help BAD"]
set res [catchcmd "test.db" ".help *"]
# look for a few of the possible help commands
list [regexp {.help} $res] \
[regexp {.quit} $res] \
+3
View File
@@ -28,6 +28,9 @@ load_static_extension db remember
do_execsql_test tabfunc01-1.1 {
SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2;
} {1 | 3 | 5 | 7 | 9 |}
do_execsql_test tabfunc01-1.1b {
PRAGMA table_xinfo(generate_series);
} {0 value {} 0 {} 0 0 1 start {} 0 {} 0 1 2 stop {} 0 {} 0 1 3 step {} 0 {} 0 1}
do_execsql_test tabfunc01-1.2 {
SELECT *, '|' FROM generate_series LIMIT 5;
} {0 | 1 | 2 | 3 | 4 |}
+11 -15
View File
@@ -22,9 +22,7 @@ ifcapable !gettable {
return
}
ifcapable memdebug {
source $testdir/malloc_common.tcl
}
source $testdir/malloc_common.tcl
do_test tableapi-1.0 {
set ::dbx [sqlite3_open test.db]
@@ -239,18 +237,16 @@ do_test tableapi-99.0 {
sqlite3_close $::dbx
} {SQLITE_OK}
ifcapable memdebug {
do_malloc_test tableapi-7 -sqlprep {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES(1,2);
INSERT INTO t1 VALUES(3,4);
INSERT INTO t1 SELECT a+4, b+4 FROM t1;
INSERT INTO t1 SELECT a+8, b+8 FROM t1;
} -tclbody {
set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}]
if {[llength $r]<26} {error "out of memory"}
}
do_malloc_test tableapi-7 -sqlprep {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES(1,2);
INSERT INTO t1 VALUES(3,4);
INSERT INTO t1 SELECT a+4, b+4 FROM t1;
INSERT INTO t1 SELECT a+8, b+8 FROM t1;
} -tclbody {
set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}]
if {[llength $r]<26} {error "out of memory"}
}
finish_test
+7
View File
@@ -17,6 +17,8 @@
#
# $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
catch {sqlite3}
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -31,6 +33,11 @@ do_test tcl-1.1 {
regsub {really_sqlite3} $msg {sqlite3} msg
lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.1.1 {
set v [catch {sqlite3} msg]
regsub {really_sqlite3} $msg {sqlite3} msg
lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.2 {
set v [catch {db bogus} msg]
lappend v $msg
+23 -9
View File
@@ -456,6 +456,11 @@ if {[info exists cmdlinearg]==0} {
{^-+malloctrace=.+$} {
foreach {dummy cmdlinearg(malloctrace)} [split $a =] break
if {$cmdlinearg(malloctrace)} {
if {0==$::sqlite_options(memdebug)} {
set err "Error: --malloctrace=1 requires an SQLITE_MEMDEBUG build"
puts stderr $err
exit 1
}
sqlite3_memdebug_log start
}
}
@@ -1258,13 +1263,13 @@ proc finalize_testing {} {
output2 "Unfreed memory: [sqlite3_memory_used] bytes in\
[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
incr nErr
ifcapable memdebug||mem5||(mem3&&debug) {
ifcapable mem5||(mem3&&debug) {
output2 "Writing unfreed memory log to \"./memleak.txt\""
sqlite3_memdebug_dump ./memleak.txt
}
} else {
output2 "All memory allocations freed - no leaks"
ifcapable memdebug||mem5 {
ifcapable mem5 {
sqlite3_memdebug_dump ./memusage.txt
}
}
@@ -1275,15 +1280,14 @@ proc finalize_testing {} {
output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
}
if {$::cmdlinearg(malloctrace)} {
output2 "Writing mallocs.sql..."
memdebug_log_sql
output2 "Writing mallocs.tcl..."
memdebug_log_sql mallocs.tcl
sqlite3_memdebug_log stop
sqlite3_memdebug_log clear
if {[sqlite3_memory_used]>0} {
output2 "Writing leaks.sql..."
output2 "Writing leaks.tcl..."
sqlite3_memdebug_log sync
memdebug_log_sql leaks.sql
memdebug_log_sql leaks.tcl
}
}
foreach f [glob -nocomplain test.db-*-journal] {
@@ -2019,7 +2023,7 @@ proc dbcksum {db dbname} {
return [md5 $txt]
}
proc memdebug_log_sql {{filename mallocs.sql}} {
proc memdebug_log_sql {filename} {
set data [sqlite3_memdebug_log dump]
set nFrame [expr [llength [lindex $data 0]]-2]
@@ -2065,8 +2069,18 @@ proc memdebug_log_sql {{filename mallocs.sql}} {
append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n"
}
set escaped "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
set escaped [string map [list "{" "\\{" "}" "\\}"] $escaped]
set fd [open $filename w]
puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
puts $fd "set BUILTIN {"
puts $fd $escaped
puts $fd "}"
puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}"] $BUILTIN]}
set mtv [open $::testdir/malloctraceviewer.tcl]
set txt [read $mtv]
close $mtv
puts $fd $txt
close $fd
}
-7
View File
@@ -200,13 +200,6 @@ do_test triggerA-2.11 {
}
} {3 305 3 9900305 4 404 4 9900404 5 504 5 9900504}
# Only run the reamining tests if memory debugging is turned on.
#
ifcapable !memdebug {
puts "Skipping triggerA malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
finish_test
return
}
source $testdir/malloc_common.tcl
# Save a copy of the current database configuration.
+4 -3
View File
@@ -682,7 +682,8 @@ do_test view-25.1 {
}
proc authLogDelete {code arg1 arg2 arg3 arg4 args} {
if {$code=="SQLITE_DELETE" && [string match sqlite_stat* $arg1]} {
lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args]
# lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args]
lappend ::log [list $code $arg1 $arg2 $arg3 $arg4]
}
return SQLITE_OK
}
@@ -692,8 +693,8 @@ do_test view-25.1 {
set log
} {}
set res [list {SQLITE_DELETE sqlite_stat1 {} main {} {}}]
ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {} {}} }
set res [list {SQLITE_DELETE sqlite_stat1 {} main {}}]
ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {}} }
do_test view-25.2 {
set log ""
db eval {DROP TABLE t25;}
-5
View File
@@ -40,11 +40,6 @@ do_ioerr_test vtab_err-1 -tclprep {
COMMIT;
}
ifcapable !memdebug {
puts "Skipping vtab_err-2 tests: not compiled with -DSQLITE_MEMDEBUG..."
finish_test
return
}
source $testdir/malloc_common.tcl
+23 -1
View File
@@ -526,5 +526,27 @@ do_catchsql_test 11.4 {
CREATE INDEX t6i ON t6(lead(b) OVER ());
} {1 {misuse of window function lead()}}
finish_test
# 2018-09-17 ticket 510cde277783b5fb5de628393959849dff377eb3
# Endless loop on a query with window functions and a limit
#
do_execsql_test 12.100 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(id INT, b VARCHAR, c VARCHAR);
INSERT INTO t1 VALUES(1, 'A', 'one');
INSERT INTO t1 VALUES(2, 'B', 'two');
INSERT INTO t1 VALUES(3, 'C', 'three');
INSERT INTO t1 VALUES(4, 'D', 'one');
INSERT INTO t1 VALUES(5, 'E', 'two');
SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x
FROM t1 WHERE id>1
ORDER BY b LIMIT 1;
} {2 B two}
do_execsql_test 12.110 {
INSERT INTO t1 VALUES(6, 'F', 'three');
INSERT INTO t1 VALUES(7, 'G', 'one');
SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x
FROM t1 WHERE id>1
ORDER BY b LIMIT 2;
} {2 B two 3 C three}
finish_test
+26
View File
@@ -358,6 +358,32 @@ execsql_test 10.3 {
SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7;
}
execsql_test 11.0 {
DROP VIEW IF EXISTS v8;
DROP TABLE IF EXISTS t8;
CREATE TABLE t8(t INT, total INT);
INSERT INTO t8 VALUES(0,2);
INSERT INTO t8 VALUES(5,1);
INSERT INTO t8 VALUES(10,1);
}
execsql_test 11.1 {
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
}
execsql_test 11.2 {
CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
}
execsql_test 11.3 {
SELECT * FROM v8;
}
execsql_test 11.4 {
SELECT * FROM (
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
) sub;
}
finish_test
+57 -9
View File
@@ -1217,13 +1217,20 @@ do_execsql_test 9.2 {
SELECT dense_rank() OVER (PARTITION BY x) FROM t2
} {1 1 1 1 1 1 1}
do_test 9.3 {
set myres {}
foreach r [db eval {SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2}] {
lappend myres [format %.2f [set r]]
lappend myres [format %.4f [set r]]
}
set myres
} {1.00 0.00 1.00 0.00 1.00 0.00 4.00 0.00 4.00 0.00 6.00 0.00 7.00 0.00}
set res2 {1.0000 0.0000 1.0000 0.0000 1.0000 0.0000 4.0000 0.0000 4.0000 0.0000 6.0000 0.0000 7.0000 0.0000}
foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
error "list element [set i] does not match: got=[set r] expected=[set r2]"
}
}
set {} {}
} {}
do_execsql_test 9.4 {
SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
@@ -1233,21 +1240,35 @@ do_execsql_test 9.5 {
SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
} {1 1 4 4 6 6 7 7}
do_test 9.6 {
set myres {}
foreach r [db eval {SELECT percent_rank() OVER () FROM t1}] {
lappend myres [format %.2f [set r]]
lappend myres [format %.4f [set r]]
}
set myres
} {0.00 0.00 0.00}
set res2 {0.0000 0.0000 0.0000}
foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
error "list element [set i] does not match: got=[set r] expected=[set r2]"
}
}
set {} {}
} {}
do_test 9.7 {
set myres {}
foreach r [db eval {SELECT cume_dist() OVER () FROM t1}] {
lappend myres [format %.2f [set r]]
lappend myres [format %.4f [set r]]
}
set myres
} {1.00 1.00 1.00}
set res2 {1.0000 1.0000 1.0000}
foreach r [set myres] r2 [set res2] {
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
error "list element [set i] does not match: got=[set r] expected=[set r2]"
}
}
set {} {}
} {}
do_execsql_test 10.0 {
DROP TABLE IF EXISTS t7;
@@ -1269,4 +1290,31 @@ do_execsql_test 10.3 {
SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7;
} {1 {} 2 4 3 {} 4 8 5 1 6 {}}
do_execsql_test 11.0 {
DROP VIEW IF EXISTS v8;
DROP TABLE IF EXISTS t8;
CREATE TABLE t8(t INT, total INT);
INSERT INTO t8 VALUES(0,2);
INSERT INTO t8 VALUES(5,1);
INSERT INTO t8 VALUES(10,1);
} {}
do_execsql_test 11.1 {
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
} {0 1 2}
do_execsql_test 11.2 {
CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
} {}
do_execsql_test 11.3 {
SELECT * FROM v8;
} {0 1 2}
do_execsql_test 11.4 {
SELECT * FROM (
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
) sub;
} {0 1 2}
finish_test
+16 -15
View File
@@ -147,17 +147,17 @@ do_execsql_test 5.5 {
#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
SELECT LIKE('!', '', '!') x WHERE x;
} {}
do_execsql_test 6.1 {
SELECT LIKE("!","","!")""WHeRE"";
} {}
do_catchsql_test 6.2 {
SELECT LIKE("!","","!")""window"";
} {1 {near "window": syntax error}}
ifcapable !icu {
do_execsql_test 6.0 {
SELECT LIKE('!', '', '!') x WHERE x;
} {}
do_execsql_test 6.1 {
SELECT LIKE("!","","!")""WHeRE"";
} {}
do_catchsql_test 6.2 {
SELECT LIKE("!","","!")""window"";
} {1 {near "window": syntax error}}
}
reset_db
do_execsql_test 7.0 {
@@ -166,9 +166,11 @@ do_execsql_test 7.0 {
INSERT INTO t1 VALUES('');
}
do_execsql_test 7.1 {
SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!';
} {0}
ifcapable !icu {
do_execsql_test 7.1 {
SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!';
} {0}
}
#-------------------------------------------------------------------------
#
@@ -336,4 +338,3 @@ do_execsql_test 11.2 {
}
finish_test
+21
View File
@@ -865,6 +865,27 @@ do_catchsql_test 16.1 {
SELECT * FROM i;
} {1 {recursive aggregate queries not supported}}
# Or window-function recursive queries. Ticket e8275b41.
#
ifcapable windowfunc {
do_catchsql_test 16.2 {
WITH RECURSIVE
i(x) AS (VALUES(1) UNION SELECT count(*) OVER () FROM i)
SELECT * FROM i;
} {1 {cannot use window functions in recursive queries}}
do_catchsql_test 16.3 {
WITH RECURSIVE
t(id, parent) AS (VALUES(1,2)),
q(id, parent, rn) AS (
VALUES(1,2,3)
UNION ALL
SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn
FROM q JOIN t ON t.parent = q.id
)
SELECT * FROM q;
} {1 {cannot use window functions in recursive queries}}
}
#-------------------------------------------------------------------------
do_execsql_test 17.1 {
WITH x(a) AS (
+41 -8
View File
@@ -220,9 +220,17 @@ set pragma_def {
NAME: table_info
FLAG: NeedSchema Result1 SchemaOpt
ARG: 0
COLS: cid name type notnull dflt_value pk
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: table_xinfo
TYPE: TABLE_INFO
FLAG: NeedSchema Result1 SchemaOpt
ARG: 1
COLS: cid name type notnull dflt_value pk hidden
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: stats
FLAG: NeedSchema Result0 SchemaReq
COLS: tbl idx wdth hght flgs
@@ -382,6 +390,11 @@ set pragma_def {
NAME: optimize
FLAG: Result1 NeedSchema
NAME: legacy_alter_table
TYPE: FLAG
ARG: SQLITE_LegacyAlter
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
}
# Open the output file
@@ -405,20 +418,20 @@ set cols {}
set cols_list {}
set arg 0
proc record_one {} {
global name type if arg allbyname typebyif flags cols allcols
global name type if arg allbyname typebyif flags cols all_cols
global cols_list colUsedBy
if {$name==""} return
if {$cols!=""} {
if {![info exists allcols($cols)]} {
if {![info exists all_cols($cols)]} {
set all_cols($cols) 1
lappend cols_list $cols
set allcols($cols) [llength $cols_list]
}
set cx $allcols($cols)
set cx $cols
lappend colUsedBy($cols) $name
} else {
set cx 0
}
set allbyname($name) [list $type $arg $if $flags $cx]
set allbyname($name) [list $type $arg $if $flags $cols]
set name {}
set type {}
set if {}
@@ -500,6 +513,13 @@ foreach f [lsort [array names allflags]] {
set fv [expr {$fv*2}]
}
# Sort the column lists so that longer column lists occur first
#
proc colscmp {a b} {
return [expr {[llength $b] - [llength $a]}]
}
set cols_list [lsort -command colscmp $cols_list]
# Generate the array of column names used by pragmas that act like
# queries.
#
@@ -508,10 +528,23 @@ puts $fd "** or that return single-column results where the name of the"
puts $fd "** result column is different from the name of the pragma\n*/"
puts $fd "static const char *const pragCName\[\] = {"
set offset 0
set allcollist {}
foreach cols $cols_list {
set cols_offset($allcols($cols)) $offset
set n [llength $cols]
set limit [expr {[llength $allcollist] - $n}]
for {set i 0} {$i<$limit} {incr i} {
set sublist [lrange $allcollist $i [expr {$i+$n-1}]]
if {$sublist==$cols} {
puts $fd [format "%27s/* $colUsedBy($cols) reuses $i */" ""]
set cols_offset($cols) $i
break
}
}
if {$i<$limit} continue
set cols_offset($cols) $offset
set ub " /* Used by: $colUsedBy($cols) */"
foreach c $cols {
lappend allcollist $c
puts $fd [format " /* %3d */ %-14s%s" $offset \"$c\", $ub]
set ub ""
incr offset
@@ -537,12 +570,12 @@ set current_if {}
set spacer [format { %26s } {}]
foreach name $allnames {
foreach {type arg if flag cx} $allbyname($name) break
if {$cx==0} {
if {$cx==0 || $cx==""} {
set cy 0
set nx 0
} else {
set cy $cols_offset($cx)
set nx [llength [lindex $cols_list [expr {$cx-1}]]]
set nx [llength $cx]
}
if {$if!=$current_if} {
if {$current_if!=""} {