Compare commits

...

29 Commits

Author SHA1 Message Date
drh ad879ffdb5 Clean up the implementation of constant function factorization.
FossilOrigin-Name: 2ab997e47998d261bd6190bbce5c09f3fbd4cfd3
2017-01-04 04:10:02 +00:00
drh 1e9b53f9bc Attempt to factor out constant functions from the interior of table scans,
since functions can often be expensive to compute.

FossilOrigin-Name: 62e9270a8057d758621da33adb27fad14225f95d
2017-01-04 01:07:24 +00:00
drh a3a40211bd Use compiler intrinsic functions for signed integer math when overflow
detection is needed.

FossilOrigin-Name: d3ac32a6e7f1823450feb3d1089802542090d164
2017-01-03 21:57:11 +00:00
drh 7433ae5df6 Back out the use of __sync_fetch_and_sub() as it does not appear to work.
FossilOrigin-Name: 4c2efd4239bf07eb4b92d4af54edd68ee6312670
2017-01-03 21:50:49 +00:00
drh 5c6b944d16 Fix a typo in a comment.
FossilOrigin-Name: ae087123db8e7d47b25a8d0a98cfd62e85e42fc6
2017-01-03 21:03:37 +00:00
drh b94f2eccc1 Use the CLANG_VERSION macro to control clang-specific features.
FossilOrigin-Name: f8ebeec211483503e135104ef977b3c384a1d789
2017-01-03 20:01:24 +00:00
drh eea46aeafc Use the GCC built-in __sync_fetch_and_sub() to make the sqlite3StatusDown()
routine atomic, and thereby avoid some mutexing.

FossilOrigin-Name: f69ce75b3d94331fdbfa2f3a27d61db24c285d2b
2017-01-03 18:05:04 +00:00
drh 4a47761e0d Make use of the __buildin_OP_overflow() functions from GCC when doing
64-bit signed integer arithmetic.

FossilOrigin-Name: 82cbebb8ee4484f13e5f48d305e20e73063f273e
2017-01-03 17:33:43 +00:00
drh 5c41d00f42 Add the experimental affinity() SQL function when SQLITE_DEBUG is defined.
FossilOrigin-Name: bed0eaa5f50112e64fc97a2afdc9d56cf8f5026a
2017-01-03 14:45:35 +00:00
drh 5424075137 Put the affinity() function implementation inside of #ifdef SQLITE_DEBUG.
FossilOrigin-Name: f778f58ae4ea3e16f51b94591a2c1e563dcb0cde
2017-01-03 14:39:30 +00:00
drh 01e64a1704 Merge all the latest changes from trunk.
FossilOrigin-Name: c27cd8a8127b81d3176f6a5b9915c9b3c69574fb
2017-01-03 14:30:28 +00:00
drh 2710b14c45 Defer size checking on row-value assignments for when the RHS is a SELECT
until after the "*" wildcards have been expanded.

FossilOrigin-Name: 36944be6be5c42096f5da84187ff203af26b08ae
2017-01-03 13:45:22 +00:00
drh b67343d075 Fix a typo on a comment. No code changes.
FossilOrigin-Name: abc27b6023e28a717bfa15648ddc152bda9c7b96
2017-01-03 11:59:54 +00:00
dan f299edb0b0 Add test cases for the fix in [f12ed3ce]. No problems discovered.
FossilOrigin-Name: 548532fdcf84d565c17aed79a6b595e8b62a3ab4
2017-01-03 08:11:24 +00:00
drh 966e291160 Improvements to the way vector assignment size checking is done. Size checks
when the RHS is a SELECT are deferred until after "*" wildcards are expanded.

FossilOrigin-Name: 696219b11049930cdbc38f574820f4bbaf8621bb
2017-01-03 02:58:01 +00:00
drh 49cd39b48c Fix the row-values in UPDATE statements within TRIGGER problem identified
by ticket [8c9458e7].

FossilOrigin-Name: f12ed3ce0bfb2d94c9baad23fdcbd816c72439a1
2017-01-03 01:24:10 +00:00
drh b163748e88 Improved assert()s on the sqlite3ExprListDup() logic for TK_SELECT_COLUMN.
FossilOrigin-Name: 14da99d41f7968bf816203b4ae11c1f0d1ee0b5d
2017-01-03 00:27:16 +00:00
drh 90a7eae84c Test cases for the row-value UPDATE TRIGGER fix.
FossilOrigin-Name: b9b964373c89a491649f366ad7d70ae4d69b891d
2017-01-02 23:43:03 +00:00
drh 3f50bb84f5 Put an ALWAYS() on an unreachable branch in the sqlite3ExprListDup() routine.
FossilOrigin-Name: 2caaaab5e07f6b76d66fbe4e93a4b956937427d8
2017-01-02 23:18:35 +00:00
drh 47073f62bf Proposed fix for the row-value TRIGGER UPDATE problem described in
ticket [8c9458e7].

FossilOrigin-Name: 61a442ea2ceec2cbd327dae0ff5214e1f3c69ec0
2017-01-02 22:36:32 +00:00
drh 63a49ce0b2 Increase the version number to 3.17.0 for the next release cycle.
FossilOrigin-Name: 16415b5aad445c9e4e849018b48538d74eec8944
2017-01-02 19:10:14 +00:00
drh 56d65cd7b9 Provide the SQLITE_DEFAULT_LOOKASIDE compile-time option and make it's default
value be 1200,100 (raised from 512,125 in the latest release).

FossilOrigin-Name: 584da48f9e818f25134e0a62fb7e84f07019511f
2017-01-02 19:02:20 +00:00
drh 83a4f47d57 Change SQLITE_DEFAULT_PCACHE_INITSZ from 100 to 20, which is experimentally
determined to be slightly faster.

FossilOrigin-Name: 12d9493cb29307aec65ceccc68e802e4d0f18112
2017-01-02 18:40:03 +00:00
drh 38eef32172 Avoid unnecessary calls to sqlite3BtreeEnterAll() and sqlite3BtreeLeaveAll()
when no btree is using shared-cache.

FossilOrigin-Name: cfb3158204628eb2fd170090a7f212df0e4ce6c9
2017-01-02 18:19:29 +00:00
drh 197231b160 Add the --all option to the wordcount test program.
Fix the speedtest1 test program so that it builds on MSVC and so that
the --lookaside 0 0 option works.

FossilOrigin-Name: cb338f367e5408861bd7c0fbf74cebdbd8e3c515
2017-01-02 12:20:15 +00:00
drh e2b45d1789 Add the --help and --all options to the wordcount test utility.
FossilOrigin-Name: 18baeadfc89f6252e38dbc22904b11c5b56347ee
2016-12-31 21:55:23 +00:00
drh aa430bfb00 In speedtest1.c, make the "--lookaside 0 0" option completely disable lookaside.
FossilOrigin-Name: 52b99bcbf18f34196ec29f829c6af539e0d05524
2016-12-31 18:37:50 +00:00
drh eb25713e91 Minor #include change to speedtest1.c so that it will compile under MSVC.
FossilOrigin-Name: 8c28fde004678c85524770969eb001719b109179
2016-12-31 14:33:05 +00:00
drh a1a523a5bb Add the built-in affinity() SQL function.
FossilOrigin-Name: 57e40e1cb1bcd3dd8473d2fdeecc9c7ff3d6192b
2016-12-26 00:18:36 +00:00
14 changed files with 538 additions and 259 deletions
+1 -1
View File
@@ -1 +1 @@
3.16.0
3.17.0
Vendored
+10 -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.16.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.17.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.16.0'
PACKAGE_STRING='sqlite 3.16.0'
PACKAGE_VERSION='3.17.0'
PACKAGE_STRING='sqlite 3.17.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1463,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.16.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.17.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.16.0:";;
short | recursive ) echo "Configuration of sqlite 3.17.0:";;
esac
cat <<\_ACEOF
@@ -1652,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.16.0
sqlite configure 3.17.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2071,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.16.0, which was
It was created by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12151,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.16.0, which was
This file was extended by sqlite $as_me 3.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12217,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.16.0
sqlite config.status 3.17.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -13829,3 +13829,4 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+17 -20
View File
@@ -1,10 +1,10 @@
C Version\s3.16.0
D 2017-01-02T11:57:58.484
C Clean\sup\sthe\simplementation\sof\sconstant\sfunction\sfactorization.
D 2017-01-04T04:10:02.788
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 661b3e6a778cfbfd7bdce8bbb1545b22f4b6f09e
F VERSION cddd8d88dc8202afa0ebc96da61fc4acbd1e96a5
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -30,7 +30,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure adbf03e758431e886bba5ab04b5adfbd496d7b24 x
F configure fcfa56d5d66668c9263dc007724f62acff06dc83 x
F configure.ac 605173e829ab64514ed89f9b53d0da1739d7b0a0
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
@@ -326,11 +326,11 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 3c4a63ff7a55faefecf6eb1589932fdbc06b2415
F src/attach.c f6725410c184a80d8141b294fdf98a854c8a52b5
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c d2c100618784bd89c089fcef03ff6e789768ecae
F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
@@ -341,11 +341,11 @@ F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c c8bc10d145c9666a34ae906250326fdaa8d58fa5
F src/expr.c 3b662f58b50ba12c004b2d9bd8d3ff5fddbbae7f
F src/expr.c 9e60a71c788a00328652ed37b9f6b6b4374592a3
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c d8582ee91975975645f206db332c38f534b783ad
F src/global.c dcdb89f30b7aa531c5660030af106bc5bc48ef2e
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
F src/global.c 4a34512d82fc5aa13c802db06bcfff5e1d3de955
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
@@ -393,7 +393,7 @@ F src/shell.c 6095531aa900decdaa765e0f3993fba7153c92c1
F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 2075e22d50833ca2d9956d0b7a6bfb845ad05dd2
F src/sqliteInt.h 9fdfb8789b27a621f3401468bc1705c32308f877
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@ -453,7 +453,7 @@ F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/update.c 1da7c462110bffed442a42884cb0d528c1db46d8
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c 1534060bc034cdc51381c040c8bd6252dbcb64c9
F src/util.c a88b0466fddf445ce752226d4698ca3faada620a
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
F src/vdbe.c 88bd6c32b333580d2661ac3afe33369757fb1522
F src/vdbe.h 50ee139f9c68fff91be1d717ed3a6abbd496919c
@@ -1035,7 +1035,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
F test/rowvalue.test 1701fb786188e9fb7934a7c155bd9cc587d9b677
F test/rowvalue.test 44f3492f415cc9f374e8388a5eb61503eaca5230
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
@@ -1127,7 +1127,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 0c92fd0db4cb778e3b6968db0ea859e28f077823
F test/speedtest1.c 4e8ea6165046f02e1cfe0f4700256e91c981ec10
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1449,7 +1449,7 @@ F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 97856eec21fd00d77da720007b1888c383f63dcf
F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
@@ -1541,10 +1541,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 2c4d167ccd4be591487f404de9ee629fd484c8bf
R b92eb609c667e98735c96cb1ee09a168
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.16.0 *
P 62e9270a8057d758621da33adb27fad14225f95d
R 1aa2a1487ef2ae3f764297787590ccdb
U drh
Z d8ea167822373183dd9b5b971ee1941f
Z 020211a07112e857de5c9ad202e08252
+1 -1
View File
@@ -1 +1 @@
04ac0b75b1716541b2b97704f4809cb7ef19cccf
2ab997e47998d261bd6190bbce5c09f3fbd4cfd3
+1
View File
@@ -137,6 +137,7 @@ static void attachFunc(
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
db->skipBtreeMutex = 0;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
zErrDyn = sqlite3MPrintf(db, "database is already attached");
+14 -3
View File
@@ -183,16 +183,24 @@ int sqlite3BtreeHoldsMutex(Btree *p){
** two or more btrees in common both try to lock all their btrees
** at the same instant.
*/
void sqlite3BtreeEnterAll(sqlite3 *db){
static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
int skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
p = db->aDb[i].pBt;
if( p ) sqlite3BtreeEnter(p);
if( p && p->sharable ){
sqlite3BtreeEnter(p);
skipOk = 0;
}
}
db->skipBtreeMutex = skipOk;
}
void sqlite3BtreeLeaveAll(sqlite3 *db){
void sqlite3BtreeEnterAll(sqlite3 *db){
if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
}
static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
int i;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
@@ -201,6 +209,9 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
if( p ) sqlite3BtreeLeave(p);
}
}
void sqlite3BtreeLeaveAll(sqlite3 *db){
if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
}
#ifndef NDEBUG
/*
+96 -26
View File
@@ -414,9 +414,10 @@ Expr *sqlite3ExprForVectorField(
assert( pVector->flags & EP_xIsSelect );
/* The TK_SELECT_COLUMN Expr node:
**
** pLeft: pVector containing TK_SELECT
** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
** if the result is not yet computed.
**
@@ -1088,7 +1089,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==flags ){
if( 0==flags || p->op==TK_SELECT_COLUMN ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -1231,6 +1232,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
assert( p->pRight==0 || p->pRight==p->pLeft );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -1293,6 +1296,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
@@ -1307,7 +1311,24 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
if( pOldExpr
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
assert( pOldExpr->pLeft==pOldExpr->pRight );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
}else{
assert( i>0 );
assert( pItem[-1].pExpr!=0 );
assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
pNewExpr->pLeft = pPriorSelectCol;
}
}
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
@@ -1482,7 +1503,7 @@ no_mem:
** Or: (a,b,c) = (SELECT x,y,z FROM ....)
**
** For each term of the vector assignment, append new entries to the
** expression list pList. In the case of a subquery on the LHS, append
** expression list pList. In the case of a subquery on the RHS, append
** TK_SELECT_COLUMN expressions.
*/
ExprList *sqlite3ExprListAppendVector(
@@ -1499,13 +1520,19 @@ ExprList *sqlite3ExprListAppendVector(
** exit prior to this routine being invoked */
if( NEVER(pColumns==0) ) goto vector_append_error;
if( pExpr==0 ) goto vector_append_error;
n = sqlite3ExprVectorSize(pExpr);
if( pColumns->nId!=n ){
/* If the RHS is a vector, then we can immediately check to see that
** the size of the RHS and LHS match. But if the RHS is a SELECT,
** wildcards ("*") in the result set of the SELECT must be expanded before
** we can do the size check, so defer the size check until code generation.
*/
if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pColumns->nId, n);
goto vector_append_error;
}
for(i=0; i<n; i++){
for(i=0; i<pColumns->nId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
@@ -1514,11 +1541,20 @@ ExprList *sqlite3ExprListAppendVector(
pColumns->a[i].zName = 0;
}
}
if( pExpr->op==TK_SELECT ){
if( pList && pList->a[iFirst].pExpr ){
assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );
pList->a[iFirst].pExpr->pRight = pExpr;
Expr *pFirst = pList->a[iFirst].pExpr;
assert( pFirst->op==TK_SELECT_COLUMN );
/* Store the SELECT statement in pRight so it will be deleted when
** sqlite3ExprListDelete() is called */
pFirst->pRight = pExpr;
pExpr = 0;
/* Remember the size of the LHS in iTable so that we can check that
** the RHS and LHS sizes match during code generation. */
pFirst->iTable = pColumns->nId;
}
}
@@ -3576,6 +3612,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
/* SQL function can be expensive. So try to move constant functions
** out of the inner loop, even if that means an extra OP_Copy. */
return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
@@ -3624,6 +3665,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
}
#ifdef SQLITE_DEBUG
/* The AFFINITY() function evaluates to a string that describes
** the type affinity of the argument. This is used for testing of
** the SQLite type logic.
*/
if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
char aff;
assert( nFarg==1 );
aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
sqlite3VdbeLoadString(v, target,
aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
return target;
}
#endif
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
testcase( i==31 );
@@ -3712,9 +3769,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
if( pExpr->iTable
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
@@ -3932,24 +3997,40 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
/*
** Factor out the code of the given expression to initialization time.
**
** If regDest>=0 then the result is always stored in that register and the
** result is not reusable. If regDest<0 then this routine is free to
** store the value whereever it wants. The register where the expression
** is stored is returned. When regDest<0, two identical expressions will
** code to the same register.
*/
void sqlite3ExprCodeAtInit(
int sqlite3ExprCodeAtInit(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The expression to code when the VDBE initializes */
int regDest, /* Store the value in this register */
u8 reusable /* True if this expression is reusable */
int regDest /* Store the value in this register */
){
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
if( regDest<0 && p ){
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
return pItem->u.iConstExprReg;
}
}
}
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
pItem->reusable = regDest<0;
if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
pItem->reusable = reusable;
}
pParse->pConstExpr = p;
return regDest;
}
/*
@@ -3972,19 +4053,8 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
ExprList *p = pParse->pConstExpr;
int i;
*pReg = 0;
if( p ){
struct ExprList_item *pItem;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
return pItem->u.iConstExprReg;
}
}
}
r2 = ++pParse->nMem;
sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}else{
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
@@ -4038,7 +4108,7 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
*/
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
sqlite3ExprCodeAtInit(pParse, pExpr, target);
}else{
sqlite3ExprCode(pParse, pExpr, target);
}
@@ -4110,7 +4180,7 @@ int sqlite3ExprCodeExprList(
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
}
}else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
+3
View File
@@ -1775,6 +1775,9 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_DEBUG
FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+14 -2
View File
@@ -169,6 +169,19 @@ const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_STMTJRNL_SPILL (64*1024)
#endif
/*
** The default lookaside-configuration, the format "SZ,N". SZ is the
** number of bytes in each lookaside slot (should be a multiple of 8)
** and N is the number of slots. The lookaside-configuration can be
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
# define SQLITE_DEFAULT_LOOKASIDE 1200,100
#endif
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -181,8 +194,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
512, /* szLookaside */
125, /* nLookaside */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
+15 -2
View File
@@ -110,6 +110,14 @@
# define GCC_VERSION 0
#endif
/* What version of CLANG is being used. 0 means CLANG is not being used */
#ifdef __clang__
# define CLANG_VERSION \
(__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
#else
# define CLANG_VERSION 0
#endif
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
@@ -587,9 +595,12 @@
** pagecaches for each database connection. A positive number is the
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
** The default value of "20" was choosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
# define SQLITE_DEFAULT_PCACHE_INITSZ 100
# define SQLITE_DEFAULT_PCACHE_INITSZ 20
#endif
/*
@@ -1296,6 +1307,7 @@ struct sqlite3 {
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
u8 mTrace; /* zero or more SQLITE_TRACE flags */
u8 skipBtreeMutex; /* True if no shared-cache backends */
int nextPagesize; /* Pagesize after VACUUM if >0 */
u32 magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
@@ -1561,6 +1573,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -3703,7 +3716,7 @@ void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
+17 -2
View File
@@ -1141,7 +1141,7 @@ u32 sqlite3Get4byte(const u8 *p){
memcpy(&x,p,4);
return x;
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& defined(__GNUC__) && GCC_VERSION>=4003000
&& (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
u32 x;
memcpy(&x,p,4);
return __builtin_bswap32(x);
@@ -1159,7 +1159,7 @@ void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
&& defined(__GNUC__) && GCC_VERSION>=4003000
&& (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
u32 x = __builtin_bswap32(v);
memcpy(p,&x,4);
#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
@@ -1279,6 +1279,10 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
int sqlite3AddInt64(i64 *pA, i64 iB){
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_add_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
testcase( iA==0 ); testcase( iA==1 );
testcase( iB==-1 ); testcase( iB==0 );
@@ -1293,8 +1297,13 @@ int sqlite3AddInt64(i64 *pA, i64 iB){
}
*pA += iB;
return 0;
#endif
}
int sqlite3SubInt64(i64 *pA, i64 iB){
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_sub_overflow(*pA, iB, pA);
#else
testcase( iB==SMALLEST_INT64+1 );
if( iB==SMALLEST_INT64 ){
testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
@@ -1304,8 +1313,13 @@ int sqlite3SubInt64(i64 *pA, i64 iB){
}else{
return sqlite3AddInt64(pA, -iB);
}
#endif
}
int sqlite3MulInt64(i64 *pA, i64 iB){
#if !defined(SQLITE_DISABLE_INTRINSIC) \
&& (GCC_VERSION>=5004000 || CLANG_VERSION>=4000000)
return __builtin_mul_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
if( iB>0 ){
if( iA>LARGEST_INT64/iB ) return 1;
@@ -1321,6 +1335,7 @@ int sqlite3MulInt64(i64 *pA, i64 iB){
}
*pA = iA*iB;
return 0;
#endif
}
/*
+60
View File
@@ -334,4 +334,64 @@ do_catchsql_test 15.5 {
INSERT INTO x1(a,b) VALUES(1,(SELECT * FROM (SELECT 1,2))<3);
} {1 {row value misused}}
#-------------------------------------------------------------------------
# Row-values used in UPDATE statements within TRIGGERs
#
# Ticket https://www.sqlite.org/src/info/8c9458e703666e1a
#
do_execsql_test 16.1 {
CREATE TABLE t16a(a,b,c);
INSERT INTO t16a VALUES(1,2,3);
CREATE TABLE t16b(x);
INSERT INTO t16b(x) VALUES(1);
CREATE TRIGGER t16r AFTER UPDATE ON t16b BEGIN
UPDATE t16a SET (a,b,c)=(SELECT new.x,new.x+1,new.x+2);
END;
UPDATE t16b SET x=7;
SELECT * FROM t16a;
} {7 8 9}
do_execsql_test 16.2 {
UPDATE t16b SET x=97;
SELECT * FROM t16a;
} {97 98 99}
do_execsql_test 16.3 {
CREATE TABLE t16c(a, b, c, d, e);
INSERT INTO t16c VALUES(1, 'a', 'b', 'c', 'd');
CREATE TRIGGER t16c1 AFTER INSERT ON t16c BEGIN
UPDATE t16c SET (c, d) = (SELECT 'A', 'B'), (e, b) = (SELECT 'C', 'D')
WHERE a = new.a-1;
END;
SELECT * FROM t16c;
} {1 a b c d}
do_execsql_test 16.4 {
INSERT INTO t16c VALUES(2, 'w', 'x', 'y', 'z');
SELECT * FROM t16c;
} {
1 D A B C
2 w x y z
}
do_execsql_test 16.5 {
DROP TRIGGER t16c1;
PRAGMA recursive_triggers = 1;
INSERT INTO t16c VALUES(3, 'i', 'ii', 'iii', 'iv');
CREATE TRIGGER t16c1 AFTER UPDATE ON t16c WHEN new.a>1 BEGIN
UPDATE t16c SET (e, d) = (
SELECT b, c FROM t16c WHERE a = new.a-1
), (c, b) = (
SELECT d, e FROM t16c WHERE a = new.a-1
) WHERE a = new.a-1;
END;
UPDATE t16c SET a=a WHERE a=3;
SELECT * FROM t16c;
} {
1 C B A D
2 z y x w
3 i ii iii iv
}
finish_test
+7 -3
View File
@@ -50,7 +50,11 @@ static const char zHelp[] =
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
@@ -1374,7 +1378,7 @@ int main(int argc, char **argv){
int doIncrvac = 0; /* True for --incrvacuum */
const char *zJMode = 0; /* Journal mode */
const char *zKey = 0; /* Encryption key */
int nLook = 0, szLook = 0; /* --lookaside configuration */
int nLook = -1, szLook = 0; /* --lookaside configuration */
int noSync = 0; /* True for --nosync */
int pageSize = 0; /* Desired page size. 0 means default */
int nPCache = 0, szPCache = 0;/* --pcache configuration */
@@ -1558,7 +1562,7 @@ int main(int argc, char **argv){
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
}
if( nLook>0 ){
if( nLook>=0 ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
}
#endif
+282 -190
View File
@@ -13,24 +13,6 @@
**
** Option:
**
** --without-rowid Use a WITHOUT ROWID table to store the words.
** --insert Use INSERT mode (the default)
** --replace Use REPLACE mode
** --select Use SELECT mode
** --update Use UPDATE mode
** --delete Use DELETE mode
** --query Use QUERY mode
** --nocase Add the NOCASE collating sequence to the words.
** --trace Enable sqlite3_trace() output.
** --summary Show summary information on the collected data.
** --stats Show sqlite3_status() results at the end.
** --pagesize NNN Use a page size of NNN
** --cachesize NNN Use a cache size of NNN
** --commit NNN Commit after every NNN operations
** --nosync Use PRAGMA synchronous=OFF
** --journal MMMM Use PRAGMA journal_mode=MMMM
** --timer Time the operation of this program
** --tag NAME Tag all output using NAME. Use only stdout.
**
** Modes:
**
@@ -81,8 +63,36 @@
#include <stdlib.h>
#include <stdarg.h>
#include "sqlite3.h"
#ifndef _WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
#define ISALPHA(X) isalpha((unsigned char)(X))
const char zHelp[] =
"Usage: wordcount [OPTIONS] DATABASE [INPUT]\n"
" --all Repeat the test for all test modes\n"
" --cachesize NNN Use a cache size of NNN\n"
" --commit NNN Commit after every NNN operations\n"
" --delete Use DELETE mode\n"
" --insert Use INSERT mode (the default)\n"
" --journal MMMM Use PRAGMA journal_mode=MMMM\n"
" --nocase Add the NOCASE collating sequence to the words.\n"
" --nosync Use PRAGMA synchronous=OFF\n"
" --pagesize NNN Use a page size of NNN\n"
" --query Use QUERY mode\n"
" --replace Use REPLACE mode\n"
" --select Use SELECT mode\n"
" --stats Show sqlite3_status() results at the end.\n"
" --summary Show summary information on the collected data.\n"
" --tag NAME Tag all output using NAME. Use only stdout.\n"
" --timer Time the operation of this program\n"
" --trace Enable sqlite3_trace() output.\n"
" --update Use UPDATE mode\n"
" --without-rowid Use a WITHOUT ROWID table to store the words.\n"
;
/* Output tag */
char *zTag = "--";
@@ -110,6 +120,12 @@ static void fatal_error(const char *zMsg, ...){
exit(1);
}
/* Print a usage message and quit */
static void usage(void){
printf("%s",zHelp);
exit(0);
}
/* The sqlite3_trace() callback function */
static void traceCallback(void *NotUsed, const char *zSql){
printf("%s;\n", zSql);
@@ -189,7 +205,6 @@ static void checksumFinalize(sqlite3_context *context){
}
}
/* Define operating modes */
#define MODE_INSERT 0
#define MODE_REPLACE 1
@@ -197,12 +212,50 @@ static void checksumFinalize(sqlite3_context *context){
#define MODE_UPDATE 3
#define MODE_DELETE 4
#define MODE_QUERY 5
#define MODE_COUNT 6
#define MODE_ALL (-1)
/* Mode names */
static const char *azMode[] = {
"--insert",
"--replace",
"--select",
"--update",
"--delete",
"--query"
};
/*
** Determine if another iteration of the test is required. Return true
** if so. Return zero if all iterations have finished.
*/
static int allLoop(
int iMode, /* The selected test mode */
int *piLoopCnt, /* Iteration loop counter */
int *piMode2, /* The test mode to use on the next iteration */
int *pUseWithoutRowid /* Whether or not to use --without-rowid */
){
int i;
if( iMode!=MODE_ALL ){
if( *piLoopCnt ) return 0;
*piMode2 = iMode;
*piLoopCnt = 1;
return 1;
}
if( (*piLoopCnt)>=MODE_COUNT*2 ) return 0;
i = (*piLoopCnt)++;
*pUseWithoutRowid = i&1;
*piMode2 = i>>1;
return 1;
}
int main(int argc, char **argv){
const char *zFileToRead = 0; /* Input file. NULL for stdin */
const char *zDbName = 0; /* Name of the database file to create */
int useWithoutRowid = 0; /* True for --without-rowid */
int iMode = MODE_INSERT; /* One of MODE_xxxxx */
int iMode2; /* Mode to use for current --all iteration */
int iLoopCnt = 0; /* Which iteration when running --all */
int useNocase = 0; /* True for --nocase */
int doTrace = 0; /* True for --trace */
int showStats = 0; /* True for --stats */
@@ -226,7 +279,8 @@ int main(int argc, char **argv){
int iCur, iHiwtr; /* Statistics values, current and "highwater" */
FILE *pTimer = stderr; /* Output channel for the timer */
sqlite3_int64 sumCnt = 0; /* Sum in QUERY mode */
sqlite3_int64 startTime;
sqlite3_int64 startTime; /* Time of start */
sqlite3_int64 totalTime = 0; /* Total time */
char zInput[2000]; /* A single line of input */
/* Process command-line arguments */
@@ -248,6 +302,9 @@ int main(int argc, char **argv){
iMode = MODE_DELETE;
}else if( strcmp(z,"query")==0 ){
iMode = MODE_QUERY;
}else if( strcmp(z,"all")==0 ){
iMode = MODE_ALL;
showTimer = -99;
}else if( strcmp(z,"nocase")==0 ){
useNocase = 1;
}else if( strcmp(z,"trace")==0 ){
@@ -274,23 +331,30 @@ int main(int argc, char **argv){
}else if( strcmp(z,"tag")==0 && i<argc-1 ){
zTag = argv[++i];
pTimer = stdout;
}else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){
usage();
}else{
fatal_error("unknown option: %s\n", argv[i]);
fatal_error("unknown option: \"%s\"\n"
"Use --help for a list of options\n",
argv[i]);
}
}else if( zDbName==0 ){
zDbName = argv[i];
}else if( zFileToRead==0 ){
zFileToRead = argv[i];
}else{
fatal_error("surplus argument: %s\n", argv[i]);
fatal_error("surplus argument: \"%s\"\n", argv[i]);
}
}
if( zDbName==0 ){
fatal_error("Usage: %s [--options] DATABASE [INPUTFILE]\n", argv[0]);
usage();
}
startTime = realTime();
/* Open the database and the input file */
if( zDbName[0] && strcmp(zDbName,":memory:")!=0 ){
unlink(zDbName);
}
if( sqlite3_open(zDbName, &db) ){
fatal_error("Cannot open database file: %s\n", zDbName);
}
@@ -300,6 +364,9 @@ int main(int argc, char **argv){
fatal_error("Could not open input file \"%s\"\n", zFileToRead);
}
}else{
if( iMode==MODE_ALL ){
fatal_error("The --all mode cannot be used with stdin\n");
}
in = stdin;
}
@@ -322,189 +389,214 @@ int main(int argc, char **argv){
sqlite3_free(zSql);
}
/* Construct the "wordcount" table into which to put the words */
if( sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0) ){
fatal_error("Could not start a transaction\n");
}
zSql = sqlite3_mprintf(
"CREATE TABLE IF NOT EXISTS wordcount(\n"
" word TEXT PRIMARY KEY COLLATE %s,\n"
" cnt INTEGER\n"
")%s",
useNocase ? "nocase" : "binary",
useWithoutRowid ? " WITHOUT ROWID" : ""
);
if( zSql==0 ) fatal_error("out of memory\n");
rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc ) fatal_error("Could not create the wordcount table: %s.\n",
sqlite3_errmsg(db));
sqlite3_free(zSql);
/* Prepare SQL statements that will be needed */
if( iMode==MODE_QUERY ){
rc = sqlite3_prepare_v2(db,
"SELECT cnt FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_SELECT ){
rc = sqlite3_prepare_v2(db,
"SELECT 1 FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
rc = sqlite3_prepare_v2(db,
"INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
iLoopCnt = 0;
while( allLoop(iMode, &iLoopCnt, &iMode2, &useWithoutRowid) ){
/* Delete prior content in --all mode */
if( iMode==MODE_ALL ){
if( sqlite3_exec(db, "DROP TABLE IF EXISTS wordcount; VACUUM;",0,0,0) ){
fatal_error("Could not clean up prior iteration\n");
}
startTime = realTime();
rewind(in);
}
/* Construct the "wordcount" table into which to put the words */
if( sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0) ){
fatal_error("Could not start a transaction\n");
}
zSql = sqlite3_mprintf(
"CREATE TABLE IF NOT EXISTS wordcount(\n"
" word TEXT PRIMARY KEY COLLATE %s,\n"
" cnt INTEGER\n"
")%s",
useNocase ? "nocase" : "binary",
useWithoutRowid ? " WITHOUT ROWID" : ""
);
if( zSql==0 ) fatal_error("out of memory\n");
rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc ) fatal_error("Could not create the wordcount table: %s.\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_SELECT || iMode==MODE_UPDATE || iMode==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
-1, &pUpdate, 0);
if( rc ) fatal_error("Could not prepare the UPDATE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_UPDATE ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_REPLACE ){
rc = sqlite3_prepare_v2(db,
sqlite3_free(zSql);
/* Prepare SQL statements that will be needed */
if( iMode2==MODE_QUERY ){
rc = sqlite3_prepare_v2(db,
"SELECT cnt FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_SELECT ){
rc = sqlite3_prepare_v2(db,
"SELECT 1 FROM wordcount WHERE word=?1",
-1, &pSelect, 0);
if( rc ) fatal_error("Could not prepare the SELECT statement: %s\n",
sqlite3_errmsg(db));
rc = sqlite3_prepare_v2(db,
"INSERT INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_SELECT || iMode2==MODE_UPDATE || iMode2==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"UPDATE wordcount SET cnt=cnt+1 WHERE word=?1",
-1, &pUpdate, 0);
if( rc ) fatal_error("Could not prepare the UPDATE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_INSERT ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_UPDATE ){
rc = sqlite3_prepare_v2(db,
"INSERT OR IGNORE INTO wordcount(word,cnt) VALUES(?1,0)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the INSERT statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_REPLACE ){
rc = sqlite3_prepare_v2(db,
"REPLACE INTO wordcount(word,cnt)"
"VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)",
-1, &pInsert, 0);
if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode==MODE_DELETE ){
rc = sqlite3_prepare_v2(db,
"DELETE FROM wordcount WHERE word=?1",
-1, &pDelete, 0);
if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n",
sqlite3_errmsg(db));
}
/* Process the input file */
while( fgets(zInput, sizeof(zInput), in) ){
for(i=0; zInput[i]; i++){
if( !ISALPHA(zInput[i]) ) continue;
for(j=i+1; ISALPHA(zInput[j]); j++){}
/* Found a new word at zInput[i] that is j-i bytes long.
** Process it into the wordcount table. */
if( iMode==MODE_DELETE ){
sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pDelete)!=SQLITE_DONE ){
fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pDelete);
}else if( iMode==MODE_SELECT ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
rc = sqlite3_step(pSelect);
sqlite3_reset(pSelect);
if( rc==SQLITE_ROW ){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n",
sqlite3_errmsg(db));
}
if( iMode2==MODE_DELETE ){
rc = sqlite3_prepare_v2(db,
"DELETE FROM wordcount WHERE word=?1",
-1, &pDelete, 0);
if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n",
sqlite3_errmsg(db));
}
/* Process the input file */
while( fgets(zInput, sizeof(zInput), in) ){
for(i=0; zInput[i]; i++){
if( !ISALPHA(zInput[i]) ) continue;
for(j=i+1; ISALPHA(zInput[j]); j++){}
/* Found a new word at zInput[i] that is j-i bytes long.
** Process it into the wordcount table. */
if( iMode2==MODE_DELETE ){
sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pDelete)!=SQLITE_DONE ){
fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}else if( rc==SQLITE_DONE ){
sqlite3_reset(pDelete);
}else if( iMode2==MODE_SELECT ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
rc = sqlite3_step(pSelect);
sqlite3_reset(pSelect);
if( rc==SQLITE_ROW ){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}else if( rc==SQLITE_DONE ){
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("Insert failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
}else{
fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db));
}
}else if( iMode2==MODE_QUERY ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pSelect)==SQLITE_ROW ){
sumCnt += sqlite3_column_int64(pSelect, 0);
}
sqlite3_reset(pSelect);
}else{
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("Insert failed: %s\n", sqlite3_errmsg(db));
fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
}else{
fatal_error("SELECT failed: %s\n", sqlite3_errmsg(db));
}
}else if( iMode==MODE_QUERY ){
sqlite3_bind_text(pSelect, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pSelect)==SQLITE_ROW ){
sumCnt += sqlite3_column_int64(pSelect, 0);
}
sqlite3_reset(pSelect);
}else{
sqlite3_bind_text(pInsert, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pInsert)!=SQLITE_DONE ){
fatal_error("INSERT failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pInsert);
if( iMode==MODE_UPDATE
|| (iMode==MODE_INSERT && sqlite3_changes(db)==0)
){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
if( iMode2==MODE_UPDATE
|| (iMode2==MODE_INSERT && sqlite3_changes(db)==0)
){
sqlite3_bind_text(pUpdate, 1, zInput+i, j-i, SQLITE_STATIC);
if( sqlite3_step(pUpdate)!=SQLITE_DONE ){
fatal_error("UPDATE failed: %s\n", sqlite3_errmsg(db));
}
sqlite3_reset(pUpdate);
}
sqlite3_reset(pUpdate);
}
i = j-1;
/* Increment the operation counter. Do a COMMIT if it is time. */
nOp++;
if( commitInterval>0 && (nOp%commitInterval)==0 ){
sqlite3_exec(db, "COMMIT; BEGIN IMMEDIATE", 0, 0, 0);
}
}
i = j-1;
/* Increment the operation counter. Do a COMMIT if it is time. */
nOp++;
if( commitInterval>0 && (nOp%commitInterval)==0 ){
sqlite3_exec(db, "COMMIT; BEGIN IMMEDIATE", 0, 0, 0);
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
sqlite3_finalize(pInsert); pInsert = 0;
sqlite3_finalize(pUpdate); pUpdate = 0;
sqlite3_finalize(pSelect); pSelect = 0;
sqlite3_finalize(pDelete); pDelete = 0;
if( iMode2==MODE_QUERY && iMode!=MODE_ALL ){
printf("%s sum of cnt: %lld\n", zTag, sumCnt);
rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
&pSelect, 0);
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
printf("%s double-check: %lld\n", zTag,sqlite3_column_int64(pSelect,0));
}
sqlite3_finalize(pSelect);
}
if( showTimer ){
sqlite3_int64 elapseTime = realTime() - startTime;
totalTime += elapseTime;
fprintf(pTimer, "%3d.%03d wordcount", (int)(elapseTime/1000),
(int)(elapseTime%1000));
if( iMode==MODE_ALL ){
fprintf(pTimer, " %s%s\n", azMode[iMode2],
useWithoutRowid? " --without-rowid" : "");
}else{
for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(pTimer," %s",argv[i]);
fprintf(pTimer, "\n");
}
}
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
if( zFileToRead ) fclose(in);
sqlite3_finalize(pInsert);
sqlite3_finalize(pUpdate);
sqlite3_finalize(pSelect);
sqlite3_finalize(pDelete);
if( iMode==MODE_QUERY ){
printf("%s sum of cnt: %lld\n", zTag, sumCnt);
rc = sqlite3_prepare_v2(db,"SELECT sum(cnt*cnt) FROM wordcount", -1,
&pSelect, 0);
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
printf("%s double-check: %lld\n", zTag, sqlite3_column_int64(pSelect, 0));
if( showSummary ){
sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
0, checksumStep, checksumFinalize);
sqlite3_exec(db,
"SELECT 'count(*): ', count(*) FROM wordcount;\n"
"SELECT 'sum(cnt): ', sum(cnt) FROM wordcount;\n"
"SELECT 'max(cnt): ', max(cnt) FROM wordcount;\n"
"SELECT 'avg(cnt): ', avg(cnt) FROM wordcount;\n"
"SELECT 'sum(cnt=1):', sum(cnt=1) FROM wordcount;\n"
"SELECT 'top 10: ', group_concat(word, ', ') FROM "
"(SELECT word FROM wordcount ORDER BY cnt DESC, word LIMIT 10);\n"
"SELECT 'checksum: ', checksum(word, cnt) FROM "
"(SELECT word, cnt FROM wordcount ORDER BY word);\n"
"PRAGMA integrity_check;\n",
printResult, 0, 0);
}
sqlite3_finalize(pSelect);
} /* End the --all loop */
/* Close the input file after the last read */
if( zFileToRead ) fclose(in);
/* In --all mode, so the total time */
if( iMode==MODE_ALL && showTimer ){
fprintf(pTimer, "%3d.%03d wordcount --all\n", (int)(totalTime/1000),
(int)(totalTime%1000));
}
if( showTimer ){
sqlite3_int64 elapseTime = realTime() - startTime;
fprintf(pTimer, "%3d.%03d wordcount", (int)(elapseTime/1000),
(int)(elapseTime%1000));
for(i=1; i<argc; i++) if( i!=showTimer ) fprintf(pTimer, " %s", argv[i]);
fprintf(pTimer, "\n");
}
if( showSummary ){
sqlite3_create_function(db, "checksum", -1, SQLITE_UTF8, 0,
0, checksumStep, checksumFinalize);
sqlite3_exec(db,
"SELECT 'count(*): ', count(*) FROM wordcount;\n"
"SELECT 'sum(cnt): ', sum(cnt) FROM wordcount;\n"
"SELECT 'max(cnt): ', max(cnt) FROM wordcount;\n"
"SELECT 'avg(cnt): ', avg(cnt) FROM wordcount;\n"
"SELECT 'sum(cnt=1):', sum(cnt=1) FROM wordcount;\n"
"SELECT 'top 10: ', group_concat(word, ', ') FROM "
"(SELECT word FROM wordcount ORDER BY cnt DESC, word LIMIT 10);\n"
"SELECT 'checksum: ', checksum(word, cnt) FROM "
"(SELECT word, cnt FROM wordcount ORDER BY word);\n"
"PRAGMA integrity_check;\n",
printResult, 0, 0);
}
/* Database connection statistics printed after both prepared statements
** have been finalized */
if( showStats ){