SQLite

Changes On Branch version_2
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch version_2 Excluding Merge-Ins

This is equivalent to a diff from 7ace5762 to 47fee16b

2007-01-08
16:20
Fix a date round-off problem in strftime(). Ticket #2153. (CVS 3575) (Leaf check-in: 47fee16b user: drh tags: version_2)
13:43
Fix a round-off error in the %W conversion of strftime(). Ticket #2150. (CVS 3572) (check-in: e6a18741 user: drh tags: version_2)
2004-04-23
23:37
Add some extra debugging logic to lemon.c. Ticket #692. (CVS 1304) (check-in: 635f674d user: drh tags: version_2)
23:20
Branch version_2. Code for version 3 is on the trunk. (CVS 1303) (check-in: db84ddf5 user: drh tags: trunk)
17:04
Get the temp_store and default_temp_store pragmas working. Update the documentation. Also fix a malloc problem that popped up during the regression testing. (CVS 1302) (check-in: 7ace5762 user: drh tags: trunk)
2004-03-26
23:16
Fix windows DLL section of Makefile.in for use with build dir. (CVS 1301) (check-in: 1e84f70f user: rdc tags: trunk)

Changes to VERSION.

1
2.8.13
|
1
2.8.17

Changes to main.mk.

151
152
153
154
155
156
157














158
159
160
161
162
163
164
libsqlite.a:	$(LIBOBJ)
	$(AR) libsqlite.a $(LIBOBJ)
	$(RANLIB) libsqlite.a

sqlite$(EXE):	$(TOP)/src/shell.c libsqlite.a sqlite.h
	$(TCCX) $(READLINE_FLAGS) -o sqlite$(EXE) $(TOP)/src/shell.c \
		libsqlite.a $(LIBREADLINE) $(THREADLIB)















# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
libsqlite.a:	$(LIBOBJ)
	$(AR) libsqlite.a $(LIBOBJ)
	$(RANLIB) libsqlite.a

sqlite$(EXE):	$(TOP)/src/shell.c libsqlite.a sqlite.h
	$(TCCX) $(READLINE_FLAGS) -o sqlite$(EXE) $(TOP)/src/shell.c \
		libsqlite.a $(LIBREADLINE) $(THREADLIB)

sqlite_analyzer$(EXE):	$(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC) \
			$(TOP)/tool/spaceanal.tcl
	sed \
	  -e '/^#/d' \
	  -e 's,\\,\\\\,g' \
	  -e 's,",\\",g' \
	  -e 's,^,",' \
	  -e 's,$$,\\n",' \
	  $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
	$(TCCX) $(TCL_FLAGS) -DTCLSH=2 -DSQLITE_TEST=1 -static -o \
 		sqlite_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \
		libsqlite.a $(LIBTCL)


# This target creates a directory named "tsrc" and fills it with
# copies of all of the C source code and header files needed to
# build on the target system.  Some of the C source code and header
# files are automatically generated.  This target takes care of
# all that automatic generation.
#

Changes to publish.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


16


17

18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


42
43
44
45


46
47
48
49
50
51
52
53
54
55
56
#!/bin/sh
#
# This script is used to compile SQLite and all its documentation and
# ship everything up to the SQLite website.  This script will only work
# on the system "zadok" at the Hwaci offices.  But others might find
# the script useful as an example.
#

# Set srcdir to the name of the directory that contains the publish.sh
# script.
#
srcdir=`echo "$0" | sed 's%\(^.*\)/[^/][^/]*$%\1%'`

# Get the makefile.
#


cp $srcdir/Makefile.linux-gcc ./Makefile


chmod +x $srcdir/install-sh


# Start building stuff.
#
make clean
make sqlite
strip sqlite
mv sqlite sqlite.bin
rm -f sqlite.bin.gz
gzip sqlite.bin


# Build the tclsqlite.so shared library for import into tclsh or wish
# under Linux
#
make target_source
rm sqlite_source.zip
cd tsrc
zip ../sqlite_source.zip *
rm shell.c
TCLDIR=/home/drh/tcltk/8.2linux
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
strip tclsqlite.so
mv tclsqlite.so ..


rm tclsqlite.c
gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so
strip sqlite.so
mv sqlite.so ..


cd ..
rm -f tclsqlite.so.gz sqlite.so.gz
gzip tclsqlite.so
gzip sqlite.so

# Build the tclsqlite.dll shared library that can be imported into tclsh
# or wish on windows.
#
make target_source
cd tsrc
rm shell.c













|

>
>
|
>
>
|
>

|




|

|
>





|

|






|
>
>



|
>
>

<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56



57
58
59
60
61
62
63
#!/bin/sh
#
# This script is used to compile SQLite and all its documentation and
# ship everything up to the SQLite website.  This script will only work
# on the system "zadok" at the Hwaci offices.  But others might find
# the script useful as an example.
#

# Set srcdir to the name of the directory that contains the publish.sh
# script.
#
srcdir=`echo "$0" | sed 's%\(^.*\)/[^/][^/]*$%\1%'`

# Clear out the build directory "doc"
#
#rm -rf doc
#make doc

# Get the current version number - needed to help build filenames
#
VERS=`cat $srcdir/VERSION`
VERSW=`sed 's/\./_/g' $srcdir/VERSION`

# Start by building an sqlite shell for linux.
#
make clean
make sqlite
strip sqlite
mv sqlite sqlite-$VERS.bin
rm -f sqlite.bin.gz
gzip sqlite-$VERS.bin
mv sqlite-$VERS.bin.gz doc

# Build the tclsqlite.so shared library for import into tclsh or wish
# under Linux
#
make target_source
rm -f doc/sqlite-source-$VERSW.zip
cd tsrc
zip ../doc/sqlite-source-$VERSW.zip *
rm shell.c
TCLDIR=/home/drh/tcltk/8.2linux
TCLSTUBLIB=$TCLDIR/libtclstub8.2g.a
OPTS='-DUSE_TCL_STUBS=1 -DNDEBUG=1'
gcc -fPIC $OPTS -O2 -I. -I$TCLDIR -shared *.c $TCLSTUBLIB -o tclsqlite.so
strip tclsqlite.so
mv tclsqlite.so tclsqlite-$VERS.so
gzip tclsqlite-$VERS.so
mv tclsqlite-$VERS.so.gz ../doc
rm tclsqlite.c
gcc -fPIC -DNDEBUG=1 -O2 -I. -shared *.c -o sqlite.so
strip sqlite.so
mv sqlite.so sqlite-$VERS.so
gzip sqlite-$VERS.so
mv sqlite-$VERS.so.gz ../doc
cd ..




# Build the tclsqlite.dll shared library that can be imported into tclsh
# or wish on windows.
#
make target_source
cd tsrc
rm shell.c
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
     --def tclsqlite.def -v --export-all \
     --driver-name i386-mingw32msvc-gcc \
     --dlltool-name i386-mingw32msvc-dlltool \
     --as i386-mingw32msvc-as \
     --target i386-mingw32 \
     -dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
i386-mingw32msvc-strip tclsqlite.dll
mv tclsqlite.dll ..
rm tclsqlite.o
cat >sqlite.def <<\END_OF_FILE
EXPORTS
sqlite_open
sqlite_close
sqlite_exec
sqlite_last_insert_rowid







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
     --def tclsqlite.def -v --export-all \
     --driver-name i386-mingw32msvc-gcc \
     --dlltool-name i386-mingw32msvc-dlltool \
     --as i386-mingw32msvc-as \
     --target i386-mingw32 \
     -dllname tclsqlite.dll -lmsvcrt *.o $TCLSTUBLIB
i386-mingw32msvc-strip tclsqlite.dll
#mv tclsqlite.dll ../tclsqlite-$VERSW.dll
rm tclsqlite.o
cat >sqlite.def <<\END_OF_FILE
EXPORTS
sqlite_open
sqlite_close
sqlite_exec
sqlite_last_insert_rowid
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
     --def sqlite.def -v --export-all \
     --driver-name i386-mingw32msvc-gcc \
     --dlltool-name i386-mingw32msvc-dlltool \
     --as i386-mingw32msvc-as \
     --target i386-mingw32 \
     -dllname sqlite.dll -lmsvcrt *.o
i386-mingw32msvc-strip sqlite.dll

mv sqlite.dll sqlite.def ..
cd ..
rm -f tclsqlite.zip sqlitedll.zip
zip tclsqlite.zip tclsqlite.dll
zip sqlitedll.zip sqlite.dll sqlite.def

# Build the sqlite.exe executable for windows.
#
make target_source
cd tsrc
rm tclsqlite.c
OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1'
i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR *.c -o sqlite.exe
mv sqlite.exe ..
cd ..
rm -f sqlite.zip
zip sqlite.zip sqlite.exe

# Construct a tarball of the source tree
#
ORIGIN=`pwd`
cd $srcdir
cd ..

EXCLUDE=`find sqlite -print | grep CVS | sed 's,sqlite/, --exclude sqlite/,'`
tar czf $ORIGIN/sqlite.tar.gz $EXCLUDE sqlite

cd $ORIGIN
vers=`cat $srcdir/VERSION`
rm -f sqlite-$vers.tar.gz
ln sqlite.tar.gz sqlite-$vers.tar.gz

#
# Build RPMS (binary) and Source RPM
#

# Make sure we are properly setup to build RPMs
#
echo "%HOME %{expand:%%(cd; pwd)}" > $HOME/.rpmmacros
echo "%_topdir %{HOME}/rpm" >> $HOME/.rpmmacros
mkdir $HOME/rpm
mkdir $HOME/rpm/BUILD
mkdir $HOME/rpm/SOURCES
mkdir $HOME/rpm/RPMS
mkdir $HOME/rpm/SRPMS
mkdir $HOME/rpm/SPECS

# create the spec file from the template
sed s/SQLITE_VERSION/$vers/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec

# copy the source tarball to the rpm directory
cp sqlite-$vers.tar.gz $HOME/rpm/SOURCES/.

# build all the rpms
rpm -ba $HOME/rpm/SPECS/sqlite.spec >& rpm-$vers.log

# copy the RPMs into the build directory.
ln $HOME/rpm/RPMS/i386/sqlite*-$vers*.rpm .
ln $HOME/rpm/SRPMS/sqlite-$vers*.rpm .


# Build the website
#
cp $srcdir/../historical/* .
rm -rf doc
make doc
ln sqlite.bin.gz sqlite.zip sqlite*.tar.gz tclsqlite.so.gz tclsqlite.zip doc
ln sqlitedll.zip sqlite.so.gz sqlite_source.zip doc
ln *.rpm doc







>
|

<
<
<








|

<
<






>
|
|
>

<
<
<

















|


|





|
|
<
<
<
<
<
<
<
<
<
<
136
137
138
139
140
141
142
143
144
145



146
147
148
149
150
151
152
153
154
155


156
157
158
159
160
161
162
163
164
165
166



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194










     --def sqlite.def -v --export-all \
     --driver-name i386-mingw32msvc-gcc \
     --dlltool-name i386-mingw32msvc-dlltool \
     --as i386-mingw32msvc-as \
     --target i386-mingw32 \
     -dllname sqlite.dll -lmsvcrt *.o
i386-mingw32msvc-strip sqlite.dll
zip ../doc/tclsqlite-$VERSW.zip tclsqlite.dll
zip ../doc/sqlitedll-$VERSW.zip sqlite.dll sqlite.def
cd ..




# Build the sqlite.exe executable for windows.
#
make target_source
cd tsrc
rm tclsqlite.c
OPTS='-DSTATIC_BUILD=1 -DNDEBUG=1'
i386-mingw32msvc-gcc -O2 $OPTS -I. -I$TCLDIR *.c -o sqlite.exe
zip ../doc/sqlite-$VERSW.zip sqlite.exe
cd ..



# Construct a tarball of the source tree
#
ORIGIN=`pwd`
cd $srcdir
cd ..
mv sqlite_v2 sqlite-$VERS
EXCLUDE=`find sqlite-$VERS -print | grep CVS | sed 's,^, --exclude ,'`
tar czf $ORIGIN/doc/sqlite-$VERS.tar.gz $EXCLUDE sqlite-$VERS
mv sqlite-$VERS sqlite_v2
cd $ORIGIN




#
# Build RPMS (binary) and Source RPM
#

# Make sure we are properly setup to build RPMs
#
echo "%HOME %{expand:%%(cd; pwd)}" > $HOME/.rpmmacros
echo "%_topdir %{HOME}/rpm" >> $HOME/.rpmmacros
mkdir $HOME/rpm
mkdir $HOME/rpm/BUILD
mkdir $HOME/rpm/SOURCES
mkdir $HOME/rpm/RPMS
mkdir $HOME/rpm/SRPMS
mkdir $HOME/rpm/SPECS

# create the spec file from the template
sed s/SQLITE_VERSION/$VERS/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec

# copy the source tarball to the rpm directory
cp doc/sqlite-$VERS.tar.gz $HOME/rpm/SOURCES/.

# build all the rpms
rpm -ba $HOME/rpm/SPECS/sqlite.spec >& rpm-$vers.log

# copy the RPMs into the build directory.
mv $HOME/rpm/RPMS/i386/sqlite*-$VERS*.rpm doc
mv $HOME/rpm/SRPMS/sqlite-$VERS*.rpm doc










Changes to src/attach.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.10 2004/02/12 18:46:39 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.10.2.1 2004/05/07 01:46:01 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
133
134
135
136
137
138
139

140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
**
** The pDbname argument is the name of the database in the DETACH statement.
*/
void sqliteDetach(Parse *pParse, Token *pDbname){
  int i;
  sqlite *db;
  Vdbe *v;


  v = sqliteGetVdbe(pParse);
  sqliteVdbeAddOp(v, OP_Halt, 0, 0);
  if( pParse->explain ) return;
  db = pParse->db;
  for(i=0; i<db->nDb; i++){

    if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
    if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
    if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
  }
  if( i>=db->nDb ){
    sqliteErrorMsg(pParse, "no such database: %T", pDbname);
    return;
  }
  if( i<2 ){
    sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
    return;
  }
#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
    return;
  }
#endif /* SQLITE_OMIT_AUTHORIZATION */
  sqliteBtreeClose(db->aDb[i].pBt);
  db->aDb[i].pBt = 0;
  sqliteFree(db->aDb[i].zName);
  sqliteResetInternalSchema(db, i);

  db->nDb--;
  if( i<db->nDb ){
    db->aDb[i] = db->aDb[db->nDb];
    memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
    sqliteResetInternalSchema(db, i);
  }
}







>






>
|
|
|














|
|
|

>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
**
** The pDbname argument is the name of the database in the DETACH statement.
*/
void sqliteDetach(Parse *pParse, Token *pDbname){
  int i;
  sqlite *db;
  Vdbe *v;
  Db *pDb;

  v = sqliteGetVdbe(pParse);
  sqliteVdbeAddOp(v, OP_Halt, 0, 0);
  if( pParse->explain ) return;
  db = pParse->db;
  for(i=0; i<db->nDb; i++){
    pDb = &db->aDb[i];
    if( pDb->pBt==0 || pDb->zName==0 ) continue;
    if( strlen(pDb->zName)!=pDbname->n ) continue;
    if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
  }
  if( i>=db->nDb ){
    sqliteErrorMsg(pParse, "no such database: %T", pDbname);
    return;
  }
  if( i<2 ){
    sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
    return;
  }
#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
    return;
  }
#endif /* SQLITE_OMIT_AUTHORIZATION */
  sqliteBtreeClose(pDb->pBt);
  pDb->pBt = 0;
  sqliteFree(pDb->zName);
  sqliteResetInternalSchema(db, i);
  if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
  db->nDb--;
  if( i<db->nDb ){
    db->aDb[i] = db->aDb[db->nDb];
    memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
    sqliteResetInternalSchema(db, i);
  }
}

Changes to src/auth.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the sqlite_set_authorizer()
** API.  This facility is an optional feature of the library.  Embedded
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.12 2004/02/22 18:40:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** All of the code in this file may be omitted by defining a single
** macro.
*/







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the sqlite_set_authorizer()
** API.  This facility is an optional feature of the library.  Embedded
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.12.2.2 2004/09/09 13:54:30 drh Exp $
*/
#include "sqliteInt.h"

/*
** All of the code in this file may be omitted by defining a single
** macro.
*/
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130


131
132
133
134
135
136
137
){
  sqlite *db = pParse->db;
  int rc;
  Table *pTab;          /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  const char *zDBase;   /* Name of database being accessed */


  if( db->xAuth==0 ) return;
  assert( pExpr->op==TK_COLUMN );
  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
  }
  if( iSrc>=0 && iSrc<pTabList->nSrc ){
    pTab = pTabList->a[iSrc].pTab;
  }else{
    /* This must be an attempt to read the NEW or OLD pseudo-tables
    ** of a trigger.
    */
    TriggerStack *pStack; /* The stack of current triggers */
    pStack = pParse->trigStack;
    assert( pStack!=0 );
    assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
    pTab = pStack->pTab;


  }
  if( pTab==0 ) return;
  if( pExpr->iColumn>=0 ){
    assert( pExpr->iColumn<pTab->nCol );
    zCol = pTab->aCol[pExpr->iColumn].zName;
  }else if( pTab->iPKey>=0 ){
    assert( pTab->iPKey<pTab->nCol );







>








|



<
<
<


>
>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126



127
128
129
130
131
132
133
134
135
136
137
){
  sqlite *db = pParse->db;
  int rc;
  Table *pTab;          /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  const char *zDBase;   /* Name of database being accessed */
  TriggerStack *pStack; /* The stack of current triggers */

  if( db->xAuth==0 ) return;
  assert( pExpr->op==TK_COLUMN );
  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
  }
  if( iSrc>=0 && iSrc<pTabList->nSrc ){
    pTab = pTabList->a[iSrc].pTab;
  }else if( (pStack = pParse->trigStack)!=0 ){
    /* This must be an attempt to read the NEW or OLD pseudo-tables
    ** of a trigger.
    */



    assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
    pTab = pStack->pTab;
  }else{
    return;
  }
  if( pTab==0 ) return;
  if( pExpr->iColumn>=0 ){
    assert( pExpr->iColumn<pTab->nCol );
    zCol = pTab->aCol[pExpr->iColumn].zName;
  }else if( pTab->iPKey>=0 ){
    assert( pTab->iPKey<pTab->nCol );
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  const char *zArg1,
  const char *zArg2,
  const char *zArg3
){
  sqlite *db = pParse->db;
  int rc;

  if( db->xAuth==0 ){
    return SQLITE_OK;
  }
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE_DENY ){
    sqliteErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE_AUTH;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){







|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  const char *zArg1,
  const char *zArg2,
  const char *zArg3
){
  sqlite *db = pParse->db;
  int rc;

  if( db->init.busy || db->xAuth==0 ){
    return SQLITE_OK;
  }
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE_DENY ){
    sqliteErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE_AUTH;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){

Changes to src/btree_rb.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2003 Feb 4
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree_rb.c,v 1.24 2004/02/29 00:11:31 drh Exp $
**
** This file implements an in-core database using Red-Black balanced
** binary trees.
** 
** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
*/
#include "btree.h"











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2003 Feb 4
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree_rb.c,v 1.24.2.1 2004/06/26 14:40:05 drh Exp $
**
** This file implements an in-core database using Red-Black balanced
** binary trees.
** 
** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
*/
#include "btree.h"
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
 * Print a representation of a node to stdout. This function is only included
 * so you can call it from within a debugger if things get really bad.  It
 * is not called from anyplace in the code.
 */
static void print_node(BtRbNode *pNode)
{
    char * str = append_node(0, pNode, 0);
    printf(str);

    /* Suppress a warning message about print_node() being unused */
    (void)print_node;
}

/* 
 * Check the following properties of the red-black tree:







|







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
 * Print a representation of a node to stdout. This function is only included
 * so you can call it from within a debugger if things get really bad.  It
 * is not called from anyplace in the code.
 */
static void print_node(BtRbNode *pNode)
{
    char * str = append_node(0, pNode, 0);
    printf("%s", str);

    /* Suppress a warning message about print_node() being unused */
    (void)print_node;
}

/* 
 * Check the following properties of the red-black tree:

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.176 2004/04/23 17:04:44 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.176.2.3 2004/08/28 14:53:34 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  ** the end.
  */
  sEnd = pParse->sLastToken;
  if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = ((int)sEnd.z) - (int)pBegin->z;
  z = pBegin->z;
  while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
  sqliteEndTable(pParse, &sEnd, 0);







|







1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  ** the end.
  */
  sEnd = pParse->sLastToken;
  if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = sEnd.z - pBegin->z;
  z = pBegin->z;
  while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
  sqliteEndTable(pParse, &sEnd, 0);
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName && !db->init.busy ){
    Index *pISameName;    /* Another index with the same name */
    Table *pTSameName;    /* A table with same name as the index */
    zName = sqliteStrNDup(pName->z, pName->n);
    if( zName==0 ) goto exit_create_index;
    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "index %s already exists", zName);
      goto exit_create_index;
    }
    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "there is already a table named %s", zName);
      goto exit_create_index;
    }
  }else if( pName==0 ){
    char zBuf[30];
    int n;
    Index *pLoop;
    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
    sprintf(zBuf,"%d)",n);
    zName = 0;
    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
    if( zName==0 ) goto exit_create_index;
  }else{
    zName = sqliteStrNDup(pName->z, pName->n);
  }

  /* Check for authorization to create an index.
  */
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    const char *zDb = db->aDb[pTab->iDb].zName;







|



















|







1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName && !db->init.busy ){
    Index *pISameName;    /* Another index with the same name */
    Table *pTSameName;    /* A table with same name as the index */
    zName = sqliteTableNameFromToken(pName);
    if( zName==0 ) goto exit_create_index;
    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "index %s already exists", zName);
      goto exit_create_index;
    }
    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "there is already a table named %s", zName);
      goto exit_create_index;
    }
  }else if( pName==0 ){
    char zBuf[30];
    int n;
    Index *pLoop;
    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
    sprintf(zBuf,"%d)",n);
    zName = 0;
    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
    if( zName==0 ) goto exit_create_index;
  }else{
    zName = sqliteTableNameFromToken(pName);
  }

  /* Check for authorization to create an index.
  */
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    const char *zDb = db->aDb[pTab->iDb].zName;

Changes to src/date.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.16 2004/02/29 01:08:18 drh Exp $
**
** NOTES:
**
** SQLite processes all times and dates as Julian Day numbers.  The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system.







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.16.2.4 2007/01/08 16:20:29 drh Exp $
**
** NOTES:
**
** SQLite processes all times and dates as Julian Day numbers.  The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system.
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810


811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
          sprintf(&z[j],"%02d.%03d",s,ms);
          j += strlen(&z[j]);
          break;
        }
        case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break;
        case 'W': /* Fall thru */
        case 'j': {
          int n;
          DateTime y = x;
          y.validJD = 0;
          y.M = 1;
          y.D = 1;
          computeJD(&y);
          n = x.rJD - y.rJD + 1;
          if( zFmt[i]=='W' ){


            sprintf(&z[j],"%02d",(n+6)/7);
            j += 2;
          }else{
            sprintf(&z[j],"%03d",n);
            j += 3;
          }
          break;
        }
        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
        case 's': {
          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
          j += strlen(&z[j]);
          break;
        }
        case 'S':  sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
        case '%':  z[j++] = '%'; break;
      }
    }
  }
  z[j] = 0;







|





|

>
>
|


|












|







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
          sprintf(&z[j],"%02d.%03d",s,ms);
          j += strlen(&z[j]);
          break;
        }
        case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break;
        case 'W': /* Fall thru */
        case 'j': {
          int n;             /* Number of days since 1st day of year */
          DateTime y = x;
          y.validJD = 0;
          y.M = 1;
          y.D = 1;
          computeJD(&y);
          n = x.rJD - y.rJD + 0.5;
          if( zFmt[i]=='W' ){
            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
            wd = ((int)(x.rJD+0.5)) % 7;
            sprintf(&z[j],"%02d",(n+7-wd)/7);
            j += 2;
          }else{
            sprintf(&z[j],"%03d",n+1);
            j += 3;
          }
          break;
        }
        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
        case 's': {
          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
          j += strlen(&z[j]);
          break;
        }
        case 'S':  sprintf(&z[j],"%02d",(int)x.s); j+=2; break;
        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
        case '%':  z[j++] = '%'; break;
      }
    }
  }
  z[j] = 0;
843
844
845
846
847
848
849

850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872

873

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.
*/
void sqliteRegisterDateTimeFunctions(sqlite *db){

  static struct {
     char *zName;
     int nArg;
     int dataType;
     void (*xFunc)(sqlite_func*,int,const char**);
  } aFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
    { "julianday", -1, SQLITE_NUMERIC, juliandayFunc   },
    { "date",      -1, SQLITE_TEXT,    dateFunc        },
    { "time",      -1, SQLITE_TEXT,    timeFunc        },
    { "datetime",  -1, SQLITE_TEXT,    datetimeFunc    },
    { "strftime",  -1, SQLITE_TEXT,    strftimeFunc    },
#endif
  };
  int i;

  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    sqlite_create_function(db, aFuncs[i].zName,
           aFuncs[i].nArg, aFuncs[i].xFunc, 0);
    if( aFuncs[i].xFunc ){
      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
    }
  }

}







>






<





<










>

845
846
847
848
849
850
851
852
853
854
855
856
857
858

859
860
861
862
863

864
865
866
867
868
869
870
871
872
873
874
875

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.
*/
void sqliteRegisterDateTimeFunctions(sqlite *db){
#ifndef SQLITE_OMIT_DATETIME_FUNCS
  static struct {
     char *zName;
     int nArg;
     int dataType;
     void (*xFunc)(sqlite_func*,int,const char**);
  } aFuncs[] = {

    { "julianday", -1, SQLITE_NUMERIC, juliandayFunc   },
    { "date",      -1, SQLITE_TEXT,    dateFunc        },
    { "time",      -1, SQLITE_TEXT,    timeFunc        },
    { "datetime",  -1, SQLITE_TEXT,    datetimeFunc    },
    { "strftime",  -1, SQLITE_TEXT,    strftimeFunc    },

  };
  int i;

  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    sqlite_create_function(db, aFuncs[i].zName,
           aFuncs[i].nArg, aFuncs[i].xFunc, 0);
    if( aFuncs[i].xFunc ){
      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
    }
  }
#endif
}

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.114 2004/04/23 17:04:45 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.114.2.4 2004/11/20 20:42:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
Expr *sqliteExprDup(Expr *p){
  Expr *pNew;
  if( p==0 ) return 0;
  pNew = sqliteMallocRaw( sizeof(*p) );
  if( pNew==0 ) return 0;
  memcpy(pNew, p, sizeof(*pNew));
  if( p->token.z!=0 ){
    pNew->token.z = sqliteStrDup(p->token.z);
    pNew->token.dyn = 1;
  }else{
    assert( pNew->token.z==0 );
  }
  pNew->span.z = 0;
  pNew->pLeft = sqliteExprDup(p->pLeft);
  pNew->pRight = sqliteExprDup(p->pRight);







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
Expr *sqliteExprDup(Expr *p){
  Expr *pNew;
  if( p==0 ) return 0;
  pNew = sqliteMallocRaw( sizeof(*p) );
  if( pNew==0 ) return 0;
  memcpy(pNew, p, sizeof(*pNew));
  if( p->token.z!=0 ){
    pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
    pNew->token.dyn = 1;
  }else{
    assert( pNew->token.z==0 );
  }
  pNew->span.z = 0;
  pNew->pLeft = sqliteExprDup(p->pLeft);
  pNew->pRight = sqliteExprDup(p->pRight);
151
152
153
154
155
156
157
158



159
160
161
162
163
164
165
  struct ExprList_item *pItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nExpr = pNew->nAlloc = p->nExpr;
  pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
  if( pItem==0 ) return 0;  /* Leaks memory after a malloc failure */



  for(i=0; i<p->nExpr; i++, pItem++){
    Expr *pNewExpr, *pOldExpr;
    pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
    if( pOldExpr->span.z!=0 && pNewExpr ){
      /* Always make a copy of the span for top-level expressions in the
      ** expression list.  The logic in SELECT processing that determines
      ** the names of columns in the result set needs this information */







|
>
>
>







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  struct ExprList_item *pItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nExpr = pNew->nAlloc = p->nExpr;
  pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqliteFree(pNew);
    return 0;
  }
  for(i=0; i<p->nExpr; i++, pItem++){
    Expr *pNewExpr, *pOldExpr;
    pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
    if( pOldExpr->span.z!=0 && pNewExpr ){
      /* Always make a copy of the span for top-level expressions in the
      ** expression list.  The logic in SELECT processing that determines
      ** the names of columns in the result set needs this information */

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.43 2004/02/25 22:51:06 rdc Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.43.2.3 2004/07/18 23:03:11 drh Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  sqlite_set_result_string(context, zBuf, -1);
}

/*
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite_func *context, int argc, const char **argv){
  char *z;
  int i;
  if( argc<1 || argv[0]==0 ) return;
  z = sqlite_set_result_string(context, argv[0], -1);
  if( z==0 ) return;
  for(i=0; z[i]; i++){
    if( islower(z[i]) ) z[i] = toupper(z[i]);
  }
}
static void lowerFunc(sqlite_func *context, int argc, const char **argv){
  char *z;
  int i;
  if( argc<1 || argv[0]==0 ) return;
  z = sqlite_set_result_string(context, argv[0], -1);
  if( z==0 ) return;
  for(i=0; z[i]; i++){
    if( isupper(z[i]) ) z[i] = tolower(z[i]);
  }
}

/*







|


|






|


|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  sqlite_set_result_string(context, zBuf, -1);
}

/*
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite_func *context, int argc, const char **argv){
  unsigned char *z;
  int i;
  if( argc<1 || argv[0]==0 ) return;
  z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
  if( z==0 ) return;
  for(i=0; z[i]; i++){
    if( islower(z[i]) ) z[i] = toupper(z[i]);
  }
}
static void lowerFunc(sqlite_func *context, int argc, const char **argv){
  unsigned char *z;
  int i;
  if( argc<1 || argv[0]==0 ) return;
  z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
  if( z==0 ) return;
  for(i=0; z[i]; i++){
    if( isupper(z[i]) ) z[i] = tolower(z[i]);
  }
}

/*
513
514
515
516
517
518
519

520
521
522
523
524
525

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
*/
static void minmaxStep(sqlite_func *context, int argc, const char **argv){
  MinMaxCtx *p;
  int (*xCompare)(const char*, const char*);
  int mask;    /* 0 for min() or 0xffffffff for max() */

  assert( argc==2 );

  if( argv[1][0]=='n' ){
    xCompare = sqliteCompare;
  }else{
    xCompare = strcmp;
  }
  mask = (int)sqlite_user_data(context);

  p = sqlite_aggregate_context(context, sizeof(*p));
  if( p==0 || argc<1 || argv[0]==0 ) return;
  if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
    int len;
    if( !p->zBuf[0] ){
      sqliteFree(p->z);
    }
    len = strlen(argv[0]);
    if( len < sizeof(p->zBuf)-1 ){
      p->z = &p->zBuf[1];
      p->zBuf[0] = 1;
    }else{
      p->z = sqliteMalloc( len+1 );
      p->zBuf[0] = 0;
      if( p->z==0 ) return;
    }
    strcpy(p->z, argv[0]);
  }
}
static void minMaxFinalize(sqlite_func *context){
  MinMaxCtx *p;
  p = sqlite_aggregate_context(context, sizeof(*p));
  if( p && p->z ){
    sqlite_set_result_string(context, p->z, strlen(p->z));
  }
  if( p && !p->zBuf[0] ){
    sqliteFree(p->z);
  }
}

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with







>






>

|


|





|


|








|


|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
*/
static void minmaxStep(sqlite_func *context, int argc, const char **argv){
  MinMaxCtx *p;
  int (*xCompare)(const char*, const char*);
  int mask;    /* 0 for min() or 0xffffffff for max() */

  assert( argc==2 );
  if( argv[0]==0 ) return;  /* Ignore NULL values */
  if( argv[1][0]=='n' ){
    xCompare = sqliteCompare;
  }else{
    xCompare = strcmp;
  }
  mask = (int)sqlite_user_data(context);
  assert( mask==0 || mask==-1 );
  p = sqlite_aggregate_context(context, sizeof(*p));
  if( p==0 || argc<1 ) return;
  if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
    int len;
    if( p->zBuf[0] ){
      sqliteFree(p->z);
    }
    len = strlen(argv[0]);
    if( len < sizeof(p->zBuf)-1 ){
      p->z = &p->zBuf[1];
      p->zBuf[0] = 0;
    }else{
      p->z = sqliteMalloc( len+1 );
      p->zBuf[0] = 1;
      if( p->z==0 ) return;
    }
    strcpy(p->z, argv[0]);
  }
}
static void minMaxFinalize(sqlite_func *context){
  MinMaxCtx *p;
  p = sqlite_aggregate_context(context, sizeof(*p));
  if( p && p->z && p->zBuf[0]<2 ){
    sqlite_set_result_string(context, p->z, strlen(p->z));
  }
  if( p && p->zBuf[0] ){
    sqliteFree(p->z);
  }
}

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
617
618
619
620
621
622
623
624





625
626
627
628
629
630
631
632





633
634
635
636
637
638
639
    { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep,   stdDevFinalize },
#endif
  };
  static const char *azTypeFuncs[] = { "min", "max", "typeof" };
  int i;

  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    void *pArg = aFuncs[i].argType==2 ? (void*)(-1) : db;





    sqlite_create_function(db, aFuncs[i].zName,
           aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
    if( aFuncs[i].xFunc ){
      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
    }
  }
  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
    void *pArg = aAggs[i].argType==2 ? (void*)(-1) : db;





    sqlite_create_aggregate(db, aAggs[i].zName,
           aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
    sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
  }
  for(i=0; i<sizeof(azTypeFuncs)/sizeof(azTypeFuncs[0]); i++){
    int n = strlen(azTypeFuncs[i]);
    FuncDef *p = sqliteHashFind(&db->aFunc, azTypeFuncs[i], n);







|
>
>
>
>
>







|
>
>
>
>
>







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
    { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep,   stdDevFinalize },
#endif
  };
  static const char *azTypeFuncs[] = { "min", "max", "typeof" };
  int i;

  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    void *pArg;
    switch( aFuncs[i].argType ){
      case 0:  pArg = 0;           break;
      case 1:  pArg = db;          break;
      case 2:  pArg = (void*)(-1); break;
    }
    sqlite_create_function(db, aFuncs[i].zName,
           aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
    if( aFuncs[i].xFunc ){
      sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
    }
  }
  for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
    void *pArg;
    switch( aAggs[i].argType ){
      case 0:  pArg = 0;           break;
      case 1:  pArg = db;          break;
      case 2:  pArg = (void*)(-1); break;
    }
    sqlite_create_aggregate(db, aAggs[i].zName,
           aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
    sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
  }
  for(i=0; i<sizeof(azTypeFuncs)/sizeof(azTypeFuncs[0]); i++){
    int n = strlen(azTypeFuncs[i]);
    FuncDef *p = sqliteHashFind(&db->aFunc, azTypeFuncs[i], n);

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.164 2004/04/23 17:04:45 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.164.2.2 2004/06/26 14:40:05 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
185
186
187
188
189
190
191
192
193
194
195



196
197
198
199
200
201
202
** indicate success or failure.
*/
static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];
  InitData initData;




  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"







|



>
>
>







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
** indicate success or failure.
*/
static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char const *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName;
  char *zSql = 0;

  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;

  /* The following SQL will read the schema from the master tables.
  ** The first version works with SQLite file formats 2 or greater.
  ** The second version is for format 1 files.
  **
  ** Beginning with file format 2, the rowid for new table entries
  ** (including entries in sqlite_master) is an increasing integer.
  ** So for file format 2 and later, we can play back sqlite_master
  ** and all the CREATE statements will appear in the right order.
  ** But with file format 1, table entries were random and so we
  ** have to make sure the CREATE TABLEs occur before their corresponding
  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
  ** CREATE TRIGGER in file format 1 because those constructs did
  ** not exist then.) 

  */
  static char init_script[] = 
     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
     "UNION ALL "
     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
  static char older_init_script[] = 
     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
     "UNION ALL "

     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
     "WHERE type='table' "
     "UNION ALL "
     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
     "WHERE type='index'";


  assert( iDb>=0 && iDb!=1 && iDb<db->nDb );

  /* Construct the schema tables: sqlite_master and sqlite_temp_master
  */
  sqliteSafetyOff(db);
  azArg[0] = "table";
  azArg[1] = MASTER_NAME;
  azArg[2] = "2";
  azArg[3] = master_schema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  sqliteInitCallback(&initData, 5, azArg, 0);
  pTab = sqliteFindTable(db, MASTER_NAME, "main");
  if( pTab ){
    pTab->readOnly = 1;
  }
  if( iDb==0 ){
    azArg[1] = TEMP_MASTER_NAME;
    azArg[3] = temp_master_schema;
    azArg[4] = "1";
    sqliteInitCallback(&initData, 5, azArg, 0);
    pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
    if( pTab ){
      pTab->readOnly = 1;
    }
  }
  sqliteSafetyOn(db);

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);







|
|
|
<
<
<
<
|
<
<
<
<
<
>

|
|
<
|
<
<
<
>
|
<
<
<
<
|
|
<

|



|

|





|
|


|
<
<
<
<
<
<
<
|
<







215
216
217
218
219
220
221
222
223
224




225





226
227
228
229

230



231
232




233
234

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252







253

254
255
256
257
258
259
260
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;

  assert( iDb>=0 && iDb<db->nDb );

  /* zMasterSchema and zInitScript are set to point at the master schema




  ** and initialisation script appropriate for the database being





  ** initialised. zMasterName is the name of the master table.
  */
  if( iDb==1 ){
    zMasterSchema = temp_master_schema;

    zMasterName = TEMP_MASTER_NAME;



  }else{
    zMasterSchema = master_schema;




    zMasterName = MASTER_NAME;
  }


  /* Construct the schema table.
  */
  sqliteSafetyOff(db);
  azArg[0] = "table";
  azArg[1] = zMasterName;
  azArg[2] = "2";
  azArg[3] = zMasterSchema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  sqliteInitCallback(&initData, 5, (char **)azArg, 0);
  pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
  if( pTab ){
    pTab->readOnly = 1;
  }else{







    return SQLITE_NOMEM;

  }
  sqliteSafetyOn(db);

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343





344








345
346


347
348
349
350
351



352
353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
      /* This happens if the database was initially empty */
      db->file_format = 4;
    }else if( db->file_format>4 ){
      sqliteBtreeCloseCursor(curMain);
      sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
      return SQLITE_ERROR;
    }
  }else if( db->file_format!=meta[2] || db->file_format<4 ){
    assert( db->file_format>=4 );
    if( meta[2]==0 ){
      sqliteSetString(pzErrMsg, "cannot attach empty database: ",
         db->aDb[iDb].zName, (char*)0);
    }else{
      sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
         "database: ", db->aDb[iDb].zName, (char*)0);
    }
    sqliteBtreeClose(db->aDb[iDb].pBt);
    db->aDb[iDb].pBt = 0;
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  sqliteSafetyOff(db);
  if( iDb==0 ){





    rc = sqlite_exec(db, 








        db->file_format>=2 ? init_script : older_init_script,
        sqliteInitCallback, &initData, 0);


  }else{
    char *zSql = 0;
    sqliteSetString(&zSql, 
       "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".sqlite_master", (char*)0);



    rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
    sqliteFree(zSql);
  }

  sqliteSafetyOn(db);
  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    rc = SQLITE_NOMEM;
    sqliteResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    if( iDb==0 ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return rc;
}

/*







|



















|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>
>

<

|
|
>
>
>
|
<
|
>









<
<
<







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348

349
350
351
352
353
354
355
356
357
358
359



360
361
362
363
364
365
366
      /* This happens if the database was initially empty */
      db->file_format = 4;
    }else if( db->file_format>4 ){
      sqliteBtreeCloseCursor(curMain);
      sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
      return SQLITE_ERROR;
    }
  }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
    assert( db->file_format>=4 );
    if( meta[2]==0 ){
      sqliteSetString(pzErrMsg, "cannot attach empty database: ",
         db->aDb[iDb].zName, (char*)0);
    }else{
      sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
         "database: ", db->aDb[iDb].zName, (char*)0);
    }
    sqliteBtreeClose(db->aDb[iDb].pBt);
    db->aDb[iDb].pBt = 0;
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  sqliteSafetyOff(db);

  /* The following SQL will read the schema from the master tables.
  ** The first version works with SQLite file formats 2 or greater.
  ** The second version is for format 1 files.
  **
  ** Beginning with file format 2, the rowid for new table entries
  ** (including entries in sqlite_master) is an increasing integer.
  ** So for file format 2 and later, we can play back sqlite_master
  ** and all the CREATE statements will appear in the right order.
  ** But with file format 1, table entries were random and so we
  ** have to make sure the CREATE TABLEs occur before their corresponding
  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
  ** CREATE TRIGGER in file format 1 because those constructs did
  ** not exist then.) 
  */
  if( db->file_format>=2 ){
    sqliteSetString(&zSql, 
        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
  }else{

    sqliteSetString(&zSql, 
        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".", zMasterName, 
       " WHERE type IN ('table', 'index')"
       " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
  }
  rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);


  sqliteFree(zSql);
  sqliteSafetyOn(db);
  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    rc = SQLITE_NOMEM;
    sqliteResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);



  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return rc;
}

/*
387
388
389
390
391
392
393
394
395
396
397
398
399
400












401
402
403
404
405
406
407
  int i, rc;
  
  if( db->init.busy ) return SQLITE_OK;
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }












  db->init.busy = 0;
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to







|
<





>
>
>
>
>
>
>
>
>
>
>
>







380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  int i, rc;
  
  if( db->init.busy ) return SQLITE_OK;
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;

    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }

  /* Once all the other databases have been initialised, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
  if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqliteInitOne(db, 1, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, 1);
    }
  }

  db->init.busy = 0;
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
){
#if SQLITE_MIN_SLEEP_MS==1
  static const char delays[] =
     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50,  50, 100};
  static const short int totals[] =
     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
  int timeout = (int)Timeout;
  int delay, prior;

  if( count <= NDELAY ){
    delay = delays[count-1];
    prior = totals[count-1];
  }else{
    delay = delays[NDELAY-1];
    prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
  }
  if( prior + delay > timeout ){
    delay = timeout - prior;
    if( delay<=0 ) return 0;
  }
  sqliteOsSleep(delay);
  return 1;
#else
  int timeout = (int)Timeout;
  if( (count+1)*1000 > timeout ){
    return 0;
  }
  sqliteOsSleep(1000);
  return 1;
#endif
}







|
















|







869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
){
#if SQLITE_MIN_SLEEP_MS==1
  static const char delays[] =
     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50,  50, 100};
  static const short int totals[] =
     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
  int timeout = (int)(long)Timeout;
  int delay, prior;

  if( count <= NDELAY ){
    delay = delays[count-1];
    prior = totals[count-1];
  }else{
    delay = delays[NDELAY-1];
    prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
  }
  if( prior + delay > timeout ){
    delay = timeout - prior;
    if( delay<=0 ) return 0;
  }
  sqliteOsSleep(delay);
  return 1;
#else
  int timeout = (int)(long)Timeout;
  if( (count+1)*1000 > timeout ){
    return 0;
  }
  sqliteOsSleep(1000);
  return 1;
#endif
}
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

/*
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
void sqlite_busy_timeout(sqlite *db, int ms){
  if( ms>0 ){
    sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)ms);
  }else{
    sqlite_busy_handler(db, 0, 0);
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.







|







939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

/*
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
void sqlite_busy_timeout(sqlite *db, int ms){
  if( ms>0 ){
    sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
  }else{
    sqlite_busy_handler(db, 0, 0);
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.

Changes to src/os.c.

460
461
462
463
464
465
466





467
468
469
470
471
472
473
  int *pReadonly
){
#if OS_UNIX
  int rc;
  id->dirfd = -1;
  id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
  if( id->fd<0 ){





    id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
    if( id->fd<0 ){
      return SQLITE_CANTOPEN; 
    }
    *pReadonly = 1;
  }else{
    *pReadonly = 0;







>
>
>
>
>







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  int *pReadonly
){
#if OS_UNIX
  int rc;
  id->dirfd = -1;
  id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
  if( id->fd<0 ){
#ifdef EISDIR
    if( errno==EISDIR ){
      return SQLITE_CANTOPEN;
    }
#endif
    id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
    if( id->fd<0 ){
      return SQLITE_CANTOPEN; 
    }
    *pReadonly = 1;
  }else{
    *pReadonly = 0;
769
770
771
772
773
774
775







776
777
778
779
780
781
782

783
784
785
786
787
788
789
790
791
792
793
794

795

796
797
798
799
800
801
802
    return SQLITE_CANTOPEN; 
  }
  TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname);
#endif
  return SQLITE_OK;
}








/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
*/
int sqliteOsTempFileName(char *zBuf){
#if OS_UNIX
  static const char *azDirs[] = {

     "/var/tmp",
     "/usr/tmp",
     "/tmp",
     ".",
  };
  static unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  struct stat buf;
  const char *zDir = ".";

  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){

    if( stat(azDirs[i], &buf) ) continue;
    if( !S_ISDIR(buf.st_mode) ) continue;
    if( access(azDirs[i], 07) ) continue;
    zDir = azDirs[i];
    break;
  }
  do{







>
>
>
>
>
>
>







>












>

>







774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
    return SQLITE_CANTOPEN; 
  }
  TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname);
#endif
  return SQLITE_OK;
}

/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
*/
const char *sqlite_temp_directory = 0;

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
*/
int sqliteOsTempFileName(char *zBuf){
#if OS_UNIX
  static const char *azDirs[] = {
     0,
     "/var/tmp",
     "/usr/tmp",
     "/tmp",
     ".",
  };
  static unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  struct stat buf;
  const char *zDir = ".";
  azDirs[0] = sqlite_temp_directory;
  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
    if( azDirs[i]==0 ) continue;
    if( stat(azDirs[i], &buf) ) continue;
    if( !S_ISDIR(buf.st_mode) ) continue;
    if( access(azDirs[i], 07) ) continue;
    zDir = azDirs[i];
    break;
  }
  do{
811
812
813
814
815
816
817

818

819
820
821




822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844


845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

862
863
864


865
866
867
868
869
870
871
872
873
#endif
#if OS_WIN
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;

  char zTempPath[SQLITE_TEMPNAME_SIZE];

  GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
  for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
  zTempPath[i] = 0;




  for(;;){
    sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
    j = strlen(zBuf);
    sqliteRandomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;
  }
#endif
#if OS_MAC
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;

  char zTempPath[SQLITE_TEMPNAME_SIZE];
  char zdirName[32];
  CInfoPBRec infoRec;
  Str31 dirName;
  memset(&infoRec, 0, sizeof(infoRec));
  memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);


  if( FindFolder(kOnSystemDisk, kTemporaryFolderType,  kCreateFolder,
       &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
    infoRec.dirInfo.ioNamePtr = dirName;
    do{
      infoRec.dirInfo.ioFDirIndex = -1;
      infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
      if( PBGetCatInfoSync(&infoRec) == noErr ){
        CopyPascalStringToC(dirName, zdirName);
        i = strlen(zdirName);
        memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
        strcpy(zTempPath, zdirName);
        zTempPath[i] = ':';
      }else{
        *zTempPath = 0;
        break;
      }
    } while( infoRec.dirInfo.ioDrDirID != fsRtDirID );

  }
  if( *zTempPath == 0 )
    getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);


  for(;;){
    sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zTempPath);
    j = strlen(zBuf);
    sqliteRandomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;







>

>
|
|
|
>
>
>
>

|















>






>
>
|
















>

|

>
>

|







826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
#endif
#if OS_WIN
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  const char *zDir;
  char zTempPath[SQLITE_TEMPNAME_SIZE];
  if( sqlite_temp_directory==0 ){
    GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
    for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
    zTempPath[i] = 0;
    zDir = zTempPath;
  }else{
    zDir = sqlite_temp_directory;
  }
  for(;;){
    sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir);
    j = strlen(zBuf);
    sqliteRandomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;
  }
#endif
#if OS_MAC
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  char *zDir;
  char zTempPath[SQLITE_TEMPNAME_SIZE];
  char zdirName[32];
  CInfoPBRec infoRec;
  Str31 dirName;
  memset(&infoRec, 0, sizeof(infoRec));
  memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
  if( sqlite_temp_directory!=0 ){
    zDir = sqlite_temp_directory;
  }else if( FindFolder(kOnSystemDisk, kTemporaryFolderType,  kCreateFolder,
       &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
    infoRec.dirInfo.ioNamePtr = dirName;
    do{
      infoRec.dirInfo.ioFDirIndex = -1;
      infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
      if( PBGetCatInfoSync(&infoRec) == noErr ){
        CopyPascalStringToC(dirName, zdirName);
        i = strlen(zdirName);
        memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
        strcpy(zTempPath, zdirName);
        zTempPath[i] = ':';
      }else{
        *zTempPath = 0;
        break;
      }
    } while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
    zDir = zTempPath;
  }
  if( zDir[0]==0 ){
    getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
    zDir = zTempPath;
  }
  for(;;){
    sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir);
    j = strlen(zBuf);
    sqliteRandomness(15, &zBuf[j]);
    for(i=0; i<15; i++, j++){
      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;
1084
1085
1086
1087
1088
1089
1090




1091
1092
1093
1094
1095
1096
1097
      return SQLITE_IOERR;
    }else{
      return SQLITE_OK;
    }
  }
#endif
}





/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory







>
>
>
>







1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
      return SQLITE_IOERR;
    }else{
      return SQLITE_OK;
    }
  }
#endif
}

#ifdef SQLITE_NOSYNC
# define fsync(X) 0
#endif

/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
char *sqliteOsFullPathname(const char *zRelative){
#if OS_UNIX
  char *zFull = 0;
  if( zRelative[0]=='/' ){
    sqliteSetString(&zFull, zRelative, (char*)0);
  }else{
    char zBuf[5000];

    sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
                    (char*)0);
  }
  return zFull;
#endif
#if OS_WIN
  char *zNotUsed;







>







1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
char *sqliteOsFullPathname(const char *zRelative){
#if OS_UNIX
  char *zFull = 0;
  if( zRelative[0]=='/' ){
    sqliteSetString(&zFull, zRelative, (char*)0);
  }else{
    char zBuf[5000];
    zBuf[0] = 0;
    sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
                    (char*)0);
  }
  return zFull;
#endif
#if OS_WIN
  char *zNotUsed;

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.101 2004/02/25 02:20:41 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>








|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.101.2.1 2005/12/19 17:37:10 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
** of the dont_rollback() call.
*/
void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
  PgHdr *pPg;

  pPg = pager_lookup(pPager, pgno);
  pPg->alwaysRollback = 1;
  if( pPg && pPg->dirty ){
    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
      /* If this pages is the last page in the file and the file has grown
      ** during the current transaction, then do NOT mark the page as clean.
      ** When the database file grows, we must make sure that the last page
      ** gets written at least once so that the disk file will be the correct
      ** size. If you do not write this page and the size of the file
      ** on the disk ends up being too small, that can lead to database







|







1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
** of the dont_rollback() call.
*/
void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
  PgHdr *pPg;

  pPg = pager_lookup(pPager, pgno);
  pPg->alwaysRollback = 1;
  if( pPg && pPg->dirty && !pPager->ckptInUse ){
    if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
      /* If this pages is the last page in the file and the file has grown
      ** during the current transaction, then do NOT mark the page as clean.
      ** When the database file grows, we must make sure that the last page
      ** gets written at least once so that the disk file will be the correct
      ** size. If you do not write this page and the size of the file
      ** on the disk ends up being too small, that can lead to database

Changes to src/printf.c.

223
224
225
226
227
228
229

230
231
232
233
234
235
236
  double rounder;            /* Used for rounding floating point values */
  etByte flag_dp;            /* True if decimal point should be shown */
  etByte flag_rtz;           /* True if trailing zeros should be removed */
  etByte flag_exp;           /* True to force display of the exponent */
  int nsd;                   /* Number of significant digits returned */
#endif


  count = length = 0;
  bufpt = 0;
  for(; (c=(*fmt))!=0; ++fmt){
    if( c!='%' ){
      int amt;
      bufpt = (char *)fmt;
      amt = 1;







>







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  double rounder;            /* Used for rounding floating point values */
  etByte flag_dp;            /* True if decimal point should be shown */
  etByte flag_rtz;           /* True if trailing zeros should be removed */
  etByte flag_exp;           /* True to force display of the exponent */
  int nsd;                   /* Number of significant digits returned */
#endif

  func(arg,"",0);
  count = length = 0;
  bufpt = 0;
  for(; (c=(*fmt))!=0; ++fmt){
    if( c!='%' ){
      int amt;
      bufpt = (char *)fmt;
      amt = 1;
669
670
671
672
673
674
675
676

677
678

679
680
681
682
683
684
685
          memcpy(pM->zText, pM->zBase, pM->nChar);
        }
      }else{
        pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
      }
    }
  }
  if( pM->zText && nNewChar>0 ){

    memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
    pM->nChar += nNewChar;

    pM->zText[pM->nChar] = 0;
  }
}

/*
** This routine is a wrapper around xprintf() that invokes mout() as
** the consumer.  







|
>
|
|
>







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
          memcpy(pM->zText, pM->zBase, pM->nChar);
        }
      }else{
        pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
      }
    }
  }
  if( pM->zText ){
    if( nNewChar>0 ){
      memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
      pM->nChar += nNewChar;
    }
    pM->zText[pM->nChar] = 0;
  }
}

/*
** This routine is a wrapper around xprintf() that invokes mout() as
** the consumer.  

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.161 2004/03/13 14:00:36 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.161.2.4 2004/07/20 01:45:49 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
359
360
361
362
363
364
365
























366
367
368
369
370
371
372
  if( zType==0 ) return;
  for(i=0; i<nColumn; i++){
    zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
  }
  zType[i] = 0;
  sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
}

























/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab and nColumn are both zero, then the pEList expressions
** are evaluated in order to get the data for this row.  If nColumn>0







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  if( zType==0 ) return;
  for(i=0; i<nColumn; i++){
    zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
  }
  zType[i] = 0;
  sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
}

/*
** Add code to implement the OFFSET and LIMIT
*/
static void codeLimiter(
  Vdbe *v,          /* Generate code into this VM */
  Select *p,        /* The SELECT statement being coded */
  int iContinue,    /* Jump here to skip the current record */
  int iBreak,       /* Jump here to end the loop */
  int nPop          /* Number of times to pop stack when jumping */
){
  if( p->iOffset>=0 ){
    int addr = sqliteVdbeCurrentAddr(v) + 2;
    if( nPop>0 ) addr++;
    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
    if( nPop>0 ){
      sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
    }
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
  }
  if( p->iLimit>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
  }
}

/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab and nColumn are both zero, then the pEList expressions
** are evaluated in order to get the data for this row.  If nColumn>0
384
385
386
387
388
389
390

391
392
393
394
395
396
397

398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;


  if( v==0 ) return 0;
  assert( pEList!=0 );

  /* If there was a LIMIT clause on the SELECT statement, then do the check
  ** to see if this row should be output.
  */

  if( pOrderBy==0 ){
    if( p->iOffset>=0 ){
      int addr = sqliteVdbeCurrentAddr(v);
      sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
      sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
    }
    if( p->iLimit>=0 ){
      sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
    }
  }

  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqliteVdbeAddOp(v, OP_Column, srcTab, i);
    }
  }else{
    nColumn = pEList->nExpr;
    for(i=0; i<pEList->nExpr; i++){
      sqliteExprCode(pParse, pEList->a[i].pExpr);
    }
  }

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( distinct>=0 && pEList && pEList->nExpr>0 ){
#if NULL_ALWAYS_DISTINCT
    sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
#endif
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
    if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);



  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
    */
    case SRT_Union: {







>







>
|
<
<
<
|
<
<
<
<



















|










>
>
>







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424



425




426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int hasDistinct;        /* True if the DISTINCT keyword is present */

  if( v==0 ) return 0;
  assert( pEList!=0 );

  /* If there was a LIMIT clause on the SELECT statement, then do the check
  ** to see if this row should be output.
  */
  hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
  if( pOrderBy==0 && !hasDistinct ){



    codeLimiter(v, p, iContinue, iBreak, 0);




  }

  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqliteVdbeAddOp(v, OP_Column, srcTab, i);
    }
  }else{
    nColumn = pEList->nExpr;
    for(i=0; i<pEList->nExpr; i++){
      sqliteExprCode(pParse, pEList->a[i].pExpr);
    }
  }

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
#if NULL_ALWAYS_DISTINCT
    sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
#endif
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
    if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
    if( pOrderBy==0 ){
      codeLimiter(v, p, iContinue, iBreak, nColumn);
    }
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
    */
    case SRT_Union: {
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
){
  int end1 = sqliteVdbeMakeLabel(v);
  int end2 = sqliteVdbeMakeLabel(v);
  int addr;
  if( eDest==SRT_Sorter ) return;
  sqliteVdbeAddOp(v, OP_Sort, 0, 0);
  addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
  if( p->iOffset>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  }
  if( p->iLimit>=0 ){
    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
  }
  switch( eDest ){
    case SRT_Callback: {
      sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
      break;
    }
    case SRT_Table:
    case SRT_TempTable: {







<
<
<
<
<
|
<
<







588
589
590
591
592
593
594





595


596
597
598
599
600
601
602
){
  int end1 = sqliteVdbeMakeLabel(v);
  int end2 = sqliteVdbeMakeLabel(v);
  int addr;
  if( eDest==SRT_Sorter ) return;
  sqliteVdbeAddOp(v, OP_Sort, 0, 0);
  addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);





  codeLimiter(v, p, addr, end2, 1);


  switch( eDest ){
    case SRT_Callback: {
      sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
      break;
    }
    case SRT_Table:
    case SRT_TempTable: {
806
807
808
809
810
811
812
813
814

815
816
817
818
819
820
821
        }
      }
    }else if( p->span.z && p->span.z[0] ){
      sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
    }else{
      char zBuf[30];
      sprintf(zBuf, "column%d", i+1);
      pTab->aCol[i].zName = sqliteStrDup(zBuf);
    }

  }
  pTab->iPKey = -1;
  return pTab;
}

/*
** For the given SELECT statement, do three things.







|

>







821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
        }
      }
    }else if( p->span.z && p->span.z[0] ){
      sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
    }else{
      char zBuf[30];
      sprintf(zBuf, "column%d", i+1);
      aCol[i].zName = sqliteStrDup(zBuf);
    }
    sqliteDequote(aCol[i].zName);
  }
  pTab->iPKey = -1;
  return pTab;
}

/*
** For the given SELECT statement, do three things.
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
        pNew->a[pNew->nExpr-1].zName = a[k].zName;
        a[k].pExpr = 0;
        a[k].zName = 0;
      }else{
        /* This expression is a "*" or a "TABLE.*" and needs to be
        ** expanded. */
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
        Token *pName;           /* text of name of TABLE */
        if( pE->op==TK_DOT && pE->pLeft ){
          pName = &pE->pLeft->token;
        }else{
          pName = 0;
        }
        for(i=0; i<pTabList->nSrc; i++){
          Table *pTab = pTabList->a[i].pTab;
          char *zTabName = pTabList->a[i].zAlias;
          if( zTabName==0 || zTabName[0]==0 ){ 
            zTabName = pTab->zName;
          }
          if( pName && (zTabName==0 || zTabName[0]==0 || 
                 sqliteStrNICmp(pName->z, zTabName, pName->n)!=0 ||
                 zTabName[pName->n]!=0) ){
            continue;
          }
          tableSeen = 1;
          for(j=0; j<pTab->nCol; j++){
            Expr *pExpr, *pLeft, *pRight;
            char *zName = pTab->aCol[j].zName;








|

|

|







|
<
|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982
        pNew->a[pNew->nExpr-1].zName = a[k].zName;
        a[k].pExpr = 0;
        a[k].zName = 0;
      }else{
        /* This expression is a "*" or a "TABLE.*" and needs to be
        ** expanded. */
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
        char *zTName;           /* text of name of TABLE */
        if( pE->op==TK_DOT && pE->pLeft ){
          zTName = sqliteTableNameFromToken(&pE->pLeft->token);
        }else{
          zTName = 0;
        }
        for(i=0; i<pTabList->nSrc; i++){
          Table *pTab = pTabList->a[i].pTab;
          char *zTabName = pTabList->a[i].zAlias;
          if( zTabName==0 || zTabName[0]==0 ){ 
            zTabName = pTab->zName;
          }
          if( zTName && (zTabName==0 || zTabName[0]==0 || 

                 sqliteStrICmp(zTName, zTabName)!=0) ){
            continue;
          }
          tableSeen = 1;
          for(j=0; j<pTab->nCol; j++){
            Expr *pExpr, *pLeft, *pRight;
            char *zName = pTab->aCol[j].zName;

998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
              pExpr = pRight;
              pExpr->span = pExpr->token;
            }
            pNew = sqliteExprListAppend(pNew, pExpr, 0);
          }
        }
        if( !tableSeen ){
          if( pName ){
            sqliteErrorMsg(pParse, "no such table: %T", pName);
          }else{
            sqliteErrorMsg(pParse, "no tables specified");
          }
          rc = 1;
        }

      }
    }
    sqliteExprListDelete(pEList);
    p->pEList = pNew;
  }
  return rc;
}







|
|





>







1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
              pExpr = pRight;
              pExpr->span = pExpr->token;
            }
            pNew = sqliteExprListAppend(pNew, pExpr, 0);
          }
        }
        if( !tableSeen ){
          if( zTName ){
            sqliteErrorMsg(pParse, "no such table: %s", zTName);
          }else{
            sqliteErrorMsg(pParse, "no tables specified");
          }
          rc = 1;
        }
        sqliteFree(zTName);
      }
    }
    sqliteExprListDelete(pEList);
    p->pEList = pNew;
  }
  return rc;
}
1912
1913
1914
1915
1916
1917
1918






1919
1920
1921
1922
1923
1924
1925
  }
  cont = sqliteVdbeMakeLabel(v);
  if( pIdx==0 ){
    sqliteVdbeAddOp(v, seekOp, base, 0);
  }else{
    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);






    sqliteVdbeAddOp(v, seekOp, base+1, 0);
    sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
    sqliteVdbeAddOp(v, OP_Close, base+1, 0);
    sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
  }
  eList.nExpr = 1;
  memset(&eListItem, 0, sizeof(eListItem));







>
>
>
>
>
>







1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
  }
  cont = sqliteVdbeMakeLabel(v);
  if( pIdx==0 ){
    sqliteVdbeAddOp(v, seekOp, base, 0);
  }else{
    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
    if( seekOp==OP_Rewind ){
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
      sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
      seekOp = OP_MoveTo;
    }
    sqliteVdbeAddOp(v, seekOp, base+1, 0);
    sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
    sqliteVdbeAddOp(v, OP_Close, base+1, 0);
    sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
  }
  eList.nExpr = 1;
  memset(&eListItem, 0, sizeof(eListItem));

Changes to src/shell.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.93 2004/03/17 23:42:13 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <ctype.h>








|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.93.2.1 2005/02/16 03:53:11 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <ctype.h>

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    char *zErrMsg = 0;
    open_db(p);
    fprintf(p->out, "BEGIN TRANSACTION;\n");
    if( nArg==1 ){
      sqlite_exec(p->db,
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE type!='meta' AND sql NOT NULL "
        "ORDER BY substr(type,2,1), name",
        dump_callback, p, &zErrMsg
      );
    }else{
      int i;
      for(i=1; i<nArg && zErrMsg==0; i++){
        sqlite_exec_printf(p->db,
          "SELECT name, type, sql FROM sqlite_master "
          "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
          "ORDER BY substr(type,2,1), name",
          dump_callback, p, &zErrMsg, azArg[i]
        );
      }
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite_freemem(zErrMsg);







|








|







587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    char *zErrMsg = 0;
    open_db(p);
    fprintf(p->out, "BEGIN TRANSACTION;\n");
    if( nArg==1 ){
      sqlite_exec(p->db,
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE type!='meta' AND sql NOT NULL "
        "ORDER BY substr(type,2,1), rowid",
        dump_callback, p, &zErrMsg
      );
    }else{
      int i;
      for(i=1; i<nArg && zErrMsg==0; i++){
        sqlite_exec_printf(p->db,
          "SELECT name, type, sql FROM sqlite_master "
          "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
          "ORDER BY substr(type,2,1), rowid",
          dump_callback, p, &zErrMsg, azArg[i]
        );
      }
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite_freemem(zErrMsg);

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30



31

32
33
34
35
36
37
38
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.60 2004/03/14 22:12:35 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif

/*
** The version of the SQLite library.
*/



#define SQLITE_VERSION         "--VERS--"


/*
** The version string is also compiled into the library so that a program
** can check to make sure that the lib*.a file and the *.h file are from
** the same version.
*/
extern const char sqlite_version[];







|















>
>
>
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.60.2.1 2004/10/06 15:52:36 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif

/*
** The version of the SQLite library.
*/
#ifdef SQLITE_VERSION
# undef SQLITE_VERSION
#else
# define SQLITE_VERSION         "--VERS--"
#endif

/*
** The version string is also compiled into the library so that a program
** can check to make sure that the lib*.a file and the *.h file are from
** the same version.
*/
extern const char sqlite_version[];
475
476
477
478
479
480
481
482
483














484
485
486
487
488
489
490
*/
int sqlite_function_type(
  sqlite *db,               /* The database there the function is registered */
  const char *zName,        /* Name of the function */
  int datatype              /* The datatype for this function */
);
#define SQLITE_NUMERIC     (-1)
#define SQLITE_TEXT        (-2)
#define SQLITE_ARGS        (-3)















/*
** The user function implementations call one of the following four routines
** in order to return their results.  The first parameter to each of these
** routines is a copy of the first argument to xFunc() or xFinialize().
** The second parameter to these routines is the result to be returned.
** A NULL can be passed as the second parameter to sqlite_set_result_string()







|

>
>
>
>
>
>
>
>
>
>
>
>
>
>







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
*/
int sqlite_function_type(
  sqlite *db,               /* The database there the function is registered */
  const char *zName,        /* Name of the function */
  int datatype              /* The datatype for this function */
);
#define SQLITE_NUMERIC     (-1)
/* #define SQLITE_TEXT     (-2)  // See below */
#define SQLITE_ARGS        (-3)

/*
** SQLite version 3 defines SQLITE_TEXT differently.  To allow both
** version 2 and version 3 to be included, undefine them both if a
** conflict is seen.  Define SQLITE2_TEXT to be the version 2 value.
*/
#ifdef SQLITE_TEXT
# undef SQLITE_TEXT
#else
# define SQLITE_TEXT     (-2)
#endif
#define SQLITE2_TEXT     (-2)



/*
** The user function implementations call one of the following four routines
** in order to return their results.  The first parameter to each of these
** routines is a copy of the first argument to xFunc() or xFinialize().
** The second parameter to these routines is the result to be returned.
** A NULL can be passed as the second parameter to sqlite_set_result_string()

Changes to src/sqliteInt.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.220 2004/02/25 13:47:33 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.220.2.2 2005/06/06 15:07:03 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
98
99
100
101
102
103
104



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
*/
#ifndef UINT32_TYPE
# define UINT32_TYPE unsigned int
#endif
#ifndef UINT16_TYPE
# define UINT16_TYPE unsigned short int
#endif



#ifndef UINT8_TYPE
# define UINT8_TYPE unsigned char
#endif
#ifndef INT8_TYPE
# define INT8_TYPE signed char
#endif
#ifndef INTPTR_TYPE
# if SQLITE_PTR_SZ==4
#   define INTPTR_TYPE int
# else
#   define INTPTR_TYPE long long
# endif
#endif
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */

typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
typedef UINT8_TYPE i8;             /* 1-byte signed integer */
typedef INTPTR_TYPE ptr;           /* Big enough to hold a pointer */
typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */

/*
** Defer sourcing vdbe.h until after the "u8" typedef is defined.







>
>
>















>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
*/
#ifndef UINT32_TYPE
# define UINT32_TYPE unsigned int
#endif
#ifndef UINT16_TYPE
# define UINT16_TYPE unsigned short int
#endif
#ifndef INT16_TYPE
# define INT16_TYPE short int
#endif
#ifndef UINT8_TYPE
# define UINT8_TYPE unsigned char
#endif
#ifndef INT8_TYPE
# define INT8_TYPE signed char
#endif
#ifndef INTPTR_TYPE
# if SQLITE_PTR_SZ==4
#   define INTPTR_TYPE int
# else
#   define INTPTR_TYPE long long
# endif
#endif
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
typedef INT16_TYPE i16;            /* 2-byte signed integer */
typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
typedef UINT8_TYPE i8;             /* 1-byte signed integer */
typedef INTPTR_TYPE ptr;           /* Big enough to hold a pointer */
typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */

/*
** Defer sourcing vdbe.h until after the "u8" typedef is defined.
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
** With the addition of multiple database support, the following structure
** can also be used to describe a particular table such as the table that
** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
** such a table must be a simple name: ID.  But in SQLite, the table can
** now be identified by a database name, a dot, then the table name: ID.ID.
*/
struct SrcList {
  u16 nSrc;        /* Number of tables or subqueries in the FROM clause */
  u16 nAlloc;      /* Number of entries allocated in a[] below */
  struct SrcList_item {
    char *zDatabase;  /* Name of database holding this table */
    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    int jointype;     /* Type of join between this table and the next */







|
|







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
** With the addition of multiple database support, the following structure
** can also be used to describe a particular table such as the table that
** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
** such a table must be a simple name: ID.  But in SQLite, the table can
** now be identified by a database name, a dot, then the table name: ID.ID.
*/
struct SrcList {
  i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
  i16 nAlloc;      /* Number of entries allocated in a[] below */
  struct SrcList_item {
    char *zDatabase;  /* Name of database holding this table */
    char *zName;      /* Name of the table */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
    int jointype;     /* Type of join between this table and the next */
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  void *sqliteRealloc(void*,int);
  char *sqliteStrDup(const char*);
  char *sqliteStrNDup(const char*, int);
# define sqliteCheckMemory(a,b)
#endif
char *sqliteMPrintf(const char*, ...);
char *sqliteVMPrintf(const char*, va_list);
void sqliteSetString(char **, const char *, ...);
void sqliteSetNString(char **, ...);
void sqliteErrorMsg(Parse*, const char*, ...);
void sqliteDequote(char*);
int sqliteKeywordCode(const char*, int);
int sqliteRunParser(Parse*, const char*, char **);
void sqliteExec(Parse*);
Expr *sqliteExpr(int, Expr*, Expr*, Token*);







|







1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
  void *sqliteRealloc(void*,int);
  char *sqliteStrDup(const char*);
  char *sqliteStrNDup(const char*, int);
# define sqliteCheckMemory(a,b)
#endif
char *sqliteMPrintf(const char*, ...);
char *sqliteVMPrintf(const char*, va_list);
void sqliteSetString(char **, ...);
void sqliteSetNString(char **, ...);
void sqliteErrorMsg(Parse*, const char*, ...);
void sqliteDequote(char*);
int sqliteKeywordCode(const char*, int);
int sqliteRunParser(Parse*, const char*, char **);
void sqliteExec(Parse*);
Expr *sqliteExpr(int, Expr*, Expr*, Token*);

Changes to src/table.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
typedef struct TabResult {
  char **azResult;
  char *zErrMsg;
  int nResult;
  int nAlloc;
  int nRow;
  int nColumn;
  int nData;
  int rc;
} TabResult;

/*
** This routine is called once for each row in the result table.  Its job
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
typedef struct TabResult {
  char **azResult;
  char *zErrMsg;
  int nResult;
  int nAlloc;
  int nRow;
  int nColumn;
  long nData;
  int rc;
} TabResult;

/*
** This routine is called once for each row in the result table.  Its job
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.
192
193
194
195
196
197
198
199
200
201
202
203
void sqlite_free_table(
  char **azResult             /* Result returned from from sqlite_get_table() */
){
  if( azResult ){
    int i, n;
    azResult--;
    if( azResult==0 ) return;
    n = (int)azResult[0];
    for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
    free(azResult);
  }
}







|




192
193
194
195
196
197
198
199
200
201
202
203
void sqlite_free_table(
  char **azResult             /* Result returned from from sqlite_get_table() */
){
  if( azResult ){
    int i, n;
    azResult--;
    if( azResult==0 ) return;
    n = (int)(long)azResult[0];
    for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
    free(azResult);
  }
}

Changes to src/tclsqlite.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.59 2004/02/25 22:51:06 rdc Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.59.2.1 2004/06/19 11:57:40 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
1161
1162
1163
1164
1165
1166
1167





1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
1179
1180
** If compiled using mktclapp, this routine runs to initialize
** everything.
*/
int Et_AppInit(Tcl_Interp *interp){
  return Sqlite_Init(interp);
}
#endif






/*
** If the macro TCLSH is defined and is one, then put in code for the
** "main" routine that will initialize Tcl.

*/
#if defined(TCLSH) && TCLSH==1
static char zMainloop[] =
  "set line {}\n"
  "while {![eof stdin]} {\n"
    "if {$line!=\"\"} {\n"
      "puts -nonewline \"> \"\n"
    "} else {\n"
      "puts -nonewline \"% \"\n"







>
>
>
>
>



|
>

|







1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
** If compiled using mktclapp, this routine runs to initialize
** everything.
*/
int Et_AppInit(Tcl_Interp *interp){
  return Sqlite_Init(interp);
}
#endif
/***************************************************************************
** The remaining code is only included if the TCLSH macro is defined to
** be an integer greater than 0
*/
#if defined(TCLSH) && TCLSH>0

/*
** If the macro TCLSH is defined and is one, then put in code for the
** "main" routine that implement a interactive shell into which the user
** can type TCL commands.
*/
#if TCLSH==1
static char zMainloop[] =
  "set line {}\n"
  "while {![eof stdin]} {\n"
    "if {$line!=\"\"} {\n"
      "puts -nonewline \"> \"\n"
    "} else {\n"
      "puts -nonewline \"% \"\n"
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200

1201



1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216











1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234




1235

































1236
1237
1238
      "}\n"
      "set line {}\n"
    "} else {\n"
      "append line \\n\n"
    "}\n"
  "}\n"
;


#define TCLSH_MAIN main   /* Needed to fake out mktclapp */
int TCLSH_MAIN(int argc, char **argv){
  Tcl_Interp *interp;
  Tcl_FindExecutable(argv[0]);

  interp = Tcl_CreateInterp();



  Sqlite_Init(interp);
#ifdef SQLITE_TEST
  {
    extern int Sqlitetest1_Init(Tcl_Interp*);
    extern int Sqlitetest2_Init(Tcl_Interp*);
    extern int Sqlitetest3_Init(Tcl_Interp*);
    extern int Sqlitetest4_Init(Tcl_Interp*);
    extern int Md5_Init(Tcl_Interp*);
    Sqlitetest1_Init(interp);
    Sqlitetest2_Init(interp);
    Sqlitetest3_Init(interp);
    Sqlitetest4_Init(interp);
    Md5_Init(interp);

  }
#endif











  if( argc>=2 ){
    int i;
    Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
    for(i=2; i<argc; i++){
      Tcl_SetVar(interp, "argv", argv[i],
          TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
    }
    if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
      const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
      if( zInfo==0 ) zInfo = interp->result;
      fprintf(stderr,"%s: %s\n", *argv, zInfo);
      return 1;
    }
  }else{
    Tcl_GlobalEval(interp, zMainloop);
  }
  return 0;




}

































#endif /* TCLSH */

#endif /* !defined(NO_TCL) */







>

<
<
|
<
>
|
>
>
>






<




<

>


>
>
>
>
>
>
>
>
>
>
>












|





>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
1195
1196
1197
1198
1199
1200
1201
1202
1203


1204

1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
      "}\n"
      "set line {}\n"
    "} else {\n"
      "append line \\n\n"
    "}\n"
  "}\n"
;
#endif /* TCLSH==1 */



int Libsqlite_Init( Tcl_Interp *interp) {

#ifdef TCL_THREADS
  if (Thread_Init(interp) == TCL_ERROR) {
    return TCL_ERROR;
  }
#endif
  Sqlite_Init(interp);
#ifdef SQLITE_TEST
  {
    extern int Sqlitetest1_Init(Tcl_Interp*);
    extern int Sqlitetest2_Init(Tcl_Interp*);
    extern int Sqlitetest3_Init(Tcl_Interp*);

    extern int Md5_Init(Tcl_Interp*);
    Sqlitetest1_Init(interp);
    Sqlitetest2_Init(interp);
    Sqlitetest3_Init(interp);

    Md5_Init(interp);
    Tcl_StaticPackage(interp, "sqlite", Libsqlite_Init, Libsqlite_Init);
  }
#endif
  return TCL_OK;
}

#define TCLSH_MAIN main   /* Needed to fake out mktclapp */
#if TCLSH==1
int TCLSH_MAIN(int argc, char **argv){
#ifndef TCL_THREADS
  Tcl_Interp *interp;
  Tcl_FindExecutable(argv[0]);
  interp = Tcl_CreateInterp();
  Libsqlite_Init(interp);
  if( argc>=2 ){
    int i;
    Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
    Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
    for(i=2; i<argc; i++){
      Tcl_SetVar(interp, "argv", argv[i],
          TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
    }
    if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
      const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
      if( zInfo==0 ) zInfo = interp->result;
      fprintf(stderr,"%s: %s\n", *argv, zInfo);
      return TCL_ERROR;
    }
  }else{
    Tcl_GlobalEval(interp, zMainloop);
  }
  return 0;
#else
  Tcl_Main(argc, argv, Libsqlite_Init);
#endif /* TCL_THREADS */
  return 0;
}
#endif /* TCLSH==1 */


/*
** If the macro TCLSH is set to 2, then implement a space analysis tool.
*/
#if TCLSH==2
static char zAnalysis[] = 
#include "spaceanal_tcl.h"
;

int main(int argc, char **argv){
  Tcl_Interp *interp;
  int i;
  Tcl_FindExecutable(argv[0]);
  interp = Tcl_CreateInterp();
  Libsqlite_Init(interp);
  Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
  Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
  for(i=1; i<argc; i++){
    Tcl_SetVar(interp, "argv", argv[i],
        TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
  }
  if( Tcl_GlobalEval(interp, zAnalysis)!=TCL_OK ){
    const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
    if( zInfo==0 ) zInfo = interp->result;
    fprintf(stderr,"%s: %s\n", *argv, zInfo);
    return TCL_ERROR;
  }
  return 0;
}
#endif /* TCLSH==2 */

#endif /* TCLSH */

#endif /* NO_TCL */

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.36 2004/02/22 17:49:34 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.36.2.1 2004/05/07 00:57:06 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

971
972
973
974
975
976
977

978
979
980
981
982
983
984
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite_search_count;
  extern int sqlite_interrupt_count;
  extern int sqlite_open_file_count;
  extern int sqlite_current_time;

  static struct {
     char *zName;
     Tcl_CmdProc *xProc;
  } aCmd[] = {
     { "sqlite_mprintf_int",             (Tcl_CmdProc*)sqlite_mprintf_int    },
     { "sqlite_mprintf_str",             (Tcl_CmdProc*)sqlite_mprintf_str    },
     { "sqlite_mprintf_double",          (Tcl_CmdProc*)sqlite_mprintf_double },







>







971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  extern int sqlite_search_count;
  extern int sqlite_interrupt_count;
  extern int sqlite_open_file_count;
  extern int sqlite_current_time;
  extern int sqlite_temp_directory;
  static struct {
     char *zName;
     Tcl_CmdProc *xProc;
  } aCmd[] = {
     { "sqlite_mprintf_int",             (Tcl_CmdProc*)sqlite_mprintf_int    },
     { "sqlite_mprintf_str",             (Tcl_CmdProc*)sqlite_mprintf_str    },
     { "sqlite_mprintf_double",          (Tcl_CmdProc*)sqlite_mprintf_double },
1016
1017
1018
1019
1020
1021
1022


1023
1024
      (char*)&sqlite_interrupt_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_open_file_count", 
      (char*)&sqlite_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_static_bind_value",
      (char*)&sqlite_static_bind_value, TCL_LINK_STRING);


  return TCL_OK;
}







>
>


1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
      (char*)&sqlite_interrupt_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_open_file_count", 
      (char*)&sqlite_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_static_bind_value",
      (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
  Tcl_LinkVar(interp, "sqlite_temp_directory",
      (char*)&sqlite_temp_directory, TCL_LINK_STRING);
  return TCL_OK;
}

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.70 2004/02/22 20:05:02 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
**          \_______/ \________/     \______/       \________________/
*            onError   pTabList      pChanges             pWhere
*/
void sqliteUpdate(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table in which we should change things */
  ExprList *pChanges,    /* Things to be changed */
  Expr *pWhere,          /* The WHERE clause.  May be null */
  int onError            /* How to handle constraint errors */
){
  int i, j;              /* Loop counters */
  Table *pTab;           /* The table to be updated */
  int addr;              /* VDBE instruction address of the start of the loop */

  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  Vdbe *v;               /* The virtual database engine */
  Index *pIdx;           /* For looping over indices */
  int nIdx;              /* Number of indices that need updating */
  int nIdxTotal;         /* Total number of indices */
  int iCur;              /* VDBE Cursor number of pTab */
  sqlite *db;            /* The database structure */
  Index **apIdx = 0;     /* An array of indices that need updating too */
  char *aIdxUsed = 0;    /* aIdxUsed[i]==1 if the i-th index is used */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */
  int chngRecno;         /* True if the record number is being changed */
  Expr *pRecnoExpr;      /* Expression defining the new record number */
  int openAll;           /* True if all indices need to be opened */
  int isView;            /* Trying to update a view */

  AuthContext sContext;  /* The authorization context */

  int before_triggers;         /* True if there are any BEFORE triggers */
  int after_triggers;          /* True if there are any AFTER triggers */
  int row_triggers_exist = 0;  /* True if any row triggers exist */

  int newIdx      = -1;  /* index of trigger "new" temp table       */
  int oldIdx      = -1;  /* index of trigger "old" temp table       */

  sContext.pParse = 0;
  if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
  db = pParse->db;
  assert( pTabList->nSrc==1 );


  /* Locate the table which we want to update. 
  */
  pTab = sqliteSrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;
  before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
            TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);







|



















|
>
















>













>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.70.2.1 2004/04/29 16:16:29 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
**          \_______/ \________/     \______/       \________________/
*            onError   pTabList      pChanges             pWhere
*/
void sqliteUpdate(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table in which we should change things */
  ExprList *pChanges,    /* Things to be changed */
  Expr *pWhere,          /* The WHERE clause.  May be null */
  int onError            /* How to handle constraint errors */
){
  int i, j;              /* Loop counters */
  Table *pTab;           /* The table to be updated */
  int loopStart;         /* VDBE instruction address of the start of the loop */
  int jumpInst;          /* Addr of VDBE instruction to jump out of loop */
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  Vdbe *v;               /* The virtual database engine */
  Index *pIdx;           /* For looping over indices */
  int nIdx;              /* Number of indices that need updating */
  int nIdxTotal;         /* Total number of indices */
  int iCur;              /* VDBE Cursor number of pTab */
  sqlite *db;            /* The database structure */
  Index **apIdx = 0;     /* An array of indices that need updating too */
  char *aIdxUsed = 0;    /* aIdxUsed[i]==1 if the i-th index is used */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */
  int chngRecno;         /* True if the record number is being changed */
  Expr *pRecnoExpr;      /* Expression defining the new record number */
  int openAll;           /* True if all indices need to be opened */
  int isView;            /* Trying to update a view */
  int iStackDepth;       /* Index of memory cell holding stack depth */
  AuthContext sContext;  /* The authorization context */

  int before_triggers;         /* True if there are any BEFORE triggers */
  int after_triggers;          /* True if there are any AFTER triggers */
  int row_triggers_exist = 0;  /* True if any row triggers exist */

  int newIdx      = -1;  /* index of trigger "new" temp table       */
  int oldIdx      = -1;  /* index of trigger "old" temp table       */

  sContext.pParse = 0;
  if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
  db = pParse->db;
  assert( pTabList->nSrc==1 );
  iStackDepth = pParse->nMem++;

  /* Locate the table which we want to update. 
  */
  pTab = sqliteSrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;
  before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
            TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
244
245
246
247
248
249
250




251
252
253
254
255
256
257
258
    */
    sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);

    /* The top of the update loop for when there are triggers.
    */
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);




    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);

    /* Open a cursor and make it point to the record that is
    ** being updated.
    */
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    if( !isView ){







>
>
>
>
|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    */
    sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);

    /* The top of the update loop for when there are triggers.
    */
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
    sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
    loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
    sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
    jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);

    /* Open a cursor and make it point to the record that is
    ** being updated.
    */
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    if( !isView ){
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
    if( !isView ){
      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
    }

    /* Fire the BEFORE and INSTEAD OF triggers
    */
    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
          newIdx, oldIdx, onError, addr) ){
      goto update_cleanup;
    }
  }

  if( !isView ){
    /* 
    ** Open every index that needs updating.  Note that if any







|







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    if( !isView ){
      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
    }

    /* Fire the BEFORE and INSTEAD OF triggers
    */
    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
          newIdx, oldIdx, onError, loopStart) ){
      goto update_cleanup;
    }
  }

  if( !isView ){
    /* 
    ** Open every index that needs updating.  Note that if any
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entires.
    ** So make the cursor point at the old record.
    */
    if( !row_triggers_exist ){
      sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    }
    sqliteVdbeAddOp(v, OP_NotExists, iCur, addr);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRecno ){
      sqliteExprCode(pParse, pRecnoExpr);







|


|







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entires.
    ** So make the cursor point at the old record.
    */
    if( !row_triggers_exist ){
      sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
      jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    }
    sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRecno ){
      sqliteExprCode(pParse, pRecnoExpr);
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
        sqliteExprCode(pParse, pChanges->a[j].pExpr);
      }
    }

    /* Do constraint checks
    */
    sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
                                   onError, addr);

    /* Delete the old indices for the current record.
    */
    sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);

    /* If changing the record number, delete the old record.
    */







|







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
        sqliteExprCode(pParse, pChanges->a[j].pExpr);
      }
    }

    /* Do constraint checks
    */
    sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
                                   onError, loopStart);

    /* Delete the old indices for the current record.
    */
    sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);

    /* If changing the record number, delete the old record.
    */
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
        if( openAll || aIdxUsed[i] )
          sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
      }
      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
      pParse->nTab = iCur;
    }
    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
          newIdx, oldIdx, onError, addr) ){
      goto update_cleanup;
    }
  }

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

  /* Close all tables if there were no FOR EACH ROW triggers */
  if( !row_triggers_exist ){
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] ){
        sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);







|







|
|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
        if( openAll || aIdxUsed[i] )
          sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
      }
      sqliteVdbeAddOp(v, OP_Close, iCur, 0);
      pParse->nTab = iCur;
    }
    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
          newIdx, oldIdx, onError, loopStart) ){
      goto update_cleanup;
    }
  }

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
  sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

  /* Close all tables if there were no FOR EACH ROW triggers */
  if( !row_triggers_exist ){
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] ){
        sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);

Changes to src/util.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.74 2004/02/22 17:49:34 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** If malloc() ever fails, this global variable gets set to 1.







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.74.2.2 2005/06/06 15:07:03 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** If malloc() ever fails, this global variable gets set to 1.
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/*
** Create a string from the 2nd and subsequent arguments (up to the
** first NULL argument), store the string in memory obtained from
** sqliteMalloc() and make the pointer indicated by the 1st argument
** point to that string.  The 1st argument must either be NULL or 
** point to memory obtained from sqliteMalloc().
*/
void sqliteSetString(char **pz, const char *zFirst, ...){
  va_list ap;
  int nByte;
  const char *z;
  char *zResult;

  if( pz==0 ) return;
  nByte = strlen(zFirst) + 1;
  va_start(ap, zFirst);
  while( (z = va_arg(ap, const char*))!=0 ){
    nByte += strlen(z);
  }
  va_end(ap);
  sqliteFree(*pz);
  *pz = zResult = sqliteMallocRaw( nByte );
  if( zResult==0 ){
    return;
  }
  strcpy(zResult, zFirst);
  zResult += strlen(zResult);
  va_start(ap, zFirst);
  while( (z = va_arg(ap, const char*))!=0 ){
    strcpy(zResult, z);
    zResult += strlen(zResult);
  }
  va_end(ap);
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1







|






|
|









<
|
|







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
/*
** Create a string from the 2nd and subsequent arguments (up to the
** first NULL argument), store the string in memory obtained from
** sqliteMalloc() and make the pointer indicated by the 1st argument
** point to that string.  The 1st argument must either be NULL or 
** point to memory obtained from sqliteMalloc().
*/
void sqliteSetString(char **pz, ...){
  va_list ap;
  int nByte;
  const char *z;
  char *zResult;

  if( pz==0 ) return;
  nByte = 1;
  va_start(ap, pz);
  while( (z = va_arg(ap, const char*))!=0 ){
    nByte += strlen(z);
  }
  va_end(ap);
  sqliteFree(*pz);
  *pz = zResult = sqliteMallocRaw( nByte );
  if( zResult==0 ){
    return;
  }

  *zResult = 0;
  va_start(ap, pz);
  while( (z = va_arg(ap, const char*))!=0 ){
    strcpy(zResult, z);
    zResult += strlen(zResult);
  }
  va_end(ap);
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
** there is no consistency, we will define our own.
*/
int sqliteStrICmp(const char *zLeft, const char *zRight){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return *a - *b;
}
int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return N<0 ? 0 : *a - *b;
}

/*
** Return TRUE if z is a pure numeric string.  Return FALSE if the
** string contains any character which is not part of a number.
**
** Am empty string is considered non-numeric.







|






|







499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
** there is no consistency, we will define our own.
*/
int sqliteStrICmp(const char *zLeft, const char *zRight){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return UpperToLower[*a] - UpperToLower[*b];
}
int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
  register unsigned char *a, *b;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}

/*
** Return TRUE if z is a pure numeric string.  Return FALSE if the
** string contains any character which is not part of a number.
**
** Am empty string is considered non-numeric.

Changes to src/vacuum.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.13 2004/03/10 18:57:32 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** A structure for holding a dynamic string - a string that can grow
** without bound. 







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.13.2.5 2005/02/14 00:25:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** A structure for holding a dynamic string - a string that can grow
** without bound. 
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
      sqlite_freemem(zErrMsg);
    }
  }
  if( rc!=SQLITE_ABORT ) p->rc = rc;
  return rc;
}

/*
** This callback is used to transfer PRAGMA settings from one database
** to the other.  The value in argv[0] should be passed to a pragma
** identified by ((vacuumStruct*)pArg)->zPragma.
*/
static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){
  vacuumStruct *p = (vacuumStruct*)pArg;
  char zBuf[200];
  assert( argc==1 );
  if( argv==0 ) return 0;
  assert( argv[0]!=0 );
  assert( strlen(p->zPragma)<100 );
  assert( strlen(argv[0])<30 );
  sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]);
  p->rc = execsql(p->pzErrMsg, p->dbNew, zBuf);
  return p->rc;
}

/*
** Generate a random name of 20 character in length.
*/
static void randomName(unsigned char *zBuf){
  static const unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789";







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







159
160
161
162
163
164
165


















166
167
168
169
170
171
172
      sqlite_freemem(zErrMsg);
    }
  }
  if( rc!=SQLITE_ABORT ) p->rc = rc;
  return rc;
}



















/*
** Generate a random name of 20 character in length.
*/
static void randomName(unsigned char *zBuf){
  static const unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789";
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240



241
242
243
244
245
246
247
  char *zTemp = 0;        /* a temporary file in same directory as zFilename */
  sqlite *dbNew = 0;      /* The new vacuumed database */
  int rc = SQLITE_OK;     /* Return code from service routines */
  int i;                  /* Loop counter */
  char *zErrMsg;          /* Error message */
  vacuumStruct sVac;      /* Information passed to callbacks */

  /* These are all of the pragmas that need to be transferred over
  ** to the new database */
  static const char *zPragma[] = {
     "default_synchronous",
     "default_cache_size",
     /* "default_temp_store", */
  };

  if( db->flags & SQLITE_InTrans ){
    sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction", 
       (char*)0);
    return SQLITE_ERROR;



  }
  memset(&sVac, 0, sizeof(sVac));

  /* Get the full pathname of the database file and create two
  ** temporary filenames in the same directory as the original file.
  */
  zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);







<
<
<
<
<
<
<
<




>
>
>







204
205
206
207
208
209
210








211
212
213
214
215
216
217
218
219
220
221
222
223
224
  char *zTemp = 0;        /* a temporary file in same directory as zFilename */
  sqlite *dbNew = 0;      /* The new vacuumed database */
  int rc = SQLITE_OK;     /* Return code from service routines */
  int i;                  /* Loop counter */
  char *zErrMsg;          /* Error message */
  vacuumStruct sVac;      /* Information passed to callbacks */









  if( db->flags & SQLITE_InTrans ){
    sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction", 
       (char*)0);
    return SQLITE_ERROR;
  }
  if( db->flags & SQLITE_Interrupt ){
    return SQLITE_INTERRUPT;
  }
  memset(&sVac, 0, sizeof(sVac));

  /* Get the full pathname of the database file and create two
  ** temporary filenames in the same directory as the original file.
  */
  zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298











299
300
301
302
303
304
305
306
307
308
309
310




311
312
313
314
315
316
317
318
319
320
  if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
    goto end_of_vacuum;
  }
  
  sVac.dbOld = db;
  sVac.dbNew = dbNew;
  sVac.pzErrMsg = pzErrMsg;
  for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){
    char zBuf[200];
    assert( strlen(zPragma[i])<100 );
    sprintf(zBuf, "PRAGMA %s;", zPragma[i]);
    sVac.zPragma = zPragma[i];
    rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite_exec(db, 
      "SELECT type, name, sql FROM sqlite_master "
      "WHERE sql NOT NULL AND type!='view' "
      "UNION ALL "
      "SELECT type, name, sql FROM sqlite_master "
      "WHERE sql NOT NULL AND type=='view'",
      vacuumCallback1, &sVac, &zErrMsg);
  }











  if( rc==SQLITE_OK ){
    rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
    sqlite_exec(db, "COMMIT", 0, 0, 0);
    sqliteResetInternalSchema(db, 0);
  }

end_of_vacuum:
  if( rc && zErrMsg!=0 ){
    sqliteSetString(pzErrMsg, "unable to vacuum database - ", 
       zErrMsg, (char*)0);
  }
  sqlite_exec(db, "ROLLBACK", 0, 0, 0);




  if( dbNew ) sqlite_close(dbNew);
  sqliteOsDelete(zTemp);
  sqliteFree(zTemp);
  sqliteFree(sVac.s1.z);
  sqliteFree(sVac.s2.z);
  if( zErrMsg ) sqlite_freemem(zErrMsg);
  if( rc==SQLITE_ABORT ) sVac.rc = SQLITE_ERROR;
  return sVac.rc;
#endif
}







<
<
<
<
<
<
<









>
>
>
>
>
>
>
>
>
>
>












>
>
>
>






|



253
254
255
256
257
258
259







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
    goto end_of_vacuum;
  }
  
  sVac.dbOld = db;
  sVac.dbNew = dbNew;
  sVac.pzErrMsg = pzErrMsg;







  if( rc==SQLITE_OK ){
    rc = sqlite_exec(db, 
      "SELECT type, name, sql FROM sqlite_master "
      "WHERE sql NOT NULL AND type!='view' "
      "UNION ALL "
      "SELECT type, name, sql FROM sqlite_master "
      "WHERE sql NOT NULL AND type=='view'",
      vacuumCallback1, &sVac, &zErrMsg);
  }
  if( rc==SQLITE_OK ){
    int meta1[SQLITE_N_BTREE_META];
    int meta2[SQLITE_N_BTREE_META];
    sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
    sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
    meta2[1] = meta1[1]+1;
    meta2[3] = meta1[3];
    meta2[4] = meta1[4];
    meta2[6] = meta1[6];
    rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
  }
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
    sqlite_exec(db, "COMMIT", 0, 0, 0);
    sqliteResetInternalSchema(db, 0);
  }

end_of_vacuum:
  if( rc && zErrMsg!=0 ){
    sqliteSetString(pzErrMsg, "unable to vacuum database - ", 
       zErrMsg, (char*)0);
  }
  sqlite_exec(db, "ROLLBACK", 0, 0, 0);
  if( (dbNew && (dbNew->flags & SQLITE_Interrupt)) 
         || (db->flags & SQLITE_Interrupt) ){
    rc = SQLITE_INTERRUPT;
  }
  if( dbNew ) sqlite_close(dbNew);
  sqliteOsDelete(zTemp);
  sqliteFree(zTemp);
  sqliteFree(sVac.s1.z);
  sqliteFree(sVac.s2.z);
  if( zErrMsg ) sqlite_freemem(zErrMsg);
  if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
  return sVac.rc;
#endif
}

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.268 2004/03/03 01:51:25 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
** procedures use this information to make sure that indices are
** working correctly.  This variable has no function other than to
** help verify the correct operation of the library.
*/
int sqlite_search_count = 0;

/*
** When this global variable is positive, it gets decremented once before
** each instruction in the VDBE.  When reaches zero, the SQLITE_Interrupt
** of the db.flags field is set in order to simulate and interrupt.
**
** This facility is used for testing purposes only.  It does not function
** in an ordinary build.
*/
int sqlite_interrupt_count = 0;

/*







|


















|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.268.2.5 2006/10/24 11:26:44 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
** procedures use this information to make sure that indices are
** working correctly.  This variable has no function other than to
** help verify the correct operation of the library.
*/
int sqlite_search_count = 0;

/*
** When this global variable is positive, it gets decremented once before
** each instruction in the VDBE.  When reaches zero, the SQLITE_Interrupt
** of the db.flags field is set in order to simulate an interrupt.
**
** This facility is used for testing purposes only.  It does not function
** in an ordinary build.
*/
int sqlite_interrupt_count = 0;

/*
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
      assert( pNos->flags & MEM_Int );
      nKey = sizeof(int);
      iKey = intToKey(pNos->i);
      zKey = (char*)&iKey;
      if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
      if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
      if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
      if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
        pC->nextRowidValid = 0;
      }
    }
    if( pTos->flags & MEM_Null ){
      pTos->z = 0;
      pTos->n = 0;
    }else{
      assert( pTos->flags & MEM_Str );
    }







<
|
<







2933
2934
2935
2936
2937
2938
2939

2940

2941
2942
2943
2944
2945
2946
2947
      assert( pNos->flags & MEM_Int );
      nKey = sizeof(int);
      iKey = intToKey(pNos->i);
      zKey = (char*)&iKey;
      if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
      if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
      if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;

      pC->nextRowidValid = 0;

    }
    if( pTos->flags & MEM_Null ){
      pTos->z = 0;
      pTos->n = 0;
    }else{
      assert( pTos->flags & MEM_Str );
    }
4541
4542
4543
4544
4545
4546
4547




4548
4549
4550
4551
4552
4553
4554
  pTos++;
  pMem = &pFocus->aMem[i];
  *pTos = *pMem;
  if( pTos->flags & MEM_Str ){
    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTos->flags |= MEM_Ephem;
  }




  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,







>
>
>
>







4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
  pTos++;
  pMem = &pFocus->aMem[i];
  *pTos = *pMem;
  if( pTos->flags & MEM_Str ){
    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTos->flags |= MEM_Ephem;
  }
  if( pTos->flags & MEM_AggCtx ){
    Release(pTos);
    pTos->flags = MEM_Null;
  }
  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,
4691
4692
4693
4694
4695
4696
4697
4698
4699

4700
4701
4702
4703
4704
4705
4706
  if( pOp->opcode==OP_SetFirst ){
    pSet->prev = sqliteHashFirst(&pSet->hash);
    if( pSet->prev==0 ){
      pc = pOp->p2 - 1;
      break;
    }
  }else{
    assert( pSet->prev );
    pSet->prev = sqliteHashNext(pSet->prev);

    if( pSet->prev==0 ){
      break;
    }else{
      pc = pOp->p2 - 1;
    }
  }
  pTos++;







|
|
>







4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
  if( pOp->opcode==OP_SetFirst ){
    pSet->prev = sqliteHashFirst(&pSet->hash);
    if( pSet->prev==0 ){
      pc = pOp->p2 - 1;
      break;
    }
  }else{
    if( pSet->prev ){
      pSet->prev = sqliteHashNext(pSet->prev);
    }
    if( pSet->prev==0 ){
      break;
    }else{
      pc = pOp->p2 - 1;
    }
  }
  pTos++;
4718
4719
4720
4721
4722
4723
4724






























4725
4726
4727
4728
4729
4730
4731
*/
case OP_Vacuum: {
  if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
  rc = sqliteRunVacuum(&p->zErrMsg, db);
  if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
  break;
}































/* An other opcode is illegal...
*/
default: {
  sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
  sqliteSetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
  rc = SQLITE_INTERNAL;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
*/
case OP_Vacuum: {
  if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
  rc = sqliteRunVacuum(&p->zErrMsg, db);
  if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
  break;
}

/* Opcode: StackDepth * * *
**
** Push an integer onto the stack which is the depth of the stack prior
** to that integer being pushed.
*/
case OP_StackDepth: {
  int depth = (&pTos[1]) - p->aStack;
  pTos++;
  pTos->i = depth;
  pTos->flags = MEM_Int;
  break;
}

/* Opcode: StackReset * * *
**
** Pop a single integer off of the stack.  Then pop the stack
** as many times as necessary to get the depth of the stack down
** to the value of the integer that was popped.
*/
case OP_StackReset: {
  int depth, goal;
  assert( pTos>=p->aStack );
  Integerify(pTos);
  goal = pTos->i;
  depth = (&pTos[1]) - p->aStack;
  assert( goal<depth );
  popStack(&pTos, depth-goal);
  break;
}

/* An other opcode is illegal...
*/
default: {
  sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
  sqliteSetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
  rc = SQLITE_INTERNAL;
4831
4832
4833
4834
4835
4836
4837

4838
4839
4840
4841
4842
4843
4844
    }
#endif
  }  /* The end of the for(;;) loop the loops through opcodes */

  /* If we reach this point, it means that execution is finished.
  */
vdbe_halt:

  if( rc ){
    p->rc = rc;
    rc = SQLITE_ERROR;
  }else{
    rc = SQLITE_DONE;
  }
  p->magic = VDBE_MAGIC_HALT;







>







4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
    }
#endif
  }  /* The end of the for(;;) loop the loops through opcodes */

  /* If we reach this point, it means that execution is finished.
  */
vdbe_halt:
  CHECK_FOR_INTERRUPT
  if( rc ){
    p->rc = rc;
    rc = SQLITE_ERROR;
  }else{
    rc = SQLITE_DONE;
  }
  p->magic = VDBE_MAGIC_HALT;

Changes to src/vdbeaux.c.

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
/*
** Print a single opcode.  This routine is used for debugging only.
*/
void sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp){
  char *zP3;
  char zPtr[40];
  if( pOp->p3type==P3_POINTER ){
    sprintf(zPtr, "ptr(%#x)", (int)pOp->p3);
    zP3 = zPtr;
  }else{
    zP3 = pOp->p3;
  }
  if( pOut==0 ) pOut = stdout;
  fprintf(pOut,"%4d %-12s %4d %4d %s\n",
      pc, sqliteOpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");







|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
/*
** Print a single opcode.  This routine is used for debugging only.
*/
void sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp){
  char *zP3;
  char zPtr[40];
  if( pOp->p3type==P3_POINTER ){
    sprintf(zPtr, "ptr(%#lx)", (long)pOp->p3);
    zP3 = zPtr;
  }else{
    zP3 = pOp->p3;
  }
  if( pOut==0 ) pOut = stdout;
  fprintf(pOut,"%4d %-12s %4d %4d %s\n",
      pc, sqliteOpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    rc = SQLITE_ERROR;
    sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
  }else{
    sprintf(p->zArgv[0],"%d",i);
    sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
    sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
    if( p->aOp[i].p3type==P3_POINTER ){
      sprintf(p->aStack[4].zShort, "ptr(%#x)", (int)p->aOp[i].p3);
      p->zArgv[4] = p->aStack[4].zShort;
    }else{
      p->zArgv[4] = p->aOp[i].p3;
    }
    p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
    p->pc = i+1;
    p->azResColumn = p->zArgv;







|







561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    rc = SQLITE_ERROR;
    sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
  }else{
    sprintf(p->zArgv[0],"%d",i);
    sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
    sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
    if( p->aOp[i].p3type==P3_POINTER ){
      sprintf(p->aStack[4].zShort, "ptr(%#lx)", (long)p->aOp[i].p3);
      p->zArgv[4] = p->aStack[4].zShort;
    }else{
      p->zArgv[4] = p->aOp[i].p3;
    }
    p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
    p->pc = i+1;
    p->azResColumn = p->zArgv;

Changes to src/where.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.89 2004/02/22 20:05:02 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.89.2.2 2004/07/19 19:30:50 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
** are being used, so we assign a single bit in a 32-bit word to track
** that cursor.  Then a 32-bit integer is able to show the set of all
** cursors being used.
*/
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
  int n;          /* Number of assigned cursor values */
  int ix[32];     /* Cursor assigned to each bit */
};

/*
** Determine the number of elements in an array.
*/
#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))








|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
** are being used, so we assign a single bit in a 32-bit word to track
** that cursor.  Then a 32-bit integer is able to show the set of all
** cursors being used.
*/
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
  int n;          /* Number of assigned cursor values */
  int ix[31];     /* Cursor assigned to each bit */
};

/*
** Determine the number of elements in an array.
*/
#define ARRAYSIZE(X)  (sizeof(X)/sizeof(X[0]))

119
120
121
122
123
124
125
126


127
128
129
130
131
132
133
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table.
*/
static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
  unsigned int mask = 0;
  if( p==0 ) return 0;
  if( p->op==TK_COLUMN ){
    return getMask(pMaskSet, p->iTable);


  }
  if( p->pRight ){
    mask = exprTableUsage(pMaskSet, p->pRight);
  }
  if( p->pLeft ){
    mask |= exprTableUsage(pMaskSet, p->pLeft);
  }







|
>
>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table.
*/
static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
  unsigned int mask = 0;
  if( p==0 ) return 0;
  if( p->op==TK_COLUMN ){
    mask = getMask(pMaskSet, p->iTable);
    if( mask==0 ) mask = -1;
    return mask;
  }
  if( p->pRight ){
    mask = exprTableUsage(pMaskSet, p->pRight);
  }
  if( p->pLeft ){
    mask |= exprTableUsage(pMaskSet, p->pLeft);
  }
264
265
266
267
268
269
270





























271
272
273
274
275
276
277
    }
  }
  if( pMatch && pbRev ){
    *pbRev = sortOrder==SQLITE_SO_DESC;
  }
  return pMatch;
}






























/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an (opaque) structure that contains
** information needed to terminate the loop.  Later, the calling routine
** should invoke sqliteWhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    }
  }
  if( pMatch && pbRev ){
    *pbRev = sortOrder==SQLITE_SO_DESC;
  }
  return pMatch;
}

/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
**
** Consider the term t2.z='ok' in the following queries:
**
**   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
**
** The t2.z='ok' is disabled in the in (2) because it did not originate
** in the ON clause.  The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
**
** Disabling a term causes that term to not be tested in the inner loop
** of the join.  Disabling is an optimization.  We would get the correct
** results if nothing were ever disabled, but joins might run a little
** slower.  The trick is to disable as much as we can without disabling
** too much.  If we disabled in (1), we'd get the wrong answer.
** See ticket #813.
*/
static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
  Expr *pExpr = *ppExpr;
  if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
    *ppExpr = 0;
  }
}

/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an (opaque) structure that contains
** information needed to terminate the loop.  Later, the calling routine
** should invoke sqliteWhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
          pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
          pLevel->inOp = OP_Next;
          pLevel->inP1 = pX->iTable;
        }
      }else{
        sqliteExprCode(pParse, aExpr[k].p->pLeft);
      }
      aExpr[k].p = 0;
      cont = pLevel->cont = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
      haveKey = 0;
      sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
      /* Case 2:  There is an index and all terms of the WHERE clause that







|







763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
          pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
          pLevel->inOp = OP_Next;
          pLevel->inP1 = pX->iTable;
        }
      }else{
        sqliteExprCode(pParse, aExpr[k].p->pLeft);
      }
      disableTerm(pLevel, &aExpr[k].p);
      cont = pLevel->cont = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
      haveKey = 0;
      sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
      /* Case 2:  There is an index and all terms of the WHERE clause that
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
          if( pX==0 ) continue;
          if( aExpr[k].idxLeft==iCur
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pX->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            if( pX->op==TK_EQ ){
              sqliteExprCode(pParse, pX->pRight);
              aExpr[k].p = 0;
              break;
            }
            if( pX->op==TK_IN && nColumn==1 ){
              if( pX->pList ){
                sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
                pLevel->inOp = OP_SetNext;
                pLevel->inP1 = pX->iTable;
                pLevel->inP2 = sqliteVdbeCurrentAddr(v);
              }else{
                assert( pX->pSelect );
                sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
                sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
                pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
                pLevel->inOp = OP_Next;
                pLevel->inP1 = pX->iTable;
              }
              aExpr[k].p = 0;
              break;
            }
          }
          if( aExpr[k].idxRight==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pLeft);
            aExpr[k].p = 0;
            break;
          }
        }
      }
      pLevel->iMem = pParse->nMem++;
      cont = pLevel->cont = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);







|
















|









|







787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
          if( pX==0 ) continue;
          if( aExpr[k].idxLeft==iCur
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pX->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            if( pX->op==TK_EQ ){
              sqliteExprCode(pParse, pX->pRight);
              disableTerm(pLevel, &aExpr[k].p);
              break;
            }
            if( pX->op==TK_IN && nColumn==1 ){
              if( pX->pList ){
                sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
                pLevel->inOp = OP_SetNext;
                pLevel->inP1 = pX->iTable;
                pLevel->inP2 = sqliteVdbeCurrentAddr(v);
              }else{
                assert( pX->pSelect );
                sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
                sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
                pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
                pLevel->inOp = OP_Next;
                pLevel->inP1 = pX->iTable;
              }
              disableTerm(pLevel, &aExpr[k].p);
              break;
            }
          }
          if( aExpr[k].idxRight==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pLeft);
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
        }
      }
      pLevel->iMem = pParse->nMem++;
      cont = pLevel->cont = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqliteVdbeAddOp(v, OP_ForceInt,
          aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
        sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
        aExpr[k].p = 0;
      }else{
        sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        k = iDirectLt[i];
        assert( k<nExpr );
        assert( aExpr[k].p!=0 );







|







881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
          sqliteExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqliteExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqliteVdbeAddOp(v, OP_ForceInt,
          aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
        sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
        disableTerm(pLevel, &aExpr[k].p);
      }else{
        sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        k = iDirectLt[i];
        assert( k<nExpr );
        assert( aExpr[k].p!=0 );
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
        pLevel->iMem = pParse->nMem++;
        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          testOp = OP_Ge;
        }else{
          testOp = OP_Gt;
        }
        aExpr[k].p = 0;
      }
      start = sqliteVdbeCurrentAddr(v);
      pLevel->op = OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqliteVdbeAddOp(v, OP_Recno, iCur, 0);







|







903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
        pLevel->iMem = pParse->nMem++;
        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
          testOp = OP_Ge;
        }else{
          testOp = OP_Gt;
        }
        disableTerm(pLevel, &aExpr[k].p);
      }
      start = sqliteVdbeCurrentAddr(v);
      pLevel->op = OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
          if( aExpr[k].p==0 ) continue;
          if( aExpr[k].idxLeft==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pRight);
            aExpr[k].p = 0;
            break;
          }
          if( aExpr[k].idxRight==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pLeft);
            aExpr[k].p = 0;
            break;
          }
        }
      }

      /* Duplicate the equality term values because they will all be
      ** used twice: once to make the termination key and once to make the







|








|







958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
          if( aExpr[k].p==0 ) continue;
          if( aExpr[k].idxLeft==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pRight);
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
          if( aExpr[k].idxRight==iCur
             && aExpr[k].p->op==TK_EQ
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, aExpr[k].p->pLeft);
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
        }
      }

      /* Duplicate the equality term values because they will all be
      ** used twice: once to make the termination key and once to make the
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
          if( aExpr[k].idxLeft==iCur
             && (pExpr->op==TK_LT || pExpr->op==TK_LE)
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pRight);
            leFlag = pExpr->op==TK_LE;
            aExpr[k].p = 0;
            break;
          }
          if( aExpr[k].idxRight==iCur
             && (pExpr->op==TK_GT || pExpr->op==TK_GE)
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && pExpr->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pLeft);
            leFlag = pExpr->op==TK_GE;
            aExpr[k].p = 0;
            break;
          }
        }
        testOp = OP_IdxGE;
      }else{
        testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
        leFlag = 1;







|









|







1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
          if( aExpr[k].idxLeft==iCur
             && (pExpr->op==TK_LT || pExpr->op==TK_LE)
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pRight);
            leFlag = pExpr->op==TK_LE;
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
          if( aExpr[k].idxRight==iCur
             && (pExpr->op==TK_GT || pExpr->op==TK_GE)
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && pExpr->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pLeft);
            leFlag = pExpr->op==TK_GE;
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
        }
        testOp = OP_IdxGE;
      }else{
        testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
        leFlag = 1;
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
          if( aExpr[k].idxLeft==iCur
             && (pExpr->op==TK_GT || pExpr->op==TK_GE)
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pRight);
            geFlag = pExpr->op==TK_GE;
            aExpr[k].p = 0;
            break;
          }
          if( aExpr[k].idxRight==iCur
             && (pExpr->op==TK_LT || pExpr->op==TK_LE)
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && pExpr->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pLeft);
            geFlag = pExpr->op==TK_LE;
            aExpr[k].p = 0;
            break;
          }
        }
      }else{
        geFlag = 1;
      }
      if( nEqColumn>0 || (score&2)!=0 ){







|









|







1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
          if( aExpr[k].idxLeft==iCur
             && (pExpr->op==TK_GT || pExpr->op==TK_GE)
             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight 
             && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pRight);
            geFlag = pExpr->op==TK_GE;
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
          if( aExpr[k].idxRight==iCur
             && (pExpr->op==TK_LT || pExpr->op==TK_LE)
             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
             && pExpr->pRight->iColumn==pIdx->aiColumn[j]
          ){
            sqliteExprCode(pParse, pExpr->pLeft);
            geFlag = pExpr->op==TK_LE;
            disableTerm(pLevel, &aExpr[k].p);
            break;
          }
        }
      }else{
        geFlag = 1;
      }
      if( nEqColumn>0 || (score&2)!=0 ){

Changes to test/auth.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: auth.test,v 1.12 2003/12/07 00:24:35 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
# defined during compilation.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: auth.test,v 1.12.2.1 2004/09/09 13:54:31 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
# defined during compilation.
32
33
34
35
36
37
38






39
40
41
42
43
44
45
  }
  db authorizer ::auth
  catchsql {CREATE TABLE t1(a,b,c)}
} {1 {not authorized}}
do_test auth-1.1.2 {
  db errorcode
} {23}






do_test auth-1.2 {
  execsql {SELECT name FROM sqlite_master}
} {}
do_test auth-1.3.1 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE_CREATE_TABLE"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]







>
>
>
>
>
>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  }
  db authorizer ::auth
  catchsql {CREATE TABLE t1(a,b,c)}
} {1 {not authorized}}
do_test auth-1.1.2 {
  db errorcode
} {23}
do_test auth-1.1.3 {
  # Ticket #896.
  catchsql {
    SELECT x;
  }
} {1 {no such column: x}}
do_test auth-1.2 {
  execsql {SELECT name FROM sqlite_master}
} {}
do_test auth-1.3.1 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE_CREATE_TABLE"} {
      set ::authargs [list $arg1 $arg2 $arg3 $arg4]

Changes to test/date.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 October 31
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.7 2004/02/29 01:08:18 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 October 31
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.7.2.1 2004/07/18 22:25:16 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"
91
92
93
94
95
96
97
98













99
100
101
102
103
104
105
datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
datetest 3.8 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
datetest 3.9 {strftime('%S','2003-10-31 12:34:56.432')} 56
datetest 3.10 {strftime('%w','2003-10-31 12:34:56.432')} 5
datetest 3.11 {strftime('%W','2003-10-31 12:34:56.432')} 44













datetest 3.12 {strftime('%Y','2003-10-31 12:34:56.432')} 2003
datetest 3.13 {strftime('%%','2003-10-31 12:34:56.432')} %
datetest 3.14 {strftime('%_','2003-10-31 12:34:56.432')} NULL
datetest 3.15 {strftime('%Y-%m-%d','2003-10-31')} 2003-10-31
proc repeat {n txt} {
  set x {} 
  while {$n>0} {







|
>
>
>
>
>
>
>
>
>
>
>
>
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
datetest 3.4 {strftime('%j','2003-10-31 12:34:56.432')} 304
datetest 3.5 {strftime('%J','2003-10-31 12:34:56.432')} 2452944.024264259
datetest 3.6 {strftime('%m','2003-10-31 12:34:56.432')} 10
datetest 3.7 {strftime('%M','2003-10-31 12:34:56.432')} 34
datetest 3.8 {strftime('%s','2003-10-31 12:34:56.432')} 1067603696
datetest 3.9 {strftime('%S','2003-10-31 12:34:56.432')} 56
datetest 3.10 {strftime('%w','2003-10-31 12:34:56.432')} 5
datetest 3.11.1 {strftime('%W','2003-10-31 12:34:56.432')} 43
datetest 3.11.2 {strftime('%W','2004-01-01')} 00
datetest 3.11.3 {strftime('%W','2004-01-02')} 00
datetest 3.11.4 {strftime('%W','2004-01-03')} 00
datetest 3.11.5 {strftime('%W','2004-01-04')} 00
datetest 3.11.6 {strftime('%W','2004-01-05')} 01
datetest 3.11.7 {strftime('%W','2004-01-06')} 01
datetest 3.11.8 {strftime('%W','2004-01-07')} 01
datetest 3.11.9 {strftime('%W','2004-01-08')} 01
datetest 3.11.10 {strftime('%W','2004-01-09')} 01
datetest 3.11.11 {strftime('%W','2004-07-18')} 28
datetest 3.11.12 {strftime('%W','2004-12-31')} 52
datetest 3.11.13 {strftime('%W','2007-12-31')} 53
datetest 3.11.14 {strftime('%W','2007-01-01')} 01
datetest 3.12 {strftime('%Y','2003-10-31 12:34:56.432')} 2003
datetest 3.13 {strftime('%%','2003-10-31 12:34:56.432')} %
datetest 3.14 {strftime('%_','2003-10-31 12:34:56.432')} NULL
datetest 3.15 {strftime('%Y-%m-%d','2003-10-31')} 2003-10-31
proc repeat {n txt} {
  set x {} 
  while {$n>0} {

Changes to test/func.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.16 2002/11/04 19:32:26 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.16.2.2 2004/07/18 21:14:05 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
260
261
262
263
264
265
266





267
268
269
270
271
272
273
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
do_test func-8.3 {
  execsql {
    CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
    SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
  }
} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}






# How do you test the random() function in a meaningful, deterministic way?
#
do_test func-9.1 {
  execsql {
    SELECT random() is not null;
  }







>
>
>
>
>







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
do_test func-8.3 {
  execsql {
    CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
    SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
  }
} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
do_test func-8.4 {
  execsql {
    SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
  }
} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}

# How do you test the random() function in a meaningful, deterministic way?
#
do_test func-9.1 {
  execsql {
    SELECT random() is not null;
  }

Changes to test/index.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE INDEX statement.
#
# $Id: index.test,v 1.24 2003/09/27 00:41:28 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a basic index and verify it is added to sqlite_master
#
do_test index-1.1 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE INDEX statement.
#
# $Id: index.test,v 1.24.2.1 2004/07/20 00:50:30 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a basic index and verify it is added to sqlite_master
#
do_test index-1.1 {
510
511
512
513
514
515
516
517















518
    INSERT INTO t1 VALUES('+',9);
    INSERT INTO t1 VALUES('+12347.E+02',10);
    INSERT INTO t1 VALUES('+12347E+02',11);
    SELECT b FROM t1 ORDER BY a;
  }
} {8 5 2 1 3 6 11 9 10 4 7}
integrity_check index-15.1
















finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
    INSERT INTO t1 VALUES('+',9);
    INSERT INTO t1 VALUES('+12347.E+02',10);
    INSERT INTO t1 VALUES('+12347E+02',11);
    SELECT b FROM t1 ORDER BY a;
  }
} {8 5 2 1 3 6 11 9 10 4 7}
integrity_check index-15.1

# Drop index with a quoted name.  Ticket #695.
#
do_test index-16.1 {
  execsql {
    CREATE INDEX "t6i2" ON t6(c);
    DROP INDEX "t6i2";
  }
} {}
do_test index-16.2 {
  execsql {
    DROP INDEX "t6i1";
  }
} {}
   

finish_test

Changes to test/interrupt.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2004 Feb 8
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is the sqlite_interrupt() API.
#
# $Id: interrupt.test,v 1.4 2004/02/18 16:57:23 drh Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Compute a checksum on the entire database.
#













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2004 Feb 8
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is the sqlite_interrupt() API.
#
# $Id: interrupt.test,v 1.4.2.1 2004/05/10 20:27:42 drh Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Compute a checksum on the entire database.
#
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}

# This routine attempts to execute the sql in $sql.  It triggers an
# interrupt a progressively later and later points during the processing
# and checks to make sure SQLITE_INTERRUPT is returned.  Eventually,
# the routine completes successfully.
#
proc interrupt_test {testid sql result {initcnt 0}} {
  set orig_sum [cksum]
  set i $initcnt

  while 1 {
    incr i
    set ::sqlite_interrupt_count $i
    do_test $testid.$i.1 [format {
      set ::r [catchsql %s]
      set ::code [db errorcode]
      expr {$::code==0 || $::code==9}
    } [list $sql]] 1
    if {$::code==9} {
      do_test $testid.$i.2 {
        cksum
      } $orig_sum
    } else {
      do_test $testid.$i.99 {
        set ::r
      } [list 0 $result]
      break
    }
  }
  set ::sqlite_interrupt_count 0
}

do_test interrupt-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    SELECT name FROM sqlite_master;
  }
} {t1}
interrupt_test interrupt-1.2 {DROP TABLE t1} {}
do_test interrupt-1.3 {
  execsql {
    SELECT name FROM sqlite_master;
  }
} {}
integrity_check interrupt-1.4








|


>
|

|









|






|








|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
}

# This routine attempts to execute the sql in $sql.  It triggers an
# interrupt a progressively later and later points during the processing
# and checks to make sure SQLITE_INTERRUPT is returned.  Eventually,
# the routine completes successfully.
#
proc interrupt_test {testid sql result {initcnt 0} {maxcnt 1000000}} {
  set orig_sum [cksum]
  set i $initcnt
  global sqlite_interrupt_count
  while {$i<$maxcnt} {
    incr i
    set sqlite_interrupt_count $i
    do_test $testid.$i.1 [format {
      set ::r [catchsql %s]
      set ::code [db errorcode]
      expr {$::code==0 || $::code==9}
    } [list $sql]] 1
    if {$::code==9} {
      do_test $testid.$i.2 {
        cksum
      } $orig_sum
    } elseif {$sqlite_interrupt_count>0} {
      do_test $testid.$i.99 {
        set ::r
      } [list 0 $result]
      break
    }
  }
  set sqlite_interrupt_count 0
}

do_test interrupt-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    SELECT name FROM sqlite_master;
  }
} {t1}
interrupt_test interrupt-1.2 {DROP TABLE t1} {} 1 14
do_test interrupt-1.3 {
  execsql {
    SELECT name FROM sqlite_master;
  }
} {}
integrity_check interrupt-1.4

157
158
159
160
161
162
163
164

165
set max_count [expr {1000000-$sqlite_interrupt_count}]
for {set i 1} {$i<$max_count-5} {incr i 1} {
  do_test interrupt-4.$i.1 {
    set ::sqlite_interrupt_count $::i
    catchsql $sql
  } {1 interrupted}
}


finish_test








>

158
159
160
161
162
163
164
165
166
167
set max_count [expr {1000000-$sqlite_interrupt_count}]
for {set i 1} {$i<$max_count-5} {incr i 1} {
  do_test interrupt-4.$i.1 {
    set ::sqlite_interrupt_count $::i
    catchsql $sql
  } {1 interrupted}
}


finish_test

Added test/join3_28.test.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for joins, including outer joins, where
# there are a large number of tables involved in the join.
#
# $Id: join3_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

catch {unset result}
set result {}
for {set N 1} {$N<=40} {incr N} {
  lappend result $N
  do_test join3-1.$N {
    execsql "CREATE TABLE t${N}(x);"
    execsql "INSERT INTO t$N VALUES($N)"
    set sql "SELECT * FROM t1"
    for {set i 2} {$i<=$N} {incr i} {append sql ", t$i"}
    execsql $sql
  } $result
}

finish_test

Added test/join4_28.test.



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 2002 May 24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for left outer joins containing WHERE
# clauses that restrict the scope of the left term of the join.
#
# $Id: join4_28.test,v 1.1.2.1 2004/07/22 16:08:39 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test join4-1.1 {
  execsql {
    create temp table t1(a integer, b varchar(10));
    insert into t1 values(1,'one');
    insert into t1 values(2,'two');
    insert into t1 values(3,'three');
    insert into t1 values(4,'four');

    create temp table t2(x integer, y varchar(10), z varchar(10));
    insert into t2 values(2,'niban','ok');
    insert into t2 values(4,'yonban','err');
  }
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.2 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.3 {
  execsql {
    create index i2 on t2(z);
  }
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.4 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.5 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z>='ok'
  }
} {2 two 2 niban ok}
do_test join4-1.4 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z>='ok'
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
do_test join4-1.6 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x where t2.z IN ('ok')
  }
} {2 two 2 niban ok}
do_test join4-1.7 {
  execsql {
    select * from t1 left outer join t2 on t1.a=t2.x and t2.z IN ('ok')
  }
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}


finish_test

Changes to test/limit.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.11 2004/03/08 13:26:18 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
set fd [open data1.txt w]







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.11.2.1 2004/07/19 23:33:04 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
set fd [open data1.txt w]
289
290
291
292
293
294
295
296




















297
} {31}
do_test limit-7.12 {
  execsql {
    SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 
       ORDER BY 1 DESC LIMIT 1 OFFSET 1;
  }
} {30}





















finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
} {31}
do_test limit-7.12 {
  execsql {
    SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 
       ORDER BY 1 DESC LIMIT 1 OFFSET 1;
  }
} {30}

# Tests for limit in conjunction with distinct.  The distinct should
# occur before both the limit and the offset.  Ticket #749.
#
do_test limit-8.1 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5;
  }
} {0 1 2 3 4}
do_test limit-8.2 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 5;
  }
} {5 6 7 8 9}
do_test limit-8.3 {
  execsql {
    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 25;
  }
} {25 26 27 28 29}


finish_test

Changes to test/minmax.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing SELECT statements that contain
# aggregate min() and max() functions and which are handled as
# as a special case.
#
# $Id: minmax.test,v 1.9 2004/03/13 14:00:37 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test minmax-1.0 {
  execsql {
    BEGIN;







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing SELECT statements that contain
# aggregate min() and max() functions and which are handled as
# as a special case.
#
# $Id: minmax.test,v 1.9.2.2 2004/07/18 21:14:05 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test minmax-1.0 {
  execsql {
    BEGIN;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
do_test minmax-1.5 {
  execsql {CREATE INDEX t1i1 ON t1(x)}
  set sqlite_search_count 0
  execsql {SELECT min(x) FROM t1}
} {1}
do_test minmax-1.6 {
  set sqlite_search_count
} {1}
do_test minmax-1.7 {
  set sqlite_search_count 0
  execsql {SELECT max(x) FROM t1}
} {20}
do_test minmax-1.8 {
  set sqlite_search_count
} {1}







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
do_test minmax-1.5 {
  execsql {CREATE INDEX t1i1 ON t1(x)}
  set sqlite_search_count 0
  execsql {SELECT min(x) FROM t1}
} {1}
do_test minmax-1.6 {
  set sqlite_search_count
} {2}
do_test minmax-1.7 {
  set sqlite_search_count 0
  execsql {SELECT max(x) FROM t1}
} {20}
do_test minmax-1.8 {
  set sqlite_search_count
} {1}
271
272
273
274
275
276
277
278
















































































279
do_test minmax-9.2 {
  execsql {
    SELECT max(rowid) FROM (
      SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
    )
  }
} {{}}

















































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
do_test minmax-9.2 {
  execsql {
    SELECT max(rowid) FROM (
      SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
    )
  }
} {{}}

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
#
do_test minmax-10.1 {
  execsql {
    CREATE TABLE t6(x);
    INSERT INTO t6 VALUES(1);
    INSERT INTO t6 VALUES(2);
    INSERT INTO t6 VALUES(NULL);
    SELECT coalesce(min(x),-1) FROM t6;
  }
} {1}
do_test minmax-10.2 {
  execsql {
    SELECT max(x) FROM t6;
  }
} {2}
do_test minmax-10.3 {
  execsql {
    CREATE INDEX i6 ON t6(x);
    SELECT coalesce(min(x),-1) FROM t6;
  }
} {1}
do_test minmax-10.4 {
  execsql {
    SELECT max(x) FROM t6;
  }
} {2}
do_test minmax-10.5 {
  execsql {
    DELETE FROM t6 WHERE x NOT NULL;
    SELECT count(*) FROM t6;
  }
} 1
do_test minmax-10.6 {
  execsql {
    SELECT count(x) FROM t6;
  }
} 0
do_test minmax-10.7 {
  execsql {
    SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
  }
} {{} {}}
do_test minmax-10.8 {
  execsql {
    SELECT min(x), max(x) FROM t6;
  }
} {{} {}}
do_test minmax-10.9 {
  execsql {
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    INSERT INTO t6 SELECT * FROM t6;
    SELECT count(*) FROM t6;
  }
} 1024
do_test minmax-10.10 {
  execsql {
    SELECT count(x) FROM t6;
  }
} 0
do_test minmax-10.11 {
  execsql {
    SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
  }
} {{} {}}
do_test minmax-10.12 {
  execsql {
    SELECT min(x), max(x) FROM t6;
  }
} {{} {}}

finish_test

Changes to test/null.test.

90
91
92
93
94
95
96

97
98
99
100
101
102
103
do_test null-2.8 {
  execsql {
    select ifnull(case c when b then 1 else 0 end, 99) from t1;
  }
} {1 0 0 1 0 0 0}

# Check to see that NULL values are ignored in aggregate functions.

#
do_test null-3.1 {
  execsql {
    select count(*), count(b), count(c), sum(b), sum(c), 
           avg(b), avg(c), min(b), max(b) from t1;
  }
} {7 4 6 2 3 0.5 0.5 0 1}







>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
do_test null-2.8 {
  execsql {
    select ifnull(case c when b then 1 else 0 end, 99) from t1;
  }
} {1 0 0 1 0 0 0}

# Check to see that NULL values are ignored in aggregate functions.
# (except for min().)
#
do_test null-3.1 {
  execsql {
    select count(*), count(b), count(c), sum(b), sum(c), 
           avg(b), avg(c), min(b), max(b) from t1;
  }
} {7 4 6 2 3 0.5 0.5 0 1}

Changes to test/select1.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.30 2002/06/02 16:09:03 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.30.2.3 2004/07/20 01:45:49 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
608
609
610
611
612
613
614
615
616
617
618





619
620
621
622
623
624
625
  }
} {t3.a 1 t3.b 2 t4.a 3 t4.b 4}
do_test select1-11.3 {
  execsql2 {
    SELECT * FROM t3 AS x, t4 AS y;
  }
} {x.a 1 x.b 2 y.a 3 y.b 4}
do_test select1-11.4 {
  execsql {
    SELECT t3.*, t4.b FROM t3, t4;
  }





} {1 2 4}
do_test select1-11.5 {
  execsql2 {
    SELECT t3.*, t4.b FROM t3, t4;
  }
} {t3.a 1 t3.b 2 t4.b 4}
do_test select1-11.6 {







|



>
>
>
>
>







608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  }
} {t3.a 1 t3.b 2 t4.a 3 t4.b 4}
do_test select1-11.3 {
  execsql2 {
    SELECT * FROM t3 AS x, t4 AS y;
  }
} {x.a 1 x.b 2 y.a 3 y.b 4}
do_test select1-11.4.1 {
  execsql {
    SELECT t3.*, t4.b FROM t3, t4;
  }
} {1 2 4}
do_test select1-11.4.2 {
  execsql {
    SELECT "t3".*, t4.b FROM t3, t4;
  }
} {1 2 4}
do_test select1-11.5 {
  execsql2 {
    SELECT t3.*, t4.b FROM t3, t4;
  }
} {t3.a 1 t3.b 2 t4.b 4}
do_test select1-11.6 {

Changes to test/tclsqlite.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.20 2004/02/25 22:51:06 rdc Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
if {[sqlite -has-codec]} {







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.20.2.2 2006/10/24 11:26:44 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
if {[sqlite -has-codec]} {
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
    }
  } msg]
  regsub {:.*$} $msg {} msg
  lappend v $msg
} {1 {syntax error in expression "x*"}}

if {[sqlite -encoding]=="UTF-8" && [sqlite -tcl-uses-utf]} {

  do_test tcl-2.1 {
    execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
    execsql "PRAGMA table_info(t\u0123x)"
  } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
  do_test tcl-2.2 {
    execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
    db eval "SELECT * FROM t\u0123x" result break
    set result(*)
  } "a b\u1235"
}

if {[sqlite -encoding]=="iso8859" && [sqlite -tcl-uses-utf]} {
  do_test tcl-2.1 {
    execsql "CREATE TABLE t\251x(a int, b\306 float)"
    execsql "PRAGMA table_info(t\251x)"
  } "0 a int 0 {} 0 1 b\306 float 0 {} 0"

  do_test tcl-2.2 {
    execsql "INSERT INTO t\251x VALUES(1,2.3)"
    db eval "SELECT * FROM t\251x" result break
    set result(*)
  } "a b\306"
}








>
















>







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    }
  } msg]
  regsub {:.*$} $msg {} msg
  lappend v $msg
} {1 {syntax error in expression "x*"}}

if {[sqlite -encoding]=="UTF-8" && [sqlite -tcl-uses-utf]} {
  catch {unset ::result}
  do_test tcl-2.1 {
    execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
    execsql "PRAGMA table_info(t\u0123x)"
  } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
  do_test tcl-2.2 {
    execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
    db eval "SELECT * FROM t\u0123x" result break
    set result(*)
  } "a b\u1235"
}

if {[sqlite -encoding]=="iso8859" && [sqlite -tcl-uses-utf]} {
  do_test tcl-2.1 {
    execsql "CREATE TABLE t\251x(a int, b\306 float)"
    execsql "PRAGMA table_info(t\251x)"
  } "0 a int 0 {} 0 1 b\306 float 0 {} 0"
  unset -nocomplain result
  do_test tcl-2.2 {
    execsql "INSERT INTO t\251x VALUES(1,2.3)"
    db eval "SELECT * FROM t\251x" result break
    set result(*)
  } "a b\306"
}

Changes to test/trigger1.test.

408
409
410
411
412
413
414















































































































415
416
do_test trigger-9.2 {
  execsql {
    INSERT INTO t3 VALUES(1,3);
    SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
  }
} {1 2 1 3 99 99 1 3}

















































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
do_test trigger-9.2 {
  execsql {
    INSERT INTO t3 VALUES(1,3);
    SELECT * FROM t3 UNION ALL SELECT 99, 99 UNION ALL SELECT * FROM t4;
  }
} {1 2 1 3 99 99 1 3}

execsql {
  DROP TABLE t2;
  DROP TABLE t3;
  DROP TABLE t4;
}

# Skip the remaining tests if we have a codec.  The ATTACH command
# will not work right on these tests when there is a codec.
#
if {[sqlite -has-codec]} {
  finish_test
  return
}

# Ticket #764. At one stage TEMP triggers would fail to re-install when the
# schema was reloaded. The following tests ensure that TEMP triggers are
# correctly re-installed.
#
# Also verify that references within trigger programs are resolved at
# statement compile time, not trigger installation time. This means, for
# example, that you can drop and re-create tables referenced by triggers. 
do_test trigger-10.0 {
  file delete -force test2.db
  file delete -force test2.db-journal
  sqlite db2 test2.db
  execsql {CREATE TABLE t3(a, b, c);} db2
  db2 close
  execsql {
    ATTACH 'test2.db' AS aux;
  }
} {}
do_test trigger-10.1 {
  execsql {
    CREATE TABLE t1(a, b, c);
    CREATE temp TABLE t2(a, b, c);
    CREATE TABLE insert_log(db, a, b, c);
  }
} {}
do_test trigger-10.2 {
  execsql {
    CREATE TEMP TRIGGER trig1 AFTER INSERT ON t1 BEGIN 
      INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
    END;
    CREATE TEMP TRIGGER trig2 AFTER INSERT ON t2 BEGIN 
      INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
    END;
    CREATE TEMP TRIGGER trig3 AFTER INSERT ON t3 BEGIN 
      INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
    END;
  }
} {}
do_test trigger-10.3 {
  execsql {
    INSERT INTO t1 VALUES(1, 2, 3);
    INSERT INTO t2 VALUES(4, 5, 6);
    INSERT INTO t3  VALUES(7, 8, 9);
  }
} {}
do_test trigger-10.4 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
do_test trigger-10.5 {
  execsql {
    BEGIN;
    INSERT INTO t1 VALUES(1, 2, 3);
    INSERT INTO t2 VALUES(4, 5, 6);
    INSERT INTO t3  VALUES(7, 8, 9);
    ROLLBACK;
  }
} {}
do_test trigger-10.6 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 1 2 3 temp 4 5 6 aux 7 8 9}
do_test trigger-10.7 {
  execsql {
    DELETE FROM insert_log;
    INSERT INTO t1 VALUES(11, 12, 13);
    INSERT INTO t2 VALUES(14, 15, 16);
    INSERT INTO t3 VALUES(17, 18, 19);
  }
} {}
do_test trigger-10.8 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 11 12 13 temp 14 15 16 aux 17 18 19}
do_test trigger-10.8 {
# Drop and re-create the insert_log table in a different database. Note
# that we can change the column names because the trigger programs don't
# use them explicitly.
  execsql {
    DROP TABLE insert_log;
    CREATE temp TABLE insert_log(db, d, e, f);
  }
} {}
do_test trigger-10.10 {
  execsql {
    INSERT INTO t1 VALUES(21, 22, 23);
    INSERT INTO t2 VALUES(24, 25, 26);
    INSERT INTO t3  VALUES(27, 28, 29);
  }
} {}
do_test trigger-10.11 {
  execsql {
    SELECT * FROM insert_log;
  }
} {main 21 22 23 temp 24 25 26 aux 27 28 29}

finish_test

Changes to test/view.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2002 February 26
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing VIEW statements.
#
# $Id: view.test,v 1.16 2003/05/31 16:21:13 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test view-1.0 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2002 February 26
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing VIEW statements.
#
# $Id: view.test,v 1.16.2.1 2004/07/20 00:20:47 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test view-1.0 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
380
381
382
383
384
385
386


















387
388
389
  }
} {5 1 4 2 3 4}
do_test view-9.6 {
  execsql {
    SELECT * FROM v10 ORDER BY 1;
  }
} {3 4 4 2 5 1}




















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  }
} {5 1 4 2 3 4}
do_test view-9.6 {
  execsql {
    SELECT * FROM v10 ORDER BY 1;
  }
} {3 4 4 2 5 1}

# Tables with columns having peculiar quoted names used in views
# Ticket #756.
#
do_test view-10.1 {
  execsql {
    CREATE TABLE t3("9" integer, [4] text);
    INSERT INTO t3 VALUES(1,2);
    CREATE VIEW v_t3_a AS SELECT a.[9] FROM t3 AS a;
    CREATE VIEW v_t3_b AS SELECT "4" FROM t3;
    SELECT * FROM v_t3_a;
  }
} {1}
do_test view-10.2 {
  execsql {
    SELECT * FROM v_t3_b;
  }
} {2}


finish_test

Changes to tool/lemon.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

extern void qsort();
extern double strtod();
extern long strtol();
extern void free();
extern int access();
extern int atoi();

#ifndef __WIN32__
#   if defined(_WIN32) || defined(WIN32)
#	define __WIN32__
#   endif
#endif

/* #define PRIVATE static */







<
<
<
<
<
<
<







8
9
10
11
12
13
14







15
16
17
18
19
20
21
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>








#ifndef __WIN32__
#   if defined(_WIN32) || defined(WIN32)
#	define __WIN32__
#   endif
#endif

/* #define PRIVATE static */
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

char *msort();
extern void *malloc();

/******** From the file "action.h" *************************************/
struct action *Action_new();
struct action *Action_sort();
void Action_add();

/********* From the file "assert.h" ************************************/
void myassert();
#ifndef NDEBUG
#  define assert(X) if(!(X))myassert(__FILE__,__LINE__)
#else
#  define assert(X)







<







29
30
31
32
33
34
35

36
37
38
39
40
41
42

char *msort();
extern void *malloc();

/******** From the file "action.h" *************************************/
struct action *Action_new();
struct action *Action_sort();


/********* From the file "assert.h" ************************************/
void myassert();
#ifndef NDEBUG
#  define assert(X) if(!(X))myassert(__FILE__,__LINE__)
#else
#  define assert(X)
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  return rc;
}

/* Sort parser actions */
struct action *Action_sort(ap)
struct action *ap;
{
  ap = (struct action *)msort(ap,&ap->next,actioncmp);
  return ap;
}

void Action_add(app,type,sp,arg)
struct action **app;
enum e_action type;
struct symbol *sp;







|







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  return rc;
}

/* Sort parser actions */
struct action *Action_sort(ap)
struct action *ap;
{
  ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
  return ap;
}

void Action_add(app,type,sp,arg)
struct action **app;
enum e_action type;
struct symbol *sp;
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

    /* Get a pointer to the state described by the basis configuration set
    ** constructed in the preceding loop */
    newstp = getstate(lemp);

    /* The state "newstp" is reached from the state "stp" by a shift action
    ** on the symbol "sp" */
    Action_add(&stp->ap,SHIFT,sp,newstp);
  }
}

/*
** Construct the propagation links
*/
void FindLinks(lemp)







|







799
800
801
802
803
804
805
806
807
808
809
810
811
812
813

    /* Get a pointer to the state described by the basis configuration set
    ** constructed in the preceding loop */
    newstp = getstate(lemp);

    /* The state "newstp" is reached from the state "stp" by a shift action
    ** on the symbol "sp" */
    Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
  }
}

/*
** Construct the propagation links
*/
void FindLinks(lemp)
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
    stp = lemp->sorted[i];
    for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
      if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
        for(j=0; j<lemp->nterminal; j++){
          if( SetFind(cfp->fws,j) ){
            /* Add a reduce action to the state "stp" which will reduce by the
            ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
            Action_add(&stp->ap,REDUCE,lemp->symbols[j],cfp->rp);
          }
	}
      }
    }
  }

  /* Add the accepting token */







|







900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
    stp = lemp->sorted[i];
    for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
      if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
        for(j=0; j<lemp->nterminal; j++){
          if( SetFind(cfp->fws,j) ){
            /* Add a reduce action to the state "stp" which will reduce by the
            ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
            Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
          }
	}
      }
    }
  }

  /* Add the accepting token */
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
    }
  }
  return;
}

/* Sort the configuration list */
void Configlist_sort(){
  current = (struct config *)msort(current,&(current->next),Configcmp);
  currentend = 0;
  return;
}

/* Sort the basis configuration list */
void Configlist_sortbasis(){
  basis = (struct config *)msort(current,&(current->bp),Configcmp);
  basisend = 0;
  return;
}

/* Return a pointer to the head of the configuration list and
** reset the list */
struct config *Configlist_return(){







|






|







1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
    }
  }
  return;
}

/* Sort the configuration list */
void Configlist_sort(){
  current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
  currentend = 0;
  return;
}

/* Sort the basis configuration list */
void Configlist_sortbasis(){
  basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
  basisend = 0;
  return;
}

/* Return a pointer to the head of the configuration list and
** reset the list */
struct config *Configlist_return(){
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
    printf("                   %d states, %d parser table entries, %d conflicts\n",
      lem.nstate, lem.tablesize, lem.nconflict);
  }
  if( lem.nconflict ){
    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
  }
  exit(lem.errorcnt + lem.nconflict);

}
/******************** From the file "msort.c" *******************************/
/*
** A generic merge-sort program.
**
** USAGE:
** Let "ptr" be a pointer to some structure which is at the head of







>







1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
    printf("                   %d states, %d parser table entries, %d conflicts\n",
      lem.nstate, lem.tablesize, lem.nconflict);
  }
  if( lem.nconflict ){
    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
  }
  exit(lem.errorcnt + lem.nconflict);
  return (lem.errorcnt + lem.nconflict);
}
/******************** From the file "msort.c" *******************************/
/*
** A generic merge-sort program.
**
** USAGE:
** Let "ptr" be a pointer to some structure which is at the head of
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892


2893
2894
2895
2896
2897
2898
2899
*/
void emit_destructor_code(out,sp,lemp,lineno)
FILE *out;
struct symbol *sp;
struct lemon *lemp;
int *lineno;
{
 char *cp;

 int linecnt = 0;
 if( sp->type==TERMINAL ){
   cp = lemp->tokendest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
 }else if( sp->destructor ){
   cp = sp->destructor;
   fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
 }else if( lemp->vardest ){
   cp = lemp->vardest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);


 }
 for(; *cp; cp++){
   if( *cp=='$' && cp[1]=='$' ){
     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
     cp++;
     continue;
   }







|













>
>







2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
*/
void emit_destructor_code(out,sp,lemp,lineno)
FILE *out;
struct symbol *sp;
struct lemon *lemp;
int *lineno;
{
 char *cp = 0;

 int linecnt = 0;
 if( sp->type==TERMINAL ){
   cp = lemp->tokendest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
 }else if( sp->destructor ){
   cp = sp->destructor;
   fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
 }else if( lemp->vardest ){
   cp = lemp->vardest;
   if( cp==0 ) return;
   fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
 }else{
   assert( 0 );  /* Cannot happen */
 }
 for(; *cp; cp++){
   if( *cp=='$' && cp[1]=='$' ){
     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
     cp++;
     continue;
   }

Added tool/spaceanal.tcl.









































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# Run this TCL script using "testfixture" in order get a report that shows
# how much disk space is used by a particular data to actually store data
# versus how much space is unused.
#

# Get the name of the database to analyze
#
if {[llength $argv]!=1} {
  puts stderr "Usage: $argv0 database-name"
  exit 1
}
set file_to_analyze [lindex $argv 0]
if {![file exists $file_to_analyze]} {
  puts stderr "No such file: $file_to_analyze"
  exit 1
}
if {![file readable $file_to_analyze]} {
  puts stderr "File is not readable: $file_to_analyze"
  exit 1
}
if {[file size $file_to_analyze]<2048} {
  puts stderr "Empty or malformed database: $file_to_analyze"
  exit 1
}

# Open the database
#
sqlite db [lindex $argv 0]
set DB [btree_open [lindex $argv 0]]

# In-memory database for collecting statistics
#
sqlite mem :memory:
set tabledef\
{CREATE TABLE space_used(
   name clob,        -- Name of a table or index in the database file
   tblname clob,     -- Name of associated table
   is_index boolean, -- TRUE if it is an index, false for a table
   nentry int,       -- Number of entries in the BTree
   payload int,      -- Total amount of data stored in this table or index
   mx_payload int,   -- Maximum payload size
   n_ovfl int,       -- Number of entries that overflow
   pri_pages int,    -- Number of primary pages used
   ovfl_pages int,   -- Number of overflow pages used
   pri_unused int,   -- Number of unused bytes on primary pages
   ovfl_unused int   -- Number of unused bytes on overflow pages
);}
mem eval $tabledef

# This query will be used to find the root page number for every index and
# table in the database.
#
set sql {
  SELECT name, tbl_name, type, rootpage 
    FROM sqlite_master WHERE type IN ('table','index')
  UNION ALL
  SELECT 'sqlite_master', 'sqlite_master', 'table', 2
  ORDER BY 1
}

# Analyze every table in the database, one at a time.
#
foreach {name tblname type rootpage} [db eval $sql] {
  puts stderr "Analyzing $name..."
  set cursor [btree_cursor $DB $rootpage 0]
  set go [btree_first $cursor]
  set size 0
  catch {unset pg_used}
  set unused_ovfl 0
  set n_overflow 0
  set cnt_ovfl 0
  set n_entry 0
  set mx_size 0
  set pg_used($rootpage) 1016
  while {$go==0} {
    incr n_entry
    set payload [btree_payload_size $cursor]
    incr size $payload
    set stat [btree_cursor_dump $cursor]
    set pgno [lindex $stat 0]
    set freebytes [lindex $stat 4]
    set pg_used($pgno) $freebytes
    if {$payload>236} {
      # if {[lindex $stat 8]==0} {error "overflow is empty with $payload"}
      set n [expr {($payload-236+1019)/1020}]
      incr n_overflow $n
      incr cnt_ovfl
      incr unused_ovfl [expr {$n*1020+236-$payload}]
    } else {
      # if {[lindex $stat 8]!=0} {error "overflow not empty with $payload"}
    }
    if {$payload>$mx_size} {set mx_size $payload}
    set go [btree_next $cursor]
  }
  btree_close_cursor $cursor
  set n_primary [llength [array names pg_used]]
  set unused_primary 0
  foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
  regsub -all ' $name '' name
  set sql "INSERT INTO space_used VALUES('$name'"
  regsub -all ' $tblname '' tblname
  append sql ",'$tblname',[expr {$type=="index"}],$n_entry"
  append sql ",$size,$mx_size,$cnt_ovfl,"
  append sql "$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
  mem eval $sql
}

# Generate a single line of output in the statistics section of the
# report.
#
proc statline {title value {extra {}}} {
  set len [string length $title]
  set dots [string range {......................................} $len end]
  set len [string length $value]
  set sp2 [string range {          } $len end]
  if {$extra ne ""} {
    set extra " $extra"
  }
  puts "$title$dots $value$sp2$extra"
}

# Generate a formatted percentage value for $num/$denom
#
proc percent {num denom} {
  if {$denom==0.0} {return ""}
  set v [expr {$num*100.0/$denom}]
  if {$v>1.0 && $v<99.0} {
    return [format %4.1f%% $v]
  } elseif {$v<0.1 || $v>99.9} {
    return [format %6.3f%% $v]
  } else {
    return [format %5.2f%% $v]
  }
}

# Generate a subreport that covers some subset of the database.
# the $where clause determines which subset to analyze.
#
proc subreport {title where} {
  set hit 0
  mem eval "SELECT sum(nentry) AS nentry, \
                   sum(payload) AS payload, \
                   sum(CASE is_index WHEN 1 THEN 0 ELSE payload-4*nentry END) \
                       AS data, \
                   max(mx_payload) AS mx_payload, \
                   sum(n_ovfl) as n_ovfl, \
                   sum(pri_pages) AS pri_pages, \
                   sum(ovfl_pages) AS ovfl_pages, \
                   sum(pri_unused) AS pri_unused, \
                   sum(ovfl_unused) AS ovfl_unused \
            FROM space_used WHERE $where" {} {set hit 1}
  if {!$hit} {return 0}
  puts ""
  set len [string length $title]
  incr len 5
  set stars "***********************************"
  append stars $stars
  set stars [string range $stars $len end]
  puts "*** $title $stars"
  puts ""
  statline "Percentage of total database" \
     [percent [expr {$pri_pages+$ovfl_pages}] $::file_pgcnt]
  statline "Number of entries" $nentry
  set storage [expr {($pri_pages+$ovfl_pages)*1024}]
  statline "Bytes of storage consumed" $storage
  statline "Bytes of payload" $payload [percent $payload $storage]
  statline "Bytes of data" $data [percent $data $storage]
  set key [expr {$payload-$data}]
  statline "Bytes of key" $key [percent $key $storage]
  set avgpay [expr {$nentry>0?$payload/$nentry:0}]
  statline "Average payload per entry" $avgpay
  set avgunused [expr {$nentry>0?($pri_unused+$ovfl_unused)/$nentry:0}]
  statline "Average unused bytes per entry" $avgunused
  statline "Average fanout" \
     [format %.2f [expr {$pri_pages==0?0:($nentry+0.0)/$pri_pages}]]
  statline "Maximum payload per entry" $mx_payload
  statline "Entries that use overflow" $n_ovfl [percent $n_ovfl $nentry]
  statline "Total pages used" [set allpgs [expr {$pri_pages+$ovfl_pages}]]
  statline "Primary pages used" $pri_pages ;# [percent $pri_pages $allpgs]
  statline "Overflow pages used" $ovfl_pages ;# [percent $ovfl_pages $allpgs]
  statline "Unused bytes on primary pages" $pri_unused \
               [percent $pri_unused [expr {$pri_pages*1024}]]
  statline "Unused bytes on overflow pages" $ovfl_unused \
               [percent $ovfl_unused [expr {$ovfl_pages*1024}]]
  set allunused [expr {$ovfl_unused+$pri_unused}]
  statline "Unused bytes on all pages" $allunused \
               [percent $allunused [expr {$allpgs*1024}]]
  return 1
}

# Output summary statistics:
#
puts "/** Disk-Space Utilization Report For $file_to_analyze"
puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]"
puts ""
set fsize [file size [lindex $argv 0]]
set file_pgcnt [expr {$fsize/1024}]
set usedcnt [mem eval {SELECT sum(pri_pages+ovfl_pages) FROM space_used}]
set freecnt [expr {$file_pgcnt-$usedcnt-1}]
set freecnt2 [lindex [btree_get_meta $DB] 0]
statline {Pages in the whole file (measured)} $file_pgcnt
set file_pgcnt2 [expr {$usedcnt+$freecnt2+1}]
statline {Pages in the whole file (calculated)} $file_pgcnt2
statline {Pages that store data} $usedcnt [percent $usedcnt $file_pgcnt]
statline {Pages on the freelist (per header)}\
   $freecnt2 [percent $freecnt2 $file_pgcnt]
statline {Pages on the freelist (calculated)}\
   $freecnt [percent $freecnt $file_pgcnt]
statline {Header pages} 1 [percent 1 $file_pgcnt]

set ntable [db eval {SELECT count(*)+1 FROM sqlite_master WHERE type='table'}]
statline {Number of tables in the database} $ntable
set nindex [db eval {SELECT count(*) FROM sqlite_master WHERE type='index'}]
set autoindex [db eval {SELECT count(*) FROM sqlite_master
                        WHERE type='index' AND name LIKE '(% autoindex %)'}]
set manindex [expr {$nindex-$autoindex}]
statline {Number of indices} $nindex
statline {Number of named indices} $manindex [percent $manindex $nindex]
statline {Automatically generated indices} $autoindex \
     [percent $autoindex $nindex]

set bytes_data [mem eval "SELECT sum(payload-4*nentry) FROM space_used
                          WHERE NOT is_index AND name!='sqlite_master'"]
set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
statline "Size of the file in bytes" $fsize
statline "Bytes of payload stored" $total_payload \
    [percent $total_payload $fsize]
statline "Bytes of user data stored" $bytes_data \
    [percent $bytes_data $fsize]

# Output table rankings
#
puts ""
puts "*** Page counts for all tables with their indices ********************"
puts ""
mem eval {SELECT tblname, count(*) AS cnt, sum(pri_pages+ovfl_pages) AS size
          FROM space_used GROUP BY tblname ORDER BY size DESC, tblname} {} {
  statline [string toupper $tblname] $size [percent $size $file_pgcnt]
}

# Output subreports
#
if {$nindex>0} {
  subreport {All tables and indices} 1
}
subreport {All tables} {NOT is_index}
if {$nindex>0} {
  subreport {All indices} {is_index}
}
foreach tbl [mem eval {SELECT name FROM space_used WHERE NOT is_index
                       ORDER BY name}] {
  regsub ' $tbl '' qn
  set name [string toupper $tbl]
  set n [mem eval "SELECT count(*) FROM space_used WHERE tblname='$qn'"]
  if {$n>1} {
    subreport "Table $name and all its indices" "tblname='$qn'"
    subreport "Table $name w/o any indices" "name='$qn'"
    subreport "Indices of table $name" "tblname='$qn' AND is_index"
  } else {
    subreport "Table $name" "name='$qn'"
  }
}

# Output instructions on what the numbers above mean.
#
puts {
*** Definitions ******************************************************

Number of pages in the whole file

    The number of 1024-byte pages that go into forming the complete database

Pages that store data

    The number of pages that store data, either as primary B*Tree pages or
    as overflow pages.  The number at the right is the data pages divided by
    the total number of pages in the file.

Pages on the freelist

    The number of pages that are not currently in use but are reserved for
    future use.  The percentage at the right is the number of freelist pages
    divided by the total number of pages in the file.

Header pages

    The number of pages of header overhead in the database.  This value is
    always 1.  The percentage at the right is the number of header pages
    divided by the total number of pages in the file.

Number of tables in the database

    The number of tables in the database, including the SQLITE_MASTER table
    used to store schema information.

Number of indices

    The total number of indices in the database.

Number of named indices

    The number of indices created using an explicit CREATE INDEX statement.

Automatically generated indices

    The number of indices used to implement PRIMARY KEY or UNIQUE constraints
    on tables.

Size of the file in bytes

    The total amount of disk space used by the entire database files.

Bytes of payload stored

    The total number of bytes of payload stored in the database.  Payload
    includes both key and data.  The content of the SQLITE_MASTER table is
    counted when computing this number.  The percentage at the right shows
    the payload divided by the total file size.

Bytes of user data stored

    The total number of bytes of data stored in the database, not counting
    the database schema information stored in the SQLITE_MASTER table.  The
    percentage at the right is the user data size divided by the total file
    size.

Percentage of total database

    The amount of the complete database file that is devoted to storing
    information described by this category.

Number of entries

    The total number of B*Tree key/value pairs stored under this category.

Bytes of storage consumed

    The total amount of disk space required to store all B*Tree entries
    under this category.  The is the total number of pages used times
    the pages size (1024).

Bytes of payload

    The amount of payload stored under this category.  Payload is the sum
    of keys and data.  Each table entry has 4 bytes of key and an arbitrary
    amount of data.  Each index entry has 4 or more bytes of key and no
    data.  The percentage at the right is the bytes of payload divided by
    the bytes of storage consumed.

Bytes of data

    The amount of data stored under this category.  The data space reported
    includes formatting information such as nul-terminators and field-lengths
    that are stored with the data.  The percentage at the right is the bytes
    of data divided by bytes of storage consumed.

Bytes of key

    The sum of the sizes of all keys under this category.  The percentage at
    the right is the bytes of key divided by the bytes of storage consumed.

Average payload per entry

    The average amount of payload on each entry.  This is just the bytes of
    payload divided by the number of entries.

Average unused bytes per entry

    The average amount of free space remaining on all pages under this
    category on a per-entry basis.  This is the number of unused bytes on
    all pages divided by the number of entries.

Maximum payload per entry

    The largest payload size of any entry.

Entries that use overflow

    Up to 236 bytes of payload for each entry are stored directly in the
    primary B*Tree page.  Any additional payload is stored on a linked list
    of overflow pages.  This is the number of entries that exceed 236 bytes
    in size.  The value to the right is the number of entries that overflow
    divided by the total number of entries.

Total pages used

    This is the number of 1024 byte pages used to hold all information in
    the current category.  This is the sum of primary and overflow pages.

Primary pages used

    This is the number of primary B*Tree pages used.

Overflow pages used

    The total number of overflow pages used for this category.

Unused bytes on primary pages

    The total number of bytes of unused space on all primary pages.  The
    percentage at the right is the number of unused bytes divided by the
    total number of bytes on primary pages.

Unused bytes on overflow pages

    The total number of bytes of unused space on all overflow pages.  The
    percentage at the right is the number of unused bytes divided by the
    total number of bytes on overflow pages.

Unused bytes on all pages

    The total number of bytes of unused space on all primary and overflow 
    pages.  The percentage at the right is the number of unused bytes 
    divided by the total number of bytes.
}

# Output the database
#
puts "**********************************************************************"
puts "The entire text of this report can be sourced into any SQL database"
puts "engine for further analysis.  All of the text above is an SQL comment."
puts "The data used to generate this report follows:"
puts "*/"
puts "BEGIN;"
puts $tabledef
unset -nocomplain x
mem eval {SELECT * FROM space_used} x {
  puts -nonewline "INSERT INTO space_used VALUES("
  regsub ' $x(name) '' qn
  regsub ' $x(tblname) '' qtn
  puts -nonewline "'$qn','$qtn',"
  puts -nonewline "$x(is_index),$x(nentry),$x(payload),$x(mx_payload),"
  puts -nonewline "$x(n_ovfl),$x(pri_pages),$x(ovfl_pages),$x(pri_unused),"
  puts "$x(ovfl_unused));"
}
puts "COMMIT;"