Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad879ffdb5 | |||
| 1e9b53f9bc | |||
| a3a40211bd | |||
| 7433ae5df6 | |||
| 5c6b944d16 | |||
| b94f2eccc1 | |||
| eea46aeafc | |||
| 4a47761e0d | |||
| 5c41d00f42 | |||
| 5424075137 | |||
| 01e64a1704 | |||
| 2710b14c45 | |||
| b67343d075 | |||
| f299edb0b0 | |||
| 966e291160 | |||
| 49cd39b48c | |||
| b163748e88 | |||
| 90a7eae84c | |||
| 3f50bb84f5 | |||
| 47073f62bf | |||
| 63a49ce0b2 | |||
| 56d65cd7b9 | |||
| 83a4f47d57 | |||
| 38eef32172 | |||
| 197231b160 | |||
| e2b45d1789 | |||
| aa430bfb00 | |||
| eb25713e91 | |||
| a1a523a5bb |
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
04ac0b75b1716541b2b97704f4809cb7ef19cccf
|
||||
2ab997e47998d261bd6190bbce5c09f3fbd4cfd3
|
||||
@@ -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
@@ -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
@@ -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 ){
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
@@ -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
@@ -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 ){
|
||||
|
||||
Reference in New Issue
Block a user