Merge latest trunk changes with this branch.

FossilOrigin-Name: 55b8011d5b455927f5b92a3cb911fd909fb0edab
This commit is contained in:
dan 2014-09-15 15:34:31 +00:00
commit d4a80e6742
84 changed files with 2262 additions and 601 deletions

View File

@ -0,0 +1,88 @@
/*
** 2014-09-08
**
** 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 the application interface definitions for the
** user-authentication extension feature.
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
** user-auth.txt file in the same source directory as this file for
** additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
int sqlite3_user_authenticate(
sqlite3 *db, /* The database connection */
const char *zUsername, /* Username */
const char *aPW, /* Password or credentials */
int nPW /* Number of bytes in aPW[] */
);
/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user. When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
const char *aPW, /* Password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* True to give new user admin privilege */
);
/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege. Any user can change their own
** login credentials. Only an admin user can change another users login
** credentials or admin privilege setting. No user may change their own
** admin privilege setting.
*/
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
const char *aPW, /* New password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* Modified admin privilege for the user */
);
/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user. The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
);
#endif /* SQLITE_USER_AUTHENTICATION */

164
ext/userauth/user-auth.txt Normal file
View File

@ -0,0 +1,164 @@
Activate the user authentication logic by including the
ext/userauth/userauth.c source code file in the build and
adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
The ext/userauth/sqlite3userauth.h header file is available to
applications to define the interface.
When using the SQLite amalgamation, it is sufficient to append
the ext/userauth/userauth.c source file onto the end of the
amalgamation.
The following new APIs are available when user authentication is
activated:
int sqlite3_user_authenticate(
sqlite3 *db, /* The database connection */
const char *zUsername, /* Username */
const char *aPW, /* Password or credentials */
int nPW /* Number of bytes in aPW[] */
);
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
const char *aPW, /* Password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* True to give new user admin privilege */
);
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
const void *aPW, /* Modified password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* Modified admin privilege for the user */
);
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
);
With this extension, a database can be marked as requiring authentication.
By default a database does not require authentication.
The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
work as before: they open a new database connection. However, if the
database being opened requires authentication, then attempts to read
or write from the database will fail with an SQLITE_AUTH error until
after sqlite3_user_authenticate() has been called successfully. The
sqlite3_user_authenticate() call will return SQLITE_OK if the
authentication credentials are accepted and SQLITE_ERROR if not.
Calling sqlite3_user_authenticate() on a no-authentication-required
database connection is a harmless no-op.
If the database is encrypted, then sqlite3_key_v2() must be called first,
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
To recapitulate: When opening an existing unencrypted authentication-
required database, the call sequence is:
sqlite3_open_v2()
sqlite3_user_authenticate();
/* Database is now usable */
To open an existing, encrypted, authentication-required database, the
call sequence is:
sqlite3_open_v2();
sqlite3_key_v2();
sqlite3_user_authenticate();
/* Database is now usable */
When opening a no-authentication-required database, the database
connection is treated as if it was authenticated as an admin user.
When ATTACH-ing new database files to a connection, each newly attached
database that is an authentication-required database is checked using
the same username and password as supplied to the main database. If that
check fails, then the ATTACH command fails with an SQLITE_AUTH error.
The sqlite3_user_add() interface can be used (by an admin user only)
to create a new user. When called on a no-authentication-required
database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
converts the database into an authentication-required database and
logs in the database connection D as user U with password P,N.
To convert a no-authentication-required database into an authentication-
required database, the isAdmin parameter must be true. If
sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
database and A is false, then the call fails with an SQLITE_AUTH error.
Any call to sqlite3_user_add() by a non-admin user results in an error.
Hence, to create a new, unencrypted, authentication-required database,
the call sequence is:
sqlite3_open_v2();
sqlite3_user_add();
And to create a new, encrypted, authentication-required database, the call
sequence is:
sqlite3_open_v2();
sqlite3_key_v2();
sqlite3_user_add();
The sqlite3_user_delete() interface can be used (by an admin user only)
to delete a user. The currently logged-in user cannot be deleted,
which guarantees that there is always an admin user and hence that
the database cannot be converted into a no-authentication-required
database.
The sqlite3_user_change() interface can be used to change a users
login credentials or admin privilege. Any user can change their own
password. Only an admin user can change another users login
credentials or admin privilege setting. No user may change their own
admin privilege setting.
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
which is the username of the currently logged in user, or NULL for a
no-authentication-required database.
-----------------------------------------------------------------------------
Implementation notes:
An authentication-required database is identified by the presence of a
new table:
CREATE TABLE sqlite_user(
uname TEXT PRIMARY KEY,
isAdmin BOOLEAN,
pw BLOB
) WITHOUT ROWID;
The sqlite_user table is inaccessible (unreadable and unwriteable) to
non-admin users and is read-only for admin users. However, if the same
database file is opened by a version of SQLite that omits
the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
table will be readable by anybody and writeable by anybody if
the "PRAGMA writable_schema=ON" statement is run first.
The sqlite_user.pw field is encoded by a built-in SQL function
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
is the plaintext password supplied to the sqlite3_user_authenticate()
interface. The second argument is the sqlite_user.pw value and is supplied
so that the function can extract the "salt" used by the password encoder.
The result of sqlite_crypt(X,Y) is another blob which is the value that
ends up being stored in sqlite_user.pw. To verify credentials X supplied
by the sqlite3_user_authenticate() routine, SQLite runs:
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
To compute an appropriate sqlite_user.pw value from a new or modified
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
when the second argument is NULL.
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
which prevents passwords from being revealed by searching the raw database
for ASCII text, but is otherwise trivally broken. For better password
security, the database should be encrypted using the SQLite Encryption
Extension or similar technology. Or, the application can use the
sqlite3_create_function() interface to provide an alternative
implementation of sqlite_crypt() that computes a stronger password hash,
perhaps using a cryptographic hash function like SHA1.

355
ext/userauth/userauth.c Normal file
View File

@ -0,0 +1,355 @@
/*
** 2014-09-08
**
** 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 the bulk of the implementation of the
** user-authentication extension feature. Some parts of the user-
** authentication code are contained within the SQLite core (in the
** src/ subdirectory of the main source code tree) but those parts
** that could reasonable be separated out are moved into this file.
**
** To compile with the user-authentication feature, append this file to
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
** compile-time option. See the user-auth.txt file in the same source
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
#ifndef _SQLITEINT_H_
# include "sqliteInt.h"
#endif
/*
** Prepare an SQL statement for use by the user authentication logic.
** Return a pointer to the prepared statement on success. Return a
** NULL pointer if there is an error of any kind.
*/
static sqlite3_stmt *sqlite3UserAuthPrepare(
sqlite3 *db,
const char *zFormat,
...
){
sqlite3_stmt *pStmt;
char *zSql;
int rc;
va_list ap;
int savedFlags = db->flags;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ) return 0;
db->flags |= SQLITE_WriteSchema;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
db->flags = savedFlags;
sqlite3_free(zSql);
if( rc ){
sqlite3_finalize(pStmt);
pStmt = 0;
}
return pStmt;
}
/*
** Check to see if the sqlite_user table exists in database zDb.
*/
static int userTableExists(sqlite3 *db, const char *zDb){
int rc;
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
if( db->init.busy==0 ){
char *zErr = 0;
sqlite3Init(db, &zErr);
sqlite3DbFree(db, zErr);
}
rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Check to see if database zDb has a "sqlite_user" table and if it does
** whether that table can authenticate zUser with nPw,zPw. Write one of
** the UAUTH_* user authorization level codes into *peAuth and return a
** result code.
*/
static int userAuthCheckLogin(
sqlite3 *db, /* The database connection to check */
const char *zDb, /* Name of specific database to check */
u8 *peAuth /* OUT: One of UAUTH_* constants */
){
sqlite3_stmt *pStmt;
int rc;
*peAuth = UAUTH_Unknown;
if( !userTableExists(db, "main") ){
*peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
return SQLITE_OK;
}
if( db->auth.zAuthUser==0 ){
*peAuth = UAUTH_Fail;
return SQLITE_OK;
}
pStmt = sqlite3UserAuthPrepare(db,
"SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
" WHERE uname=?2", zDb);
if( pStmt==0 ) return SQLITE_NOMEM;
sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
*peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
}else{
*peAuth = UAUTH_Fail;
}
return sqlite3_finalize(pStmt);
}
int sqlite3UserAuthCheckLogin(
sqlite3 *db, /* The database connection to check */
const char *zDb, /* Name of specific database to check */
u8 *peAuth /* OUT: One of UAUTH_* constants */
){
int rc;
u8 savedAuthLevel;
assert( zDb!=0 );
assert( peAuth!=0 );
savedAuthLevel = db->auth.authLevel;
db->auth.authLevel = UAUTH_Admin;
rc = userAuthCheckLogin(db, zDb, peAuth);
db->auth.authLevel = savedAuthLevel;
return rc;
}
/*
** If the current authLevel is UAUTH_Unknown, the take actions to figure
** out what authLevel should be
*/
void sqlite3UserAuthInit(sqlite3 *db){
if( db->auth.authLevel==UAUTH_Unknown ){
u8 authLevel = UAUTH_Fail;
sqlite3UserAuthCheckLogin(db, "main", &authLevel);
db->auth.authLevel = authLevel;
if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
}
}
/*
** Implementation of the sqlite_crypt(X,Y) function.
**
** If Y is NULL then generate a new hash for password X and return that
** hash. If Y is not null, then generate a hash for password X using the
** same salt as the previous hash Y and return the new hash.
*/
void sqlite3CryptFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
const char *zIn;
int nIn, ii;
u8 *zOut;
char zSalt[8];
zIn = sqlite3_value_blob(argv[0]);
nIn = sqlite3_value_bytes(argv[0]);
if( sqlite3_value_type(argv[1])==SQLITE_BLOB
&& sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
){
memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
}else{
sqlite3_randomness(sizeof(zSalt), zSalt);
}
zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
if( zOut==0 ){
sqlite3_result_error_nomem(context);
}else{
memcpy(zOut, zSalt, sizeof(zSalt));
for(ii=0; ii<nIn; ii++){
zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
}
sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
}
}
/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
** appropriate username and password prior to enable read and write
** access to the database.
**
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
** combination is incorrect or unknown.
**
** If the SQLITE_USER table is not present in the database file, then
** this interface is a harmless no-op returnning SQLITE_OK.
*/
int sqlite3_user_authenticate(
sqlite3 *db, /* The database connection */
const char *zUsername, /* Username */
const char *zPW, /* Password or credentials */
int nPW /* Number of bytes in aPW[] */
){
int rc;
u8 authLevel = UAUTH_Fail;
db->auth.authLevel = UAUTH_Unknown;
sqlite3_free(db->auth.zAuthUser);
sqlite3_free(db->auth.zAuthPW);
memset(&db->auth, 0, sizeof(db->auth));
db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
memcpy(db->auth.zAuthPW,zPW,nPW);
db->auth.nAuthPW = nPW;
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
db->auth.authLevel = authLevel;
sqlite3ExpirePreparedStatements(db);
if( rc ){
return rc; /* OOM error, I/O error, etc. */
}
if( authLevel<UAUTH_User ){
return SQLITE_AUTH; /* Incorrect username and/or password */
}
return SQLITE_OK; /* Successful login */
}
/*
** The sqlite3_user_add() interface can be used (by an admin user only)
** to create a new user. When called on a no-authentication-required
** database, this routine converts the database into an authentication-
** required database, automatically makes the added user an
** administrator, and logs in the current connection as that user.
** The sqlite3_user_add() interface only works for the "main" database, not
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
** non-admin user results in an error.
*/
int sqlite3_user_add(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to be added */
const char *aPW, /* Password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* True to give new user admin privilege */
){
sqlite3_stmt *pStmt;
int rc;
sqlite3UserAuthInit(db);
if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
if( !userTableExists(db, "main") ){
if( !isAdmin ) return SQLITE_AUTH;
pStmt = sqlite3UserAuthPrepare(db,
"CREATE TABLE sqlite_user(\n"
" uname TEXT PRIMARY KEY,\n"
" isAdmin BOOLEAN,\n"
" pw BLOB\n"
") WITHOUT ROWID;");
if( pStmt==0 ) return SQLITE_NOMEM;
sqlite3_step(pStmt);
rc = sqlite3_finalize(pStmt);
if( rc ) return rc;
}
pStmt = sqlite3UserAuthPrepare(db,
"INSERT INTO sqlite_user(uname,isAdmin,pw)"
" VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
zUsername, isAdmin!=0);
if( pStmt==0 ) return SQLITE_NOMEM;
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_finalize(pStmt);
if( rc ) return rc;
if( db->auth.zAuthUser==0 ){
assert( isAdmin!=0 );
sqlite3_user_authenticate(db, zUsername, aPW, nPW);
}
return SQLITE_OK;
}
/*
** The sqlite3_user_change() interface can be used to change a users
** login credentials or admin privilege. Any user can change their own
** login credentials. Only an admin user can change another users login
** credentials or admin privilege setting. No user may change their own
** admin privilege setting.
*/
int sqlite3_user_change(
sqlite3 *db, /* Database connection */
const char *zUsername, /* Username to change */
const char *aPW, /* Modified password or credentials */
int nPW, /* Number of bytes in aPW[] */
int isAdmin /* Modified admin privilege for the user */
){
sqlite3_stmt *pStmt;
int rc;
u8 authLevel;
authLevel = db->auth.authLevel;
if( authLevel<UAUTH_User ){
/* Must be logged in to make a change */
return SQLITE_AUTH;
}
if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
if( db->auth.authLevel<UAUTH_Admin ){
/* Must be an administrator to change a different user */
return SQLITE_AUTH;
}
}else if( isAdmin!=(authLevel==UAUTH_Admin) ){
/* Cannot change the isAdmin setting for self */
return SQLITE_AUTH;
}
db->auth.authLevel = UAUTH_Admin;
if( !userTableExists(db, "main") ){
/* This routine is a no-op if the user to be modified does not exist */
}else{
pStmt = sqlite3UserAuthPrepare(db,
"UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
" WHERE uname=%Q", isAdmin, zUsername);
if( pStmt==0 ){
rc = SQLITE_NOMEM;
}else{
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_finalize(pStmt);
}
}
db->auth.authLevel = authLevel;
return rc;
}
/*
** The sqlite3_user_delete() interface can be used (by an admin user only)
** to delete a user. The currently logged-in user cannot be deleted,
** which guarantees that there is always an admin user and hence that
** the database cannot be converted into a no-authentication-required
** database.
*/
int sqlite3_user_delete(
sqlite3 *db, /* Database connection */
const char *zUsername /* Username to remove */
){
sqlite3_stmt *pStmt;
if( db->auth.authLevel<UAUTH_Admin ){
/* Must be an administrator to delete a user */
return SQLITE_AUTH;
}
if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
/* Cannot delete self */
return SQLITE_AUTH;
}
if( !userTableExists(db, "main") ){
/* This routine is a no-op if the user to be deleted does not exist */
return SQLITE_OK;
}
pStmt = sqlite3UserAuthPrepare(db,
"DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
if( pStmt==0 ) return SQLITE_NOMEM;
sqlite3_step(pStmt);
return sqlite3_finalize(pStmt);
}
#endif /* SQLITE_USER_AUTHENTICATION */

13
main.mk
View File

@ -46,7 +46,7 @@
#
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
TCCX += -I$(TOP)/ext/async
TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
# Object files for the SQLite library.
#
@ -67,7 +67,7 @@ LIBOBJ+= vdbe.o parse.o \
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rowset.o rtree.o select.o status.o \
table.o threads.o tokenize.o trigger.o \
update.o util.o vacuum.o \
update.o userauth.o util.o vacuum.o \
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
@ -214,7 +214,9 @@ SRC += \
$(TOP)/ext/rtree/sqlite3rtree.h \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/userauth/userauth.c \
$(TOP)/ext/userauth/sqlite3userauth.h
# Generated source code files
#
@ -378,6 +380,8 @@ EXTHDR += \
$(TOP)/ext/rtree/rtree.h
EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
$(TOP)/ext/userauth/sqlite3userauth.h
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@ -559,6 +563,9 @@ fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
# Rules for building test programs and for running tests
#

170
manifest
View File

@ -1,5 +1,5 @@
C Have\ssqlite3ota.c\suse\sgrave\saccents\sinstead\sof\sdouble-quotes\sto\senclose\sidentifiers\sin\sgenerated\sSQL.\sTo\savoid\shaving\sthe\sSQL\sengine\ssubstitute\sa\sliteral\sstring\sif\sa\scolumn\sreference\scannot\sbe\sresolved.
D 2014-09-15T15:22:32.496
C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
D 2014-09-15T15:34:31.844
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -150,10 +150,13 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk ed2e37f6cd016ecc614165b3392bdbf89a129b4a
F main.mk 8e4a294f77e23b2d19e2ac8f5a8761d260bfa4af
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@ -167,79 +170,79 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
F src/analyze.c f00f06e6ef66c61b41f154889fe7caf5ed55a0ce
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
F src/analyze.c 79383a54fee3b7f1fb03dd4c8c8115583f506de5
F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4
F src/btree.c 9cb1989073502a9d2f18fbb0e7df8ad89dda2dcf
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
F src/btree.c 3957262c61e865833021af435b6b6daf3a0829be
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
F src/build.c c26b233dcdb1e2c8f468d49236c266f9f3de96d8
F src/callback.c b97d0695ffcf6a8710ee445ffe56ee387d4d8a6f
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 3c2a375c0329247d01222170ae19ad8a52ecbf9a
F src/expr.c e1691ab0fe6be7247ef073b0038fb8ecd9944fad
F src/btreeInt.h e0ecb5dba292722039a7540beb3fc448103273cc
F src/build.c 047d7e1d2d89fa55134fa1d6b669c9c2983c0d11
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
F src/ctime.c 16cd19215d9fd849ee2b7509b092f2e0bbd6a958
F src/date.c 57a7f9ba9f6b4d5268f5e411739066a611f99036
F src/delete.c df9e2f273675ebf8d7f229e7668ba941bdc7021a
F src/expr.c 19392d98e089640c3336e65b4254cc337efef7d1
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 8d81a780ad78d16ec9082585758a8f1d6bf02ca3
F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
F src/func.c 5d498933f6168dff80941c873805fe04dc2b766d
F src/global.c 5110fa12e09729b84eee0191c984ec4008e21937
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 62b0ceab1720dc74ed1fbcf953224132245704d8
F src/insert.c 25e63641927530eee0487c5a8bbf6e5414c4c753
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab
F src/main.c c9802dc99c019fbba516202300d56be2c478fa93
F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
F src/main.c 6b9fd1867a5575db2119f850302a883e7684009c
F src/malloc.c cc015821ba267ad5c91dc8761d0498a3fc3ce6ce
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
F src/mutex.c 84a073c9a23a8d7bdd2ea832522d1730df18812c
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1
F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3
F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 8525ca79457c5b4673a5fda2774ee39fe155f40f
F src/os_win.c 2aa8aa7780d7cf03e912d2088ab2ec5c32f33dc5
F src/os_unix.c addd023b26c623fec4dedc110fc4370a65b4768c
F src/os_win.c 0a4042ef35f322e86fa01f6c8884c5e645b911e7
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
F src/pager.c 9611de7c00ea3cfe35295d88ebda1a096b71b41d
F src/pager.c b7c625fc92e86fea1971b8a630009eab3ff18997
F src/pager.h 6a08df06b7edc3684375c0fab40602c695a044f2
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c 3b3791297e8977002e56b4a9b8916f2039abad9b
F src/pcache.c 4121a0571c18581ee9f82f086d5e2030051ebd6a
F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
F src/pcache1.c c5af6403a55178c9d1c09e4f77b0f9c88822762c
F src/pragma.c e1b8049c059ccab0afc2a483ff2e0dd599fcb124
F src/prepare.c 314961aa6650cc860394cb2f31931cf2de93baa8
F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74
F src/pcache1.c dab8ab930d4a73b99768d881185994f34b80ecaa
F src/pragma.c 5dba6b386cbfe0b094350b7d6c99fd410958f22d
F src/prepare.c 905c3c601ccadd22bb70b63cd48392f7126c9807
F src/printf.c e74925089a85e3c9f0e315595f41c139d3d118c2
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
F src/select.c 89e569b263535662f54b537eb9118b2c554ae7aa
F src/shell.c 713cef4d73c05fc8e12f4960072329d767a05d50
F src/sqlite.h.in 578c42cb3899ee6ad93a0cccff4eb47e1e9a2c80
F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 0cd6706fd52ae5db229e9041094db6ec27195335
F src/shell.c c00220cdd7f2027780bc25b78376c16dc24e4b7d
F src/sqlite.h.in 5bcaca9d5a8403fda0c8677de4c527907b317f1d
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 7c090825333d91ca392c2479a9e835e7b6a5eb12
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 3210f8bd040d1c6d8b1616325b15dd3ff749e48f
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 29357f2be7b0d00e8ea900eaf727e0c5ffeaa660
F src/test1.c e9a0e5804b078532e69e69ec14c8326bf2cfc318
F src/table.c 218ae2ba022881846741dfc8351aefdf129e0377
F src/tclsqlite.c ac7d1672f69c9d69defeb022f656d04f5cefd198
F src/test1.c 75655557ebc7138e1d745313635b6b100c90c151
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
@ -252,18 +255,18 @@ F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c d5f00627c4f47515a57f905806558153cccd7253
F src/test_config.c 6f721f0337b96d58e81ff69bba101113c8168c2b
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
F src/test_func.c d3013ce36f19ac72a99c73864930fd1fa41832f8
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c db4614c2262a06abc4409dc048d59c580c38320f
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
F src/test_malloc.c 5368fb1de77246da1ae0ff59cba0d30cb0e5812f
F src/test_malloc.c ba34143f941a9d74b30bbffc8818389bb73a1ca2
F src/test_multiplex.c ca90057438b63bf0840ebb84d0ef050624519a76
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
@ -273,7 +276,7 @@ F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31
@ -285,30 +288,30 @@ F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 22dded4283dc4b25422f6444cdcb8d6b1ea0b5ff
F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec
F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6
F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059
F src/tokenize.c 3df63041994f55afeb168b463ec836e8f1c50e7c
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359
F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 90db7ad740b6d3f7ab446e6244dbc17ce495cca6
F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
F src/vdbe.c 9a45dcbcc967fc0cb9248c75ba245d1d47de3e78
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
F src/vdbeInt.h cdc8e421f85beb1ac9b4669ec5beadab6faa15e0
F src/vdbeapi.c 09677a53dd8c71bcd670b0bd073bb9aefa02b441
F src/vdbeaux.c cef5d34a64ae3a65b56d96d3fd663246ec8e1c36
F src/vdbeInt.h b4843c35c3ba533b69d4250f550b5bacf2fb013d
F src/vdbeapi.c 06b712d4772b318b69cd37a416deb1ff0426aa8c
F src/vdbeaux.c 91fd1e0c54a765838dc61fcf79f31acce035ce38
F src/vdbeblob.c a8e2c3baa3e7081347c4677185a631bfc43de043
F src/vdbemem.c 921d5468a68ac06f369810992e84ca22cc730a62
F src/vdbesort.c 7c45bfcd823f30d172bbbc1b9f51ef4402fbfe8d
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vdbemem.c dc36ea9fe26c25550c50085f388167086ef7d73a
F src/vdbesort.c 36ac09004c2ca57486ba3d1f4ac5d0d62257b136
F src/vdbetrace.c 16d39c1ef7d1f4a3a7464bea3b7b4bdd7849c415
F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f
F src/wal.c 93b4fcb56a98f435a2cb66024bb2b12d66d1ff53
F src/wal.c 6f5ff51117293e7b2c75ad21834f51115e59ea96
F src/wal.h 237bc4484f7c289f094ecb6efb2b6c02005484e1
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c d9eae96b2cbbe4842eac3ee156ccd1b933d802c4
F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 839b5e1db2507e221ad1c308f148a8519ed750be
F src/whereInt.h 124d970450955a6982e174b07c320ae6d62a595c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
@ -339,9 +342,9 @@ F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test 5bdf154eb28c0e4bbc0473f335858c0d96171768
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360
F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa
F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
F test/autoindex2.test 60d2fc6f38364308ce73a9beb01b47ded38697de
@ -482,7 +485,7 @@ F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
F test/fkey2.test 32ca728bcb854feed72d1406ea375fe423eebff2
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
@ -580,7 +583,7 @@ F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test c551043de056b0b1582a54e878991f57bad074bc
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
@ -715,7 +718,7 @@ F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
@ -788,7 +791,7 @@ F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test b78b30afb9537a73788ca1233a23a32190a3bb1f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
F test/savepoint.test 6c53f76dffe5df0dd87646efe3e7aa159c36e07b
F test/savepoint.test 51d3900dc071a7c2ad4248578a5925631b476313
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
@ -1060,6 +1063,7 @@ F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
@ -1070,7 +1074,7 @@ F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
F test/vtab1.test b631d147b198cfd7903ab5fed028eb2a3d321dc6
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09
@ -1131,7 +1135,7 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
F test/whereJ.test 8880784c211c459595f734a35bcc5f2061fce987
F test/whereJ.test 63599653dfefe4e74ebb358db753417fe0aa8a49
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
@ -1142,7 +1146,7 @@ F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
@ -1199,7 +1203,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 473a72d7009a22ea514a98ee8869e7e7bca14cf5
R 6e8944bfcc8da0bf6b98d50ae7beb161
P 79f2418429aa05c56069c56d51b4d72f662a6970 69a64560777f85b47349b4b2aab01dc99298592e
R 10cbf38158f2f089e176ffb2e809ade0
U dan
Z 793743aae527be1bb170d7639993b8ad
Z c612131a6abb7d1e449d4f88a8b72de0

View File

@ -1 +1 @@
79f2418429aa05c56069c56d51b4d72f662a6970
55b8011d5b455927f5b92a3cb911fd909fb0edab

View File

@ -174,8 +174,8 @@ static void renameTriggerFunc(
UNUSED_PARAMETER(NotUsed);
/* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
** statement is that the table name is the first token that is immediately
** preceded by either TK_ON or TK_DOT and immediately followed by one
** of TK_WHEN, TK_BEGIN or TK_FOR.
*/
if( zSql ){

View File

@ -35,7 +35,7 @@
** not possible to enable both STAT3 and STAT4 at the same time. If they
** are both enabled, then STAT4 takes precedence.
**
** For most applications, sqlite_stat1 provides all the statisics required
** For most applications, sqlite_stat1 provides all the statistics required
** for the query planner to make good choices.
**
** Format of sqlite_stat1:
@ -387,7 +387,7 @@ static void stat4Destructor(void *pOld){
** original WITHOUT ROWID table as N==K as a special case.
**
** This routine allocates the Stat4Accum object in heap memory. The return
** value is a pointer to the the Stat4Accum object. The datatype of the
** value is a pointer to the Stat4Accum object. The datatype of the
** return value is BLOB, but it is really just a pointer to the Stat4Accum
** object.
*/
@ -1583,7 +1583,7 @@ static void initAvgEq(Index *pIdx){
/* Set nSum to the number of distinct (iCol+1) field prefixes that
** occur in the stat4 table for this index before pFinal. Set
** sumEq to the sum of the nEq values for column iCol for the same
** set (adding the value only once where there exist dupicate
** set (adding the value only once where there exist duplicate
** prefixes). */
for(i=0; i<(pIdx->nSample-1); i++){
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){

View File

@ -207,6 +207,15 @@ static void attachFunc(
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
}
#ifdef SQLITE_USER_AUTHENTICATION
if( rc==SQLITE_OK ){
u8 newAuth = 0;
rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
if( newAuth<db->auth.authLevel ){
rc = SQLITE_AUTH_USER;
}
}
#endif
if( rc ){
int iDb = db->nDb - 1;
assert( iDb>=2 );

View File

@ -73,7 +73,7 @@ int sqlite3_set_authorizer(
void *pArg
){
sqlite3_mutex_enter(db->mutex);
db->xAuth = xAuth;
db->xAuth = (sqlite3_xauth)xAuth;
db->pAuthArg = pArg;
sqlite3ExpirePreparedStatements(db);
sqlite3_mutex_leave(db->mutex);
@ -108,7 +108,11 @@ int sqlite3AuthReadCol(
char *zDb = db->aDb[iDb].zName; /* Name of attached database */
int rc; /* Auth callback return code */
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
#endif
);
if( rc==SQLITE_DENY ){
if( db->nDb>2 || iDb!=0 ){
sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
@ -208,7 +212,11 @@ int sqlite3AuthCheck(
if( db->xAuth==0 ){
return SQLITE_OK;
}
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
#endif
);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;

View File

@ -106,7 +106,7 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
Btree *pLater;
/* In most cases, we should be able to acquire the lock we
** want without having to go throught the ascending lock
** want without having to go through the ascending lock
** procedure that follows. Just be sure not to block.
*/
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a external (disk-based) database using BTrees.
** This file implements an external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
@ -607,7 +607,7 @@ static int saveCursorPosition(BtCursor *pCur){
** data.
*/
if( 0==pCur->apPage[0]->intKey ){
void *pKey = sqlite3Malloc( (int)pCur->nKey );
void *pKey = sqlite3Malloc( pCur->nKey );
if( pKey ){
rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
@ -1145,7 +1145,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
*/
static int defragmentPage(MemPage *pPage){
int i; /* Loop counter */
int pc; /* Address of a i-th cell */
int pc; /* Address of the i-th cell */
int hdr; /* Offset to the page header */
int size; /* Size of a cell */
int usableSize; /* Number of usable bytes on a page */
@ -2602,7 +2602,7 @@ page1_init_failed:
** false then all cursors are counted.
**
** For the purposes of this routine, a cursor is any cursor that
** is capable of reading or writing to the databse. Cursors that
** is capable of reading or writing to the database. Cursors that
** have been tripped into the CURSOR_FAULT state are not counted.
*/
static int countValidCursors(BtShared *pBt, int wrOnly){
@ -3066,7 +3066,7 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
** calling this function again), return SQLITE_DONE. Or, if an error
** occurs, return some other error code.
**
** More specificly, this function attempts to re-organize the database so
** More specifically, this function attempts to re-organize the database so
** that the last page of the file currently in use is no longer in use.
**
** Parameter nFin is the number of pages that this database would contain
@ -3074,7 +3074,7 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
**
** If the bCommit parameter is non-zero, this function assumes that the
** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
** or an error. bCommit is passed true for an auto-vacuum-on-commmit
** or an error. bCommit is passed true for an auto-vacuum-on-commit
** operation, or false for an incremental vacuum.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
@ -3541,7 +3541,7 @@ int sqlite3BtreeRollback(Btree *p, int tripCode){
}
/*
** Start a statement subtransaction. The subtransaction can can be rolled
** Start a statement subtransaction. The subtransaction can be rolled
** back independently of the main transaction. You must start a transaction
** before starting a subtransaction. The subtransaction is ended automatically
** if the main transaction commits or rolls back.
@ -3775,7 +3775,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
** compiler to crash when getCellInfo() is implemented as a macro.
** But there is a measureable speed advantage to using the macro on gcc
** (when less compiler optimizations like -Os or -O0 are used and the
** compiler is not doing agressive inlining.) So we use a real function
** compiler is not doing aggressive inlining.) So we use a real function
** for MSVC and a macro for everything else. Ticket #2457.
*/
#ifndef NDEBUG
@ -3992,7 +3992,7 @@ static int copyPayload(
**
** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily
** popluates the overflow page-list cache array (BtCursor.aOverflow).
** populates the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
@ -4194,7 +4194,7 @@ static int accessPayload(
/*
** Read part of the key associated with cursor pCur. Exactly
** "amt" bytes will be transfered into pBuf[]. The transfer
** "amt" bytes will be transferred into pBuf[]. The transfer
** begins at "offset".
**
** The caller must ensure that pCur is pointing to a valid row
@ -5890,7 +5890,7 @@ static void insertCell(
** The cells are guaranteed to fit on the page.
*/
static void assemblePage(
MemPage *pPage, /* The page to be assemblied */
MemPage *pPage, /* The page to be assembled */
int nCell, /* The number of cells to add to this page */
u8 **apCell, /* Pointers to cell bodies */
u16 *aSize /* Sizes of the cells */
@ -6556,7 +6556,7 @@ static int balance_nonroot(
}
/*
** Put the new pages in accending order. This helps to
** Put the new pages in ascending order. This helps to
** keep entries in the disk file in order so that a scan
** of the table is a linear scan through the file. That
** in turn helps the operating system to deliver pages
@ -6951,7 +6951,7 @@ static int balance(BtCursor *pCur){
/* Call balance_quick() to create a new sibling of pPage on which
** to store the overflow cell. balance_quick() inserts a new cell
** into pParent, which may cause pParent overflow. If this
** happens, the next interation of the do-loop will balance pParent
** happens, the next iteration of the do-loop will balance pParent
** use either balance_nonroot() or balance_deeper(). Until this
** happens, the overflow cell is stored in the aBalanceQuickSpace[]
** buffer.
@ -7028,7 +7028,7 @@ static int balance(BtCursor *pCur){
** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
** been performed. seekResult is the search result returned (a negative
** number if pCur points at an entry that is smaller than (pKey, nKey), or
** a positive value if pCur points at an etry that is larger than
** a positive value if pCur points at an entry that is larger than
** (pKey, nKey)).
**
** If the seekResult parameter is non-zero, then the caller guarantees that
@ -7185,7 +7185,7 @@ end_insert:
/*
** Delete the entry that the cursor is pointing to. The cursor
** is left pointing at a arbitrary location.
** is left pointing at an arbitrary location.
*/
int sqlite3BtreeDelete(BtCursor *pCur){
Btree *p = pCur->pBtree;
@ -7883,7 +7883,7 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
/*
** Add 1 to the reference count for page iPage. If this is the second
** reference to the page, add an error message to pCheck->zErrMsg.
** Return 1 if there are 2 ore more references to the page and 0 if
** Return 1 if there are 2 or more references to the page and 0 if
** if this is the first reference to the page.
**
** Also check that the page number is in bounds.

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a external (disk-based) database using BTrees.
** This file implements an external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
@ -135,7 +135,7 @@
**
** The flags define the format of this btree page. The leaf flag means that
** this page has no children. The zerodata flag means that this page carries
** only keys and no data. The intkey flag means that the key is a integer
** only keys and no data. The intkey flag means that the key is an integer
** which is stored in the key size entry of the cell header rather than in
** the payload area.
**
@ -544,7 +544,7 @@ struct BtCursor {
** seek the cursor to the saved position.
**
** CURSOR_FAULT:
** A unrecoverable error (an I/O error or a malloc failure) has occurred
** An unrecoverable error (an I/O error or a malloc failure) has occurred
** on a different connection that shares the BtShared cache with this
** cursor. The error has left the cache in an inconsistent state.
** Do nothing else with this cursor. Any attempt to use the cursor

View File

@ -156,6 +156,17 @@ void sqlite3FinishCoding(Parse *pParse){
while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
if( pParse->nTableLock>0 && db->init.busy==0 ){
sqlite3UserAuthInit(db);
if( db->auth.authLevel<UAUTH_User ){
pParse->rc = SQLITE_AUTH_USER;
sqlite3ErrorMsg(pParse, "user not authenticated");
return;
}
}
#endif
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
@ -271,6 +282,16 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested--;
}
#if SQLITE_USER_AUTHENTICATION
/*
** Return TRUE if zTable is the name of the system table that stores the
** list of users and their access credentials.
*/
int sqlite3UserAuthTable(const char *zTable){
return sqlite3_stricmp(zTable, "sqlite_user")==0;
}
#endif
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@ -289,6 +310,13 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
assert( zName!=0 );
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
#if SQLITE_USER_AUTHENTICATION
/* Only the admin user is allowed to know that the sqlite_user table
** exists */
if( db->auth.authLevel<UAUTH_Admin && sqlite3UserAuthTable(zName)!=0 ){
return 0;
}
#endif
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
@ -333,6 +361,12 @@ Table *sqlite3LocateTable(
}
pParse->checkSchema = 1;
}
#if SQLITE_USER_AUTHENICATION
else if( pParse->db->auth.authLevel<UAUTH_User ){
sqlite3ErrorMsg(pParse, "user not authenticated");
p = 0;
}
#endif
return p;
}
@ -1619,7 +1653,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** no rowid btree for a WITHOUT ROWID. Instead, the canonical
** data storage is a covering index btree.
** (2) Bypass the creation of the sqlite_master table entry
** for the PRIMARY KEY as the the primary key index is now
** for the PRIMARY KEY as the primary key index is now
** identified by the sqlite_master table entry of the table itself.
** (3) Set the Index.tnum of the PRIMARY KEY Index object in the
** schema to the rootpage from the main table.
@ -1640,7 +1674,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
Vdbe *v = pParse->pVdbe;
/* Convert the OP_CreateTable opcode that would normally create the
** root-page for the table into a OP_CreateIndex opcode. The index
** root-page for the table into an OP_CreateIndex opcode. The index
** created will become the PRIMARY KEY index.
*/
if( pParse->addrCrTab ){
@ -2052,7 +2086,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
sqlite3_xauth xAuth; /* Saved xAuth pointer */
assert( pTable );
@ -2654,7 +2688,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
int regRecord; /* Register holding assemblied index record */
int regRecord; /* Register holding assembled index record */
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
@ -2867,6 +2901,10 @@ Index *sqlite3CreateIndex(
assert( pTab!=0 );
assert( pParse->nErr==0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
#if SQLITE_USER_AUTHENTICATION
&& sqlite3UserAuthTable(pTab->zName)==0
#endif
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
@ -3254,7 +3292,7 @@ exit_create_index:
** Fill the Index.aiRowEst[] array with default information - information
** to be used when we have not run the ANALYZE command.
**
** aiRowEst[0] is suppose to contain the number of elements in the index.
** aiRowEst[0] is supposed to contain the number of elements in the index.
** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
** number of rows in the table that match any particular value of the
** first column of the index. aiRowEst[2] is an estimate of the number
@ -3633,7 +3671,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
** if this is the first term of the FROM clause. pTable and pDatabase
** are the name of the table and database named in the FROM clause term.
** pDatabase is NULL if the database name qualifier is missing - the
** usual case. If the term has a alias, then pAlias points to the
** usual case. If the term has an alias, then pAlias points to the
** alias token. If the term is a subquery, then pSubquery is the
** SELECT statement that the subquery encodes. The pTable and
** pDatabase parameters are NULL for subqueries. The pOn and pUsing

View File

@ -142,7 +142,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
**
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
** array of three CollSeq structures. The first is the collation sequence
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
** preferred for UTF-8, the second UTF-16le, and the third UTF-16be.
**
** Stored immediately after the three collation sequences is a copy of
** the collation sequence name. A pointer to this string is stored in

View File

@ -70,7 +70,7 @@ extern const char sqlite3IsEbcdicIdChar[];
** a statement.
**
** (4) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** statement, possibly preceded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (5) TRIGGER We are in the middle of a trigger definition that must be
@ -80,7 +80,7 @@ extern const char sqlite3IsEbcdicIdChar[];
** the end of a trigger definition.
**
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
** of a trigger definition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
@ -123,7 +123,7 @@ int sqlite3_complete(const char *zSql){
};
#else
/* If triggers are not supported by this compile then the statement machine
** used to detect the end of a statement is much simplier
** used to detect the end of a statement is much simpler
*/
static const u8 trans[3][3] = {
/* Token: */

View File

@ -368,6 +368,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#ifdef SQLITE_USER_AUTHENTICATION
"USER_AUTHENTICATION",
#endif
#ifdef SQLITE_WIN32_MALLOC
"WIN32_MALLOC",
#endif

View File

@ -24,7 +24,7 @@
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
**
** This implemention requires years to be expressed as a 4-digit number
** This implementation requires years to be expressed as a 4-digit number
** which means that only dates between 0000-01-01 and 9999-12-31 can
** be represented, even though julian day numbers allow a much wider
** range of dates.

View File

@ -90,7 +90,7 @@ void sqlite3MaterializeView(
Parse *pParse, /* Parsing context */
Table *pView, /* View definition */
Expr *pWhere, /* Optional WHERE clause to be added */
int iCur /* Cursor number for ephemerial table */
int iCur /* Cursor number for ephemeral table */
){
SelectDest dest;
Select *pSel;
@ -248,7 +248,7 @@ void sqlite3DeleteFrom(
int addrBypass = 0; /* Address of jump over the delete logic */
int addrLoop = 0; /* Top of the delete loop */
int addrDelete = 0; /* Jump directly to the delete logic */
int addrEphOpen = 0; /* Instruction to open the Ephermeral table */
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
@ -328,7 +328,7 @@ void sqlite3DeleteFrom(
sqlite3BeginWriteOperation(pParse, 1, iDb);
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
** an ephemeral table.
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
@ -382,7 +382,7 @@ void sqlite3DeleteFrom(
iRowSet = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
}else{
/* For a WITHOUT ROWID table, create an ephermeral table used to
/* For a WITHOUT ROWID table, create an ephemeral table used to
** hold all primary keys for rows to be deleted. */
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
@ -557,7 +557,7 @@ delete_from_cleanup:
return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** thely may interfere with compilation of other functions in this file
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation). */
#ifdef isView
#undef isView

View File

@ -22,7 +22,7 @@
** affinity of that column is returned. Otherwise, 0x00 is returned,
** indicating no affinity for the expression.
**
** i.e. the WHERE clause expresssions in the following statements all
** i.e. the WHERE clause expressions in the following statements all
** have an affinity:
**
** CREATE TABLE t1(a);
@ -501,7 +501,7 @@ void sqlite3ExprAttachSubtrees(
}
/*
** Allocate a Expr node which joins as many as two subtrees.
** Allocate an Expr node which joins as many as two subtrees.
**
** One or both of the subtrees can be NULL. Return a pointer to the new
** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
@ -611,7 +611,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
**
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
** as the previous instance of the same wildcard. Or if this is the first
** instance of the wildcard, the next sequenial variable number is
** instance of the wildcard, the next sequential variable number is
** assigned.
*/
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
@ -746,7 +746,7 @@ static int exprStructSize(Expr *p){
** During expression analysis, extra information is computed and moved into
** later parts of teh Expr object and that extra information might get chopped
** off if the expression is reduced. Note also that it does not work to
** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal
** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal
** to reduce a pristine expression tree from the parser. The implementation
** of dupedExprStructSize() contain multiple assert() statements that attempt
** to enforce this constraint.
@ -815,7 +815,7 @@ static int dupedExprSize(Expr *p, int flags){
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
** if any. Before returning, *pzBuffer is set to the first byte past the
** portion of the buffer copied into by this function.
*/
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
@ -1541,7 +1541,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephermeral table instead of an
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
**
** The inFlags parameter must contain exactly one of the bits
@ -1671,7 +1671,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){
** and IN_INDEX_NOOP is an allowed reply
** and the RHS of the IN operator is a list, not a subquery
** and the RHS is not contant or has two or fewer terms,
** then it is not worth creating an ephermeral table to evaluate
** then it is not worth creating an ephemeral table to evaluate
** the IN operator so return IN_INDEX_NOOP.
*/
if( eType==0
@ -2432,16 +2432,9 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
*/
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
int i;
struct yColCache *p;
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int x = p->iReg;
if( x>=iFrom && x<iFrom+nReg ){
p->iReg += iTo-iFrom;
}
}
sqlite3ExprCacheRemove(pParse, iFrom, nReg);
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
@ -2758,7 +2751,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
/* Attempt a direct implementation of the built-in COALESCE() and
** IFNULL() functions. This avoids unnecessary evalation of
** IFNULL() functions. This avoids unnecessary evaluation of
** arguments past the first non-NULL argument.
*/
if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
@ -3197,7 +3190,7 @@ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
}
/*
** Generate code that evalutes the given expression and puts the result
** Generate code that evaluates the given expression and puts the result
** in register target.
**
** Also make a copy of the expression results into another "cache" register
@ -3552,7 +3545,7 @@ int sqlite3ExprCodeExprList(
** x>=y AND x<=z
**
** Code it as such, taking care to do the common subexpression
** elementation of x.
** elimination of x.
*/
static void exprCodeBetween(
Parse *pParse, /* Parsing and code generating context */
@ -4289,7 +4282,7 @@ int sqlite3GetTempReg(Parse *pParse){
** purpose.
**
** If a register is currently being used by the column cache, then
** the dallocation is deferred until the column cache line that uses
** the deallocation is deferred until the column cache line that uses
** the register becomes stale.
*/
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){

View File

@ -173,7 +173,7 @@
**
** 4) No parent key columns were provided explicitly as part of the
** foreign key definition, and the PRIMARY KEY of the parent table
** consists of a a different number of columns to the child key in
** consists of a different number of columns to the child key in
** the child table.
**
** then non-zero is returned, and a "foreign key mismatch" error loaded

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C-language implementions for many of the SQL
** This file contains the C-language implementations for many of the SQL
** functions of SQLite. (Some function, and in particular the date and
** time functions, are implemented separately.)
*/
@ -325,13 +325,14 @@ static void substrFunc(
for(z2=z; *z2 && p2; p2--){
SQLITE_SKIP_UTF8(z2);
}
sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
}else{
if( p1+p2>len ){
p2 = len-p1;
if( p2<0 ) p2 = 0;
}
sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
}
}
@ -390,7 +391,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){
sqlite3_result_error_toobig(context);
z = 0;
}else{
z = sqlite3Malloc((int)nByte);
z = sqlite3Malloc(nByte);
if( !z ){
sqlite3_result_error_nomem(context);
}
@ -1041,7 +1042,7 @@ static void charFunc(
*zOut++ = 0x80 + (u8)(c & 0x3F);
} \
}
sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
}
/*
@ -1638,7 +1639,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
}
/*
** All all of the FuncDef structures in the aBuiltinFunc[] array above
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
** a consequence of calling sqlite3_initialize()).
**
@ -1662,10 +1663,12 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(trim, 2, 3, 0, trimFunc ),
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize,
SQLITE_FUNC_MINMAX ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
SQLITE_FUNC_MINMAX ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ),
@ -1695,6 +1698,9 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
#if SQLITE_USER_AUTHENTICATION
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
@ -1715,8 +1721,8 @@ void sqlite3RegisterGlobalFunctions(void){
AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
/* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */
{0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
SQLITE_FUNC_COUNT ),
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),

View File

@ -10,7 +10,7 @@
**
*************************************************************************
**
** This file contains definitions of global variables and contants.
** This file contains definitions of global variables and constants.
*/
#include "sqliteInt.h"

View File

@ -410,7 +410,7 @@ static int xferOptimization(
** The 4th template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
** that is also read as part of the SELECT. In the third form,
** we have to use a intermediate table to store the results of
** we have to use an intermediate table to store the results of
** the select. The template is like this:
**
** X <- A
@ -575,7 +575,7 @@ void sqlite3Insert(
regAutoinc = autoIncBegin(pParse, iDb, pTab);
/* Allocate registers for holding the rowid of the new row,
** the content of the new row, and the assemblied row record.
** the content of the new row, and the assembled row record.
*/
regRowid = regIns = pParse->nMem+1;
pParse->nMem += pTab->nCol + 1;
@ -1027,7 +1027,7 @@ insert_cleanup:
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** thely may interfere with compilation of other functions in this file
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation). */
#ifdef isView
#undef isView
@ -1143,7 +1143,7 @@ void sqlite3GenerateConstraintChecks(
int ix; /* Index loop counter */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
int j1; /* Addresss of jump instruction */
int j1; /* Address of jump instruction */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
int ipkTop = 0; /* Top of the rowid change constraint check */
@ -1551,7 +1551,7 @@ void sqlite3CompleteInsertion(
Index *pIdx; /* An index being inserted or updated */
u8 pik_flags; /* flag values passed to the btree insert */
int regData; /* Content registers (after the rowid) */
int regRec; /* Register holding assemblied record for the table */
int regRec; /* Register holding assembled record for the table */
int i; /* Loop counter */
u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
@ -1685,7 +1685,7 @@ int sqlite3OpenTableAndIndices(
** The following global variable is incremented whenever the
** transfer optimization is used. This is used for testing
** purposes only - to make sure the transfer optimization really
** is happening when it is suppose to.
** is happening when it is supposed to.
*/
int sqlite3_xferopt_count;
#endif /* SQLITE_TEST */
@ -1752,7 +1752,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
** INSERT INTO tab1 SELECT * FROM tab2;
**
** The xfer optimization transfers raw records from tab2 over to tab1.
** Columns are not decoded and reassemblied, which greatly improves
** Columns are not decoded and reassembled, which greatly improves
** performance. Raw index records are transferred in the same way.
**
** The xfer optimization is only attempted if tab1 and tab2 are compatible.

View File

@ -125,7 +125,7 @@ exec_out:
sqlite3DbFree(db, azCols);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
if( rc!=SQLITE_OK && pzErrMsg ){
int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
*pzErrMsg = sqlite3Malloc(nErrMsg);
if( *pzErrMsg ){

View File

@ -271,9 +271,9 @@ static void yyGrowStack(yyParser *p){
** A pointer to a parser. This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
void *ParseAlloc(void *(*mallocProc)(size_t)){
void *ParseAlloc(void *(*mallocProc)(u64)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
pParser = (yyParser*)(*mallocProc)( (u64)sizeof(yyParser) );
if( pParser ){
pParser->yyidx = -1;
#ifdef YYTRACKMAXSTACKDEPTH

View File

@ -390,7 +390,20 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_uri_int64,
sqlite3_uri_parameter,
sqlite3_vsnprintf,
sqlite3_wal_checkpoint_v2
sqlite3_wal_checkpoint_v2,
/* Version 3.8.7 and later */
sqlite3_auto_extension,
sqlite3_bind_blob64,
sqlite3_bind_text64,
sqlite3_cancel_auto_extension,
sqlite3_load_extension,
sqlite3_malloc64,
sqlite3_msize,
sqlite3_realloc64,
sqlite3_reset_auto_extension,
sqlite3_result_blob64,
sqlite3_result_text64,
sqlite3_strglob
};
/*

View File

@ -985,6 +985,10 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
sqlite3CloseExtensions(db);
#if SQLITE_USER_AUTHENTICATION
sqlite3_free(db->auth.zAuthUser);
sqlite3_free(db->auth.zAuthPW);
#endif
db->magic = SQLITE_MAGIC_ERROR;
@ -2566,7 +2570,6 @@ static int openDatabase(
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
/* The default safety_level for the main database is 'full'; for the temp
** database it is 'NONE'. This matches the pager layer defaults.
*/
@ -2853,9 +2856,9 @@ int sqlite3_get_autocommit(sqlite3 *db){
}
/*
** The following routines are subtitutes for constants SQLITE_CORRUPT,
** The following routines are substitutes for constants SQLITE_CORRUPT,
** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
** constants. They server two purposes:
** constants. They serve two purposes:
**
** 1. Serve as a convenient place to set a breakpoint in a debugger
** to detect when version error conditions occurs.
@ -3169,7 +3172,7 @@ int sqlite3_test_control(int op, ...){
** IMPORTANT: Changing the PENDING byte from 0x40000000 results in
** an incompatible database file format. Changing the PENDING byte
** while any database connection is open results in undefined and
** dileterious behavior.
** deleterious behavior.
*/
case SQLITE_TESTCTRL_PENDING_BYTE: {
rc = PENDING_BYTE;

View File

@ -294,11 +294,9 @@ static int mallocWithAlarm(int n, void **pp){
** Allocate memory. This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
void *sqlite3Malloc(int n){
void *sqlite3Malloc(u64 n){
void *p;
if( n<=0 /* IMP: R-65312-04917 */
|| n>=0x7fffff00
){
if( n==0 || n>=0x7fffff00 ){
/* A memory allocation of a number of bytes which is near the maximum
** signed integer value might cause an integer overflow inside of the
** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
@ -310,7 +308,7 @@ void *sqlite3Malloc(int n){
mallocWithAlarm(n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
p = sqlite3GlobalConfig.m.xMalloc(n);
p = sqlite3GlobalConfig.m.xMalloc((int)n);
}
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
return p;
@ -322,6 +320,12 @@ void *sqlite3Malloc(int n){
** allocation.
*/
void *sqlite3_malloc(int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return n<=0 ? 0 : sqlite3Malloc(n);
}
void *sqlite3_malloc64(sqlite3_uint64 n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
@ -458,6 +462,9 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
return sqlite3GlobalConfig.m.xSize(p);
}
}
sqlite3_uint64 sqlite3_msize(void *p){
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
}
/*
** Free memory previously obtained from sqlite3Malloc().
@ -519,13 +526,13 @@ void sqlite3DbFree(sqlite3 *db, void *p){
/*
** Change the size of an existing memory allocation
*/
void *sqlite3Realloc(void *pOld, int nBytes){
void *sqlite3Realloc(void *pOld, u64 nBytes){
int nOld, nNew, nDiff;
void *pNew;
if( pOld==0 ){
return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
}
if( nBytes<=0 ){
if( nBytes==0 ){
sqlite3_free(pOld); /* IMP: R-31593-10574 */
return 0;
}
@ -537,7 +544,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
/* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
** argument to xRealloc is always a value returned by a prior call to
** xRoundup. */
nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes);
if( nOld==nNew ){
pNew = pOld;
}else if( sqlite3GlobalConfig.bMemstat ){
@ -572,6 +579,13 @@ void *sqlite3Realloc(void *pOld, int nBytes){
** subsystem is initialized prior to invoking sqliteRealloc.
*/
void *sqlite3_realloc(void *pOld, int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
if( n<0 ) n = 0;
return sqlite3Realloc(pOld, n);
}
void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
@ -582,7 +596,7 @@ void *sqlite3_realloc(void *pOld, int n){
/*
** Allocate and zero memory.
*/
void *sqlite3MallocZero(int n){
void *sqlite3MallocZero(u64 n){
void *p = sqlite3Malloc(n);
if( p ){
memset(p, 0, n);
@ -594,7 +608,7 @@ void *sqlite3MallocZero(int n){
** Allocate and zero memory. If the allocation fails, make
** the mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocZero(sqlite3 *db, int n){
void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
void *p = sqlite3DbMallocRaw(db, n);
if( p ){
memset(p, 0, n);
@ -620,7 +634,7 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
void *p;
assert( db==0 || sqlite3_mutex_held(db->mutex) );
assert( db==0 || db->pnBytesFreed==0 );
@ -664,7 +678,7 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
void *pNew = 0;
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
@ -701,7 +715,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
** Attempt to reallocate p. If the reallocation fails, then free p
** and set the mallocFailed flag in the database connection.
*/
void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){
void *pNew;
pNew = sqlite3DbRealloc(db, p, n);
if( !pNew ){
@ -731,7 +745,7 @@ char *sqlite3DbStrDup(sqlite3 *db, const char *z){
}
return zNew;
}
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
char *zNew;
if( z==0 ){
return 0;

View File

@ -188,7 +188,7 @@ static int sqlite3MemSize(void *pPrior){
**
** For this low-level interface, we know that pPrior!=0. Cases where
** pPrior==0 while have been intercepted by higher-level routine and
** redirected to xMalloc. Similarly, we know that nByte>0 becauses
** redirected to xMalloc. Similarly, we know that nByte>0 because
** cases where nByte<=0 will have been intercepted by higher-level
** routines and redirected to xFree.
*/

View File

@ -28,7 +28,7 @@
** 1. All memory allocations sizes are rounded up to a power of 2.
**
** 2. If two adjacent free blocks are the halves of a larger block,
** then the two blocks are coalesed into the single larger block.
** then the two blocks are coalesced into the single larger block.
**
** 3. New memory is allocated from the first available free block.
**

View File

@ -26,7 +26,7 @@ typedef struct FileChunk FileChunk;
**
** The size chosen is a little less than a power of two. That way,
** the FileChunk object will have a size that almost exactly fills
** a power-of-two allocation. This mimimizes wasted space in power-of-two
** a power-of-two allocation. This minimizes wasted space in power-of-two
** memory allocators.
*/
#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))

View File

@ -25,7 +25,7 @@
** Figure out what version of the code to use. The choices are
**
** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
** mutexes implemention cannot be overridden
** mutexes implementation cannot be overridden
** at start-time.
**
** SQLITE_MUTEX_NOOP For single-threaded applications. No

View File

@ -120,7 +120,7 @@
** shared locks begins at SHARED_FIRST.
**
** The same locking strategy and
** byte ranges are used for Unix. This leaves open the possiblity of having
** byte ranges are used for Unix. This leaves open the possibility of having
** clients on win95, winNT, and unix all talking to the same shared file
** and all locking correctly. To do so would require that samba (or whatever
** tool is being used for file sharing) implements locks correctly between

View File

@ -299,6 +299,14 @@ static int randomnessPid = 0;
# endif
#endif
/*
** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek()
** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined.
*/
#ifdef __ANDROID__
# define lseek lseek64
#endif
/*
** Different Unix systems declare open() in different ways. Same use
** open(const char*,int,mode_t). Others use open(const char*,int,...).
@ -631,7 +639,7 @@ static int unixMutexHeld(void) {
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string represetation of the supplied
** binaries. This returns the string representation of the supplied
** integer lock-type.
*/
static const char *azFileLock(int eFileLock){
@ -708,9 +716,22 @@ static int lockTrace(int fd, int op, struct flock *p){
/*
** Retry ftruncate() calls that fail due to EINTR
**
** All calls to ftruncate() within this file should be made through this wrapper.
** On the Android platform, bypassing the logic below could lead to a corrupt
** database.
*/
static int robust_ftruncate(int h, sqlite3_int64 sz){
int rc;
#ifdef __ANDROID__
/* On Android, ftruncate() always uses 32-bit offsets, even if
** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to
** truncate a file to any size larger than 2GiB. Silently ignore any
** such attempts. */
if( sz>(sqlite3_int64)0x7FFFFFFF ){
rc = SQLITE_OK;
}else
#endif
do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
return rc;
}
@ -3098,7 +3119,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
** NB: If you define USE_PREAD or USE_PREAD64, then it might also
** be necessary to define _XOPEN_SOURCE to be 500. This varies from
** one system to another. Since SQLite does not define USE_PREAD
** any any form by default, we will not attempt to define _XOPEN_SOURCE.
** in any form by default, we will not attempt to define _XOPEN_SOURCE.
** See tickets #2741 and #2681.
**
** To avoid stomping the errno value on a failed read the lastErrno value
@ -3595,7 +3616,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
rc = robust_ftruncate(pFile->h, (off_t)nByte);
rc = robust_ftruncate(pFile->h, nByte);
if( rc ){
pFile->lastErrno = errno;
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
@ -3730,7 +3751,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
}
/*
** If *pArg is inititially negative then this is a query. Set *pArg to
** If *pArg is initially negative then this is a query. Set *pArg to
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
**
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
@ -3937,7 +3958,7 @@ static int unixSectorSize(sqlite3_file *id){
** Return the device characteristics for the file.
**
** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
** However, that choice is contraversial since technically the underlying
** However, that choice is controversial since technically the underlying
** file system does not always provide powersafe overwrites. (In other
** words, after a power-loss event, parts of the file that were never
** written might end up being altered.) However, non-PSOW behavior is very,
@ -4909,7 +4930,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
** looks at the filesystem type and tries to guess the best locking
** strategy from that.
**
** For finder-funtion F, two objects are created:
** For finder-function F, two objects are created:
**
** (1) The real finder-function named "FImpt()".
**
@ -5171,7 +5192,7 @@ static const sqlite3_io_methods
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
/*
** An abstract type for a pointer to a IO method finder function:
** An abstract type for a pointer to an IO method finder function:
*/
typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
@ -5485,7 +5506,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
** descriptor on the same path, fail, and return an error to SQLite.
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */
** not searching for a reusable file descriptor are not dire. */
if( 0==osStat(zPath, &sStat) ){
unixInodeInfo *pInode;
@ -5516,7 +5537,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
** written to *pMode. If an IO error occurs, an SQLite error code is
** returned and the value of *pMode is not modified.
**
** In most cases cases, this routine sets *pMode to 0, which will become
** In most cases, this routine sets *pMode to 0, which will become
** an indication to robust_open() to create the file using
** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
** But if the file being opened is a WAL or regular journal file, then
@ -6308,7 +6329,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** proxy path against the values stored in the conch. The conch file is
** stored in the same directory as the database file and the file name
** is patterned after the database file name as ".<databasename>-conch".
** If the conch file does not exist, or it's contents do not match the
** If the conch file does not exist, or its contents do not match the
** host ID and/or proxy path, then the lock is escalated to an exclusive
** lock and the conch file contents is updated with the host ID and proxy
** path and the lock is downgraded to a shared lock again. If the conch
@ -6360,7 +6381,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
** force proxy locking to be used for every database file opened, and 0
** will force automatic proxy locking to be disabled for all database
** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
** files (explicitly calling the SQLITE_SET_LOCKPROXYFILE pragma or
** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
*/

View File

@ -1286,12 +1286,14 @@ void sqlite3_win32_sleep(DWORD milliseconds){
#endif
}
#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
DWORD sqlite3Win32Wait(HANDLE hObject){
DWORD rc;
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
TRUE))==WAIT_IO_COMPLETION ){}
return rc;
}
#endif
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
@ -3126,7 +3128,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
}
/*
** If *pArg is inititially negative then this is a query. Set *pArg to
** If *pArg is initially negative then this is a query. Set *pArg to
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
**
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
@ -4140,7 +4142,7 @@ static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
}else{
/* FIXME: If Windows truly always prevents truncating or deleting a
** file while a mapping is held, then the following winUnmapfile() call
** is unnecessary can can be omitted - potentially improving
** is unnecessary can be omitted - potentially improving
** performance. */
winUnmapfile(pFd);
}

View File

@ -76,12 +76,12 @@
** Definition: Two databases (or the same database at two points it time)
** are said to be "logically equivalent" if they give the same answer to
** all queries. Note in particular the content of freelist leaf
** pages can be changed arbitarily without effecting the logical equivalence
** pages can be changed arbitrarily without affecting the logical equivalence
** of the database.
**
** (7) At any time, if any subset, including the empty set and the total set,
** of the unsynced changes to a rollback journal are removed and the
** journal is rolled back, the resulting database file will be logical
** journal is rolled back, the resulting database file will be logically
** equivalent to the database file at the beginning of the transaction.
**
** (8) When a transaction is rolled back, the xTruncate method of the VFS
@ -378,7 +378,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** The exception is when the database file is unlocked as the pager moves
** from ERROR to OPEN state. At this point there may be a hot-journal file
** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
** transition, by the same pager or any other). If the call to xUnlock()
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
** can confuse the call to xCheckReservedLock() call made later as part
@ -461,7 +461,7 @@ struct PagerSavepoint {
#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
/*
** A open page cache is an instance of struct Pager. A description of
** An open page cache is an instance of struct Pager. A description of
** some of the more important member variables follows:
**
** eState
@ -634,7 +634,7 @@ struct Pager {
/**************************************************************************
** The following block contains those class members that change during
** routine opertion. Class members not in this block are either fixed
** routine operation. Class members not in this block are either fixed
** when the pager is first created or else only change when there is a
** significant mode change (such as changing the page_size, locking_mode,
** or the journal_mode). From another view, these class members describe
@ -2431,7 +2431,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
nMasterPtr = pVfs->mxPathname+1;
zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
if( !zMasterJournal ){
rc = SQLITE_NOMEM;
goto delmaster_out;
@ -2500,7 +2500,7 @@ delmaster_out:
** If the file on disk is currently larger than nPage pages, then use the VFS
** xTruncate() method to truncate it.
**
** Or, it might might be the case that the file on disk is smaller than
** Or, it might be the case that the file on disk is smaller than
** nPage pages. Some operating system implementations can get confused if
** you try to truncate a file to some size that is larger than it
** currently is, so detect this case and write a single zero byte to
@ -2559,7 +2559,7 @@ int sqlite3SectorSize(sqlite3_file *pFile){
/*
** Set the value of the Pager.sectorSize variable for the given
** pager based on the value returned by the xSectorSize method
** of the open database file. The sector size will be used used
** of the open database file. The sector size will be used
** to determine the size and alignment of journal header and
** master journal pointers within created journal files.
**
@ -3621,12 +3621,14 @@ int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
if( rc==SQLITE_OK ){
pager_reset(pPager);
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
if( rc==SQLITE_OK ){
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
}
}
*pPageSize = pPager->pageSize;
@ -3759,7 +3761,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
int rc; /* Return code */
/* Check that this is either a no-op (because the requested lock is
** already held, or one of the transistions that the busy-handler
** already held), or one of the transitions that the busy-handler
** may be invoked during, according to the comment above
** sqlite3PagerSetBusyhandler().
*/
@ -4389,7 +4391,7 @@ static int pagerStress(void *p, PgHdr *pPg){
** a rollback or by user request, respectively.
**
** Spilling is also prohibited when in an error state since that could
** lead to database corruption. In the current implementaton it
** lead to database corruption. In the current implementation it
** is impossible for sqlite3PcacheFetch() to be called with createFlag==3
** while in the error state, hence it is impossible for this routine to
** be called in the error state. Nevertheless, we include a NEVER()
@ -4929,7 +4931,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
*pExists = (first!=0);
}else if( rc==SQLITE_CANTOPEN ){
/* If we cannot open the rollback journal file in order to see if
** its has a zero header, that might be due to an I/O error, or
** it has a zero header, that might be due to an I/O error, or
** it might be due to the race condition described above and in
** ticket #3883. Either way, assume that the journal is hot.
** This might be a false positive. But if it is, then the

View File

@ -45,23 +45,6 @@ struct PCache {
/********************************** Linked List Management ********************/
#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
/*
** Check that the pCache->pSynced variable is set correctly. If it
** is not, either fail an assert or return zero. Otherwise, return
** non-zero. This is only used in debugging builds, as follows:
**
** expensive_assert( pcacheCheckSynced(pCache) );
*/
static int pcacheCheckSynced(PCache *pCache){
PgHdr *p;
for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
}
return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
}
#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
/* Allowed values for second argument to pcacheManageDirtyList() */
#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */
#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */
@ -107,7 +90,6 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
}
pPage->pDirtyNext = 0;
pPage->pDirtyPrev = 0;
expensive_assert( pcacheCheckSynced(p) );
}
if( addRemove & PCACHE_DIRTYLIST_ADD ){
assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
@ -116,18 +98,17 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
if( pPage->pDirtyNext ){
assert( pPage->pDirtyNext->pDirtyPrev==0 );
pPage->pDirtyNext->pDirtyPrev = pPage;
}else if( p->bPurgeable ){
assert( p->eCreate==2 );
p->eCreate = 1;
}else{
p->pDirtyTail = pPage;
if( p->bPurgeable ){
assert( p->eCreate==2 );
p->eCreate = 1;
}
}
p->pDirty = pPage;
if( !p->pDirtyTail ){
p->pDirtyTail = pPage;
}
if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
p->pSynced = pPage;
}
expensive_assert( pcacheCheckSynced(p) );
}
}
@ -304,7 +285,6 @@ int sqlite3PcacheFetchStress(
** cleared), but if that is not possible settle for any other
** unreferenced dirty page.
*/
expensive_assert( pcacheCheckSynced(pCache) );
for(pPg=pCache->pSynced;
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
@ -390,7 +370,7 @@ PgHdr *sqlite3PcacheFetchFinish(
/*
** Decrement the reference count on a page. If the page is clean and the
** reference count drops to 0, then it is made elible for recycling.
** reference count drops to 0, then it is made eligible for recycling.
*/
void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
assert( p->nRef>0 );
@ -399,7 +379,7 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
p->pCache->nRef--;
if( (p->flags&PGHDR_DIRTY)==0 ){
pcacheUnpin(p);
}else{
}else if( p->pDirtyPrev!=0 ){
/* Move the page to the head of the dirty list. */
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
}

View File

@ -13,7 +13,7 @@
** This file implements the default page cache implementation (the
** sqlite3_pcache interface). It also contains part of the implementation
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
** If the default page cache implementation is overriden, then neither of
** If the default page cache implementation is overridden, then neither of
** these two features are available.
*/
@ -25,7 +25,7 @@ typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each others unpinned
** of one or more PCaches that are able to recycle each other's unpinned
** pages when they are under memory pressure. A PGroup is an instance of
** the following object.
**

View File

@ -1422,6 +1422,12 @@ void sqlite3Pragma(
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
#if SQLITE_USER_AUTHENTICATION
if( db->auth.authLevel==UAUTH_User ){
/* Do not allow non-admin users to modify the schema arbitrarily */
mask &= ~(SQLITE_WriteSchema);
}
#endif
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;

View File

@ -328,7 +328,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
sqlite3_xauth xAuth;
xAuth = db->xAuth;
db->xAuth = 0;
#endif
@ -394,6 +394,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int commit_internal = !(db->flags&SQLITE_InternChanges);
assert( sqlite3_mutex_held(db->mutex) );
assert( db->init.busy==0 );
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
@ -409,8 +410,8 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
** schema may contain references to objects in other databases.
*/
#ifndef SQLITE_OMIT_TEMPDB
if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
&& !DbHasProperty(db, 1, DB_SchemaLoaded) ){
assert( db->nDb>1 );
if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 1, pzErrMsg);
if( rc ){
sqlite3ResetOneSchema(db, 1);

View File

@ -904,7 +904,7 @@ char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
/*
** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
** the string and before returnning. This routine is intended to be used
** the string and before returning. This routine is intended to be used
** to modify an existing string. For example:
**
** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);

View File

@ -719,9 +719,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
}
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pDef ){
auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
if( auth!=SQLITE_OK ){
if( auth==SQLITE_DENY ){
@ -732,9 +730,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->op = TK_NULL;
return WRC_Prune;
}
#endif
if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
}
#endif
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
pNC->nErr++;
@ -757,7 +755,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->op2++;
pNC2 = pNC2->pNext;
}
if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
assert( pDef!=0 );
if( pNC2 ){
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
}
pNC->ncFlags |= NC_AllowAgg;
}
/* FIX ME: Compute pExpr->affinity based on the expected return
@ -1118,7 +1122,7 @@ static int resolveOrderGroupBy(
}
/*
** Resolve names in the SELECT statement p and all of its descendents.
** Resolve names in the SELECT statement p and all of its descendants.
*/
static int resolveSelectStep(Walker *pWalker, Select *p){
NameContext *pOuterNC; /* Context that contains this SELECT */
@ -1222,7 +1226,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
assert( (p->selFlags & SF_Aggregate)==0 );
pGroupBy = p->pGroupBy;
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
p->selFlags |= SF_Aggregate;
assert( NC_MinMaxAgg==SF_MinMaxAgg );
p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
@ -1350,7 +1355,7 @@ int sqlite3ResolveExprNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
u8 savedHasAgg;
u16 savedHasAgg;
Walker w;
if( pExpr==0 ) return 0;
@ -1363,8 +1368,8 @@ int sqlite3ResolveExprNames(
pParse->nHeight += pExpr->nHeight;
}
#endif
savedHasAgg = pNC->ncFlags & NC_HasAgg;
pNC->ncFlags &= ~NC_HasAgg;
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
memset(&w, 0, sizeof(w));
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
@ -1379,9 +1384,8 @@ int sqlite3ResolveExprNames(
}
if( pNC->ncFlags & NC_HasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}else if( savedHasAgg ){
pNC->ncFlags |= NC_HasAgg;
}
pNC->ncFlags |= savedHasAgg;
return ExprHasProperty(pExpr, EP_Error);
}

View File

@ -50,7 +50,7 @@
** No INSERTs may occurs after a SMALLEST. An assertion will fail if
** that is attempted.
**
** The cost of an INSERT is roughly constant. (Sometime new memory
** The cost of an INSERT is roughly constant. (Sometimes new memory
** has to be allocated on an INSERT.) The cost of a TEST with a new
** batch number is O(NlogN) where N is the number of elements in the RowSet.
** The cost of a TEST using the same batch number is O(logN). The cost
@ -443,8 +443,8 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
** Check to see if element iRowid was inserted into the rowset as
** part of any insert batch prior to iBatch. Return 1 or 0.
**
** If this is the first test of a new batch and if there exist entires
** on pRowSet->pEntry, then sort those entires into the forest at
** If this is the first test of a new batch and if there exist entries
** on pRowSet->pEntry, then sort those entries into the forest at
** pRowSet->pForest so that they can be tested.
*/
int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){

View File

@ -488,7 +488,7 @@ static void pushOntoSorter(
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
if( nPrefixReg==0 ){
sqlite3VdbeAddOp3(v, OP_Move, regData, regBase+nExpr+bSeq, nData);
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
@ -524,7 +524,7 @@ static void pushOntoSorter(
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
sqlite3VdbeJumpHere(v, addrFirst);
sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat);
sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
sqlite3VdbeJumpHere(v, addrJmp);
}
if( pSort->sortFlags & SORTFLAG_UseSorter ){
@ -1010,7 +1010,7 @@ int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
** then the KeyInfo structure is appropriate for initializing a virtual
** index to implement a DISTINCT test.
**
** Space to hold the KeyInfo structure is obtain from malloc. The calling
** Space to hold the KeyInfo structure is obtained from malloc. The calling
** function is responsible for seeing that this structure is eventually
** freed.
*/
@ -1541,7 +1541,7 @@ static void generateColumnNames(
}
/*
** Given a an expression list (which is really the list of expressions
** Given an expression list (which is really the list of expressions
** that form the result set of a SELECT statement) compute appropriate
** column names for a table that would hold the expression list.
**
@ -1614,7 +1614,7 @@ static int selectColumnsFromExprList(
}
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
** append an integer to the name so that it becomes unique.
*/
nName = sqlite3Strlen30(zName);
for(j=cnt=0; j<i; j++){
@ -3098,7 +3098,7 @@ static void substSelect(
**
** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simpification gives the same result
** The code generated for this simplification gives the same result
** but only has to scan the data once. And because indices might
** exist on the table t1, a complete scan of the data might be
** avoided.
@ -3131,8 +3131,10 @@ static void substSelect(
** (9) The subquery does not use LIMIT or the outer query does not use
** aggregates.
**
** (10) The subquery does not use aggregates or the outer query does not
** use LIMIT.
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
** accidently carried the comment forward until 2014-09-15. Original
** text: "The subquery does not use aggregates or the outer query does not
** use LIMIT."
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
@ -3195,6 +3197,11 @@ static void substSelect(
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
** (24) The subquery is not an aggregate that uses the built-in min() or
** or max() functions. (Without this restriction, a query like:
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
** return the value X for which Y was maximal.)
**
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
@ -3242,7 +3249,7 @@ static int flattenSubquery(
pSubSrc = pSub->pSrc;
assert( pSubSrc );
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
** because they could be computed at compile-time. But when LIMIT and OFFSET
** became arbitrary expressions, we were forced to add restrictions (13)
** and (14). */
@ -3267,8 +3274,14 @@ static int flattenSubquery(
if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
return 0; /* Restriction (21) */
}
if( pSub->selFlags & SF_Recursive ) return 0; /* Restriction (22) */
if( (p->selFlags & SF_Recursive) && pSub->pPrior ) return 0; /* (23) */
testcase( pSub->selFlags & SF_Recursive );
testcase( pSub->selFlags & SF_MinMaxAgg );
if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){
return 0; /* Restrictions (22) and (24) */
}
if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
return 0; /* Restriction (23) */
}
/* OBSOLETE COMMENT 1:
** Restriction 3: If the subquery is a join, make sure the subquery is
@ -3628,7 +3641,7 @@ static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
/*
** The select statement passed as the first argument is an aggregate query.
** The second argment is the associated aggregate-info object. This
** The second argument is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
**
** SELECT count(*) FROM <tbl>
@ -3958,10 +3971,10 @@ static void selectPopWith(Walker *pWalker, Select *p){
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
** statement so that we can freely modify or delete that statement
** without worrying about messing up the presistent representation
** without worrying about messing up the persistent representation
** of the view.
**
** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword
** on joins and the ON and USING clause of joins.
**
** (4) Scan the list of columns in the result set (pEList) looking

View File

@ -33,6 +33,9 @@
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
#if SQLITE_USER_AUTHENTICATION
# include "sqlite3userauth.h"
#endif
#include <ctype.h>
#include <stdarg.h>
@ -3435,6 +3438,71 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif
}else
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
if( nArg<2 ){
fprintf(stderr, "Usage: .user SUBCOMMAND ...\n");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
if( strcmp(azArg[1],"login")==0 ){
if( nArg!=4 ){
fprintf(stderr, "Usage: .user login USER PASSWORD\n");
rc = 1;
goto meta_command_exit;
}
rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
(int)strlen(azArg[3]));
if( rc ){
fprintf(stderr, "Authentication failed for user %s\n", azArg[2]);
rc = 1;
}
}else if( strcmp(azArg[1],"add")==0 ){
if( nArg!=5 ){
fprintf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
rc = 1;
goto meta_command_exit;
}
rc = sqlite3_user_add(p->db, azArg[2],
azArg[3], (int)strlen(azArg[3]),
booleanValue(azArg[4]));
if( rc ){
fprintf(stderr, "User-Add failed: %d\n", rc);
rc = 1;
}
}else if( strcmp(azArg[1],"edit")==0 ){
if( nArg!=5 ){
fprintf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
rc = 1;
goto meta_command_exit;
}
rc = sqlite3_user_change(p->db, azArg[2],
azArg[3], (int)strlen(azArg[3]),
booleanValue(azArg[4]));
if( rc ){
fprintf(stderr, "User-Edit failed: %d\n", rc);
rc = 1;
}
}else if( strcmp(azArg[1],"delete")==0 ){
if( nArg!=3 ){
fprintf(stderr, "Usage: .user delete USER\n");
rc = 1;
goto meta_command_exit;
}
rc = sqlite3_user_delete(p->db, azArg[2]);
if( rc ){
fprintf(stderr, "User-Delete failed: %d\n", rc);
rc = 1;
}
}else{
fprintf(stderr, "Usage: .user login|add|edit|delete ...\n");
rc = 1;
goto meta_command_exit;
}
}else
#endif /* SQLITE_USER_AUTHENTICATION */
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
sqlite3_libversion(), sqlite3_sourceid());

View File

@ -492,6 +492,7 @@ int sqlite3_exec(
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
@ -2094,7 +2095,7 @@ int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
** turns off all busy handlers.
**
** ^(There can only be a single busy handler for a particular
** [database connection] any any given moment. If another busy handler
** [database connection] at any given moment. If another busy handler
** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^
**
@ -2298,6 +2299,10 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
** a NULL pointer.
**
** ^The sqlite3_malloc64(N) routine works just like
** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead
** of a signed 32-bit integer.
**
** ^Calling sqlite3_free() with a pointer previously returned
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
** that it might be reused. ^The sqlite3_free() routine is
@ -2309,24 +2314,38 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** might result if sqlite3_free() is called with a non-NULL pointer that
** was not obtained from sqlite3_malloc() or sqlite3_realloc().
**
** ^(The sqlite3_realloc() interface attempts to resize a
** prior memory allocation to be at least N bytes, where N is the
** second parameter. The memory allocation to be resized is the first
** parameter.)^ ^ If the first parameter to sqlite3_realloc()
** ^The sqlite3_realloc(X,N) interface attempts to resize a
** prior memory allocation X to be at least N bytes.
** ^If the X parameter to sqlite3_realloc(X,N)
** is a NULL pointer then its behavior is identical to calling
** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
** ^If the second parameter to sqlite3_realloc() is zero or
** sqlite3_malloc(N).
** ^If the N parameter to sqlite3_realloc(X,N) is zero or
** negative then the behavior is exactly the same as calling
** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
** ^sqlite3_realloc() returns a pointer to a memory allocation
** of at least N bytes in size or NULL if sufficient memory is unavailable.
** sqlite3_free(X).
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
** of at least N bytes in size or NULL if insufficient memory is available.
** ^If M is the size of the prior allocation, then min(N,M) bytes
** of the prior allocation are copied into the beginning of buffer returned
** by sqlite3_realloc() and the prior allocation is freed.
** ^If sqlite3_realloc() returns NULL, then the prior allocation
** is not freed.
** by sqlite3_realloc(X,N) and the prior allocation is freed.
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
** prior allocation is not freed.
**
** ^The memory returned by sqlite3_malloc() and sqlite3_realloc()
** ^The sqlite3_realloc64(X,N) interfaces works the same as
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
** of a 32-bit signed integer.
**
** ^If X is a memory allocation previously obtained from sqlite3_malloc(),
** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then
** sqlite3_msize(X) returns the size of that memory allocation in bytes.
** ^The value returned by sqlite3_msize(X) might be larger than the number
** of bytes requested when X was allocated. ^If X is a NULL pointer then
** sqlite3_msize(X) returns zero. If X points to something that is not
** the beginning of memory allocation, or if it points to a formerly
** valid memory allocation that has now been freed, then the behavior
** of sqlite3_msize(X) is undefined and possibly harmful.
**
** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
** sqlite3_malloc64(), and sqlite3_realloc64()
** is always aligned to at least an 8 byte boundary, or to a
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
@ -2354,8 +2373,11 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** [sqlite3_free()] or [sqlite3_realloc()].
*/
void *sqlite3_malloc(int);
void *sqlite3_malloc64(sqlite3_uint64);
void *sqlite3_realloc(void*, int);
void *sqlite3_realloc64(void*, sqlite3_uint64);
void sqlite3_free(void*);
sqlite3_uint64 sqlite3_msize(void*);
/*
** CAPI3REF: Memory Allocator Statistics
@ -3364,7 +3386,8 @@ typedef struct sqlite3_context sqlite3_context;
** If the fourth parameter to sqlite3_bind_blob() is negative, then
** the behavior is undefined.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() then that parameter must be the byte offset
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
@ -3383,6 +3406,14 @@ typedef struct sqlite3_context sqlite3_context;
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
** to specify the encoding of the text in the third parameter. If
** the sixth argument to sqlite3_bind_text64() is not how of the
** allowed values shown above, or if the text encoding is different
** from the encoding specified by the sixth parameter, then the behavior
** is undefined.
**
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
** (just an integer to hold its size) while it is being processed.
@ -3403,6 +3434,9 @@ typedef struct sqlite3_context sqlite3_context;
**
** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
** [error code] if anything goes wrong.
** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB
** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or
** [SQLITE_MAX_LENGTH].
** ^[SQLITE_RANGE] is returned if the parameter
** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
**
@ -3410,12 +3444,16 @@ typedef struct sqlite3_context sqlite3_context;
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
@ -4164,7 +4202,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
** object results in undefined behavior.
**
** ^These routines work just like the corresponding [column access functions]
** except that these routines take a single [protected sqlite3_value] object
** except that these routines take a single [protected sqlite3_value] object
** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
**
** ^The sqlite3_value_text16() interface extracts a UTF-16 string
@ -4407,10 +4445,14 @@ typedef void (*sqlite3_destructor_type)(void*);
** of the application-defined function to be NULL.
**
** ^The sqlite3_result_text(), sqlite3_result_text16(),
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
** sqlite3_result_text16le(), and sqlite3_result_text16be()
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.
** ^The sqlite3_result_text64() interface sets the return value of an
** application-defined function to be a text string in an encoding
** specified by the fifth (and last) parameter, which must be one
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
@ -4454,6 +4496,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** the [sqlite3_context] pointer, the results are undefined.
*/
void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*));
void sqlite3_result_double(sqlite3_context*, double);
void sqlite3_result_error(sqlite3_context*, const char*, int);
void sqlite3_result_error16(sqlite3_context*, const void*, int);
@ -4464,6 +4507,8 @@ void sqlite3_result_int(sqlite3_context*, int);
void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
void sqlite3_result_null(sqlite3_context*);
void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
void(*)(void*), unsigned char encoding);
void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
@ -6357,12 +6402,12 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** <dd>This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** <dd>This parameter returns the approximate number of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
** ^The full amount of memory used by the schemas is reported, even if the
@ -6371,7 +6416,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** <dd>This parameter returns the approximate number of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.

View File

@ -28,7 +28,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each others' shared
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
@ -250,11 +250,28 @@ struct sqlite3_api_routines {
const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
};
/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
@ -467,6 +484,19 @@ struct sqlite3_api_routines {
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE

View File

@ -351,7 +351,7 @@
#endif
/*
** Return true (non-zero) if the input is a integer that is too large
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
*/
@ -639,7 +639,7 @@ extern const int sqlite3one;
** all alignment restrictions correct.
**
** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
** underlying malloc() implemention might return us 4-byte aligned
** underlying malloc() implementation might return us 4-byte aligned
** pointers. In that case, only verify 4-byte alignment.
*/
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
@ -988,6 +988,45 @@ struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */
};
#ifdef SQLITE_USER_AUTHENTICATION
/*
** Information held in the "sqlite3" database connection object and used
** to manage user authentication.
*/
typedef struct sqlite3_userauth sqlite3_userauth;
struct sqlite3_userauth {
u8 authLevel; /* Current authentication level */
int nAuthPW; /* Size of the zAuthPW in bytes */
char *zAuthPW; /* Password used to authenticate */
char *zAuthUser; /* User name used to authenticate */
};
/* Allowed values for sqlite3_userauth.authLevel */
#define UAUTH_Unknown 0 /* Authentication not yet checked */
#define UAUTH_Fail 1 /* User authentication failed */
#define UAUTH_User 2 /* Authenticated as a normal user */
#define UAUTH_Admin 3 /* Authenticated as an administrator */
/* Functions used only by user authorization logic */
int sqlite3UserAuthTable(const char*);
int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
void sqlite3UserAuthInit(sqlite3*);
void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
#endif /* SQLITE_USER_AUTHENTICATION */
/*
** typedef for the authorization callback function.
*/
#ifdef SQLITE_USER_AUTHENTICATION
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
const char*, const char*);
#else
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
const char*);
#endif
/*
** Each database connection is an instance of the following structure.
*/
@ -1055,8 +1094,7 @@ struct sqlite3 {
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
sqlite3_xauth xAuth; /* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
@ -1082,7 +1120,6 @@ struct sqlite3 {
i64 nDeferredCons; /* Net deferred constraints this transaction. */
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
@ -1100,6 +1137,9 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
sqlite3_userauth auth; /* User authentication information */
#endif
};
/*
@ -1161,7 +1201,6 @@ struct sqlite3 {
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@ -1248,6 +1287,7 @@ struct FuncDestructor {
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@ -1295,6 +1335,9 @@ struct FuncDestructor {
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
/*
** All current savepoints are stored in a linked list starting at
@ -2217,17 +2260,22 @@ struct NameContext {
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
int nErr; /* Number of errors encountered while resolving names */
u8 ncFlags; /* Zero or more NC_* flags defined below */
u16 ncFlags; /* Zero or more NC_* flags defined below */
};
/*
** Allowed values for the NameContext, ncFlags field.
**
** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and
** SQLITE_FUNC_MINMAX.
**
*/
#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
/*
** An instance of the following structure contains all information
@ -2278,13 +2326,13 @@ struct Select {
#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
/* 0x0040 NOT USED */
#define SF_Compound 0x0040 /* Part of a compound query */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
/* 0x0100 NOT USED */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
#define SF_Compound 0x1000 /* Part of a compound query */
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
/*
@ -2886,8 +2934,8 @@ int sqlite3CantopenError(int);
/*
** FTS4 is really an extension for FTS3. It is enabled using the
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call
** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
@ -2934,15 +2982,15 @@ int sqlite3Strlen30(const char*);
int sqlite3MallocInit(void);
void sqlite3MallocEnd(void);
void *sqlite3Malloc(int);
void *sqlite3MallocZero(int);
void *sqlite3DbMallocZero(sqlite3*, int);
void *sqlite3DbMallocRaw(sqlite3*, int);
void *sqlite3Malloc(u64);
void *sqlite3MallocZero(u64);
void *sqlite3DbMallocZero(sqlite3*, u64);
void *sqlite3DbMallocRaw(sqlite3*, u64);
char *sqlite3DbStrDup(sqlite3*,const char*);
char *sqlite3DbStrNDup(sqlite3*,const char*, int);
void *sqlite3Realloc(void*, int);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
void *sqlite3DbRealloc(sqlite3 *, void *, int);
char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
void *sqlite3Realloc(void*, u64);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
void *sqlite3DbRealloc(sqlite3 *, void *, u64);
void sqlite3DbFree(sqlite3*, void*);
int sqlite3MallocSize(void*);
int sqlite3DbMallocSize(sqlite3*, void*);
@ -3483,7 +3531,7 @@ int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void *sqlite3ParserAlloc(void*(*)(u64));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH

View File

@ -29,10 +29,10 @@
typedef struct TabResult {
char **azResult; /* Accumulated output */
char *zErrMsg; /* Error message text, if an error occurs */
int nAlloc; /* Slots allocated for azResult[] */
int nRow; /* Number of rows in the result */
int nColumn; /* Number of columns in the result */
int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
u32 nAlloc; /* Slots allocated for azResult[] */
u32 nRow; /* Number of rows in the result */
u32 nColumn; /* Number of columns in the result */
u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
int rc; /* Return code from sqlite3_exec() */
} TabResult;
@ -58,7 +58,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
if( p->nData + need > p->nAlloc ){
char **azNew;
p->nAlloc = p->nAlloc*2 + need;
azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
}
@ -182,7 +182,7 @@ int sqlite3_get_table(
** This routine frees the space the sqlite3_get_table() malloced.
*/
void sqlite3_free_table(
char **azResult /* Result returned from from sqlite3_get_table() */
char **azResult /* Result returned from sqlite3_get_table() */
){
if( azResult ){
int i, n;

View File

@ -760,7 +760,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
/* If there are arguments to the function, make a shallow copy of the
** script object, lappend the arguments, then evaluate the copy.
**
** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated.
** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
** The new Tcl_Obj contains pointers to the original list elements.
** That way, when Tcl_EvalObjv() is run and shimmers the first element
** of the list to tclCmdNameType, that alternate representation will
@ -872,6 +872,9 @@ static int auth_callback(
const char *zArg2,
const char *zArg3,
const char *zArg4
#ifdef SQLITE_USER_AUTHENTICATION
,const char *zArg5
#endif
){
const char *zCode;
Tcl_DString str;
@ -924,6 +927,9 @@ static int auth_callback(
Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
#ifdef SQLITE_USER_AUTHENTICATION
Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
#endif
rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
@ -1700,8 +1706,11 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
pDb->zAuth = 0;
}
if( pDb->zAuth ){
typedef int (*sqlite3_auth_cb)(
void*,int,const char*,const char*,
const char*,const char*);
pDb->interp = interp;
sqlite3_set_authorizer(pDb->db, auth_callback, pDb);
sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
}else{
sqlite3_set_authorizer(pDb->db, 0, 0);
}

View File

@ -2605,7 +2605,7 @@ static int test_bind(
** SQLite selected to call. The TCL test script implements the
** "test_collate" proc.
**
** Note that this will only work with one intepreter at a time, as the
** Note that this will only work with one interpreter at a time, as the
** interp pointer to use when evaluating the TCL script is stored in
** pTestCollateInterp.
*/
@ -3758,7 +3758,7 @@ static int test_prepare_v2(
** Usage: sqlite3_prepare_tkt3134 DB
**
** Generate a prepared statement for a zero-byte string as a test
** for ticket #3134. The string should be preceeded by a zero byte.
** for ticket #3134. The string should be preceded by a zero byte.
*/
static int test_prepare_tkt3134(
void * clientData,
@ -6561,6 +6561,132 @@ static int testTransactionRestore(
return TCL_OK;
}
#ifdef SQLITE_USER_AUTHENTICATION
#include "sqlite3userauth.h"
/*
** tclcmd: sqlite3_user_authenticate DB USERNAME PASSWORD
*/
static int test_user_authenticate(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
char *zUser = 0;
char *zPasswd = 0;
int nPasswd = 0;
sqlite3 *db;
int rc;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
zUser = Tcl_GetString(objv[2]);
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
#endif /* SQLITE_USER_AUTHENTICATION */
#ifdef SQLITE_USER_AUTHENTICATION
/*
** tclcmd: sqlite3_user_add DB USERNAME PASSWORD ISADMIN
*/
static int test_user_add(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
char *zUser = 0;
char *zPasswd = 0;
int nPasswd = 0;
int isAdmin = 0;
sqlite3 *db;
int rc;
if( objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
zUser = Tcl_GetString(objv[2]);
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
rc = sqlite3_user_add(db, zUser, zPasswd, nPasswd, isAdmin);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
#endif /* SQLITE_USER_AUTHENTICATION */
#ifdef SQLITE_USER_AUTHENTICATION
/*
** tclcmd: sqlite3_user_change DB USERNAME PASSWORD ISADMIN
*/
static int test_user_change(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
char *zUser = 0;
char *zPasswd = 0;
int nPasswd = 0;
int isAdmin = 0;
sqlite3 *db;
int rc;
if( objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME PASSWORD ISADMIN");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
zUser = Tcl_GetString(objv[2]);
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
Tcl_GetBooleanFromObj(interp, objv[4], &isAdmin);
rc = sqlite3_user_change(db, zUser, zPasswd, nPasswd, isAdmin);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
#endif /* SQLITE_USER_AUTHENTICATION */
#ifdef SQLITE_USER_AUTHENTICATION
/*
** tclcmd: sqlite3_user_delete DB USERNAME
*/
static int test_user_delete(
ClientData clientData, /* Unused */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
char *zUser = 0;
sqlite3 *db;
int rc;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB USERNAME");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
zUser = Tcl_GetString(objv[2]);
rc = sqlite3_user_delete(db, zUser);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
#endif /* SQLITE_USER_AUTHENTICATION */
/*
** Register commands with the TCL interpreter.
*/
@ -6800,7 +6926,14 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sorter_test_sort4_helper", sorter_test_sort4_helper },
{ "sqlite3_transaction_save", testTransactionSave },
{ "sqlite3_transaction_restore", testTransactionRestore },
#ifdef SQLITE_USER_AUTHENTICATION
{ "sqlite3_user_authenticate", test_user_authenticate, 0 },
{ "sqlite3_user_add", test_user_add, 0 },
{ "sqlite3_user_change", test_user_change, 0 },
{ "sqlite3_user_delete", test_user_delete, 0 },
#endif
};
static int bitmask_size = sizeof(Bitmask)*8;
int i;
extern int sqlite3_sync_count, sqlite3_fullsync_count;

View File

@ -603,6 +603,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_USER_AUTHENTICATION
Tcl_SetVar2(interp, "sqlite_options", "userauth", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "userauth", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_MULTIPLEX_EXT_OVWR
Tcl_SetVar2(interp, "sqlite_options", "multiplex_ext_overwrite", "1", TCL_GLOBAL_ONLY);
#else

View File

@ -37,13 +37,13 @@ struct sqlite3_intarray {
typedef struct intarray_vtab intarray_vtab;
typedef struct intarray_cursor intarray_cursor;
/* A intarray table object */
/* An intarray table object */
struct intarray_vtab {
sqlite3_vtab base; /* Base class */
sqlite3_intarray *pContent; /* Content of the integer array */
};
/* A intarray cursor object */
/* An intarray cursor object */
struct intarray_cursor {
sqlite3_vtab_cursor base; /* Base class */
int i; /* Current cursor position */

View File

@ -696,6 +696,12 @@ static int test_memdebug_pending(
return TCL_OK;
}
/*
** The following global variable keeps track of the number of tests
** that have run. This variable is only useful when running in the
** debugger.
*/
static int sqlite3_memdebug_title_count = 0;
/*
** Usage: sqlite3_memdebug_settitle TITLE
@ -713,6 +719,7 @@ static int test_memdebug_settitle(
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3_memdebug_title_count++;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
return TCL_ERROR;
@ -880,7 +887,7 @@ static int test_memdebug_log(
**
** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
** The buffer is static and is of limited size. N might be
** adjusted downward as needed to accomodate the requested size.
** adjusted downward as needed to accommodate the requested size.
** The revised value of N is returned.
**
** A negative SIZE causes the buffer pointer to be NULL.
@ -920,7 +927,7 @@ static int test_config_scratch(
**
** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
** The buffer is static and is of limited size. N might be
** adjusted downward as needed to accomodate the requested size.
** adjusted downward as needed to accommodate the requested size.
** The revised value of N is returned.
**
** A negative SIZE causes the buffer pointer to be NULL.

View File

@ -189,7 +189,7 @@ static int schemaNext(sqlite3_vtab_cursor *cur){
/* Set zSql to the SQL to pull the list of tables from the
** sqlite_master (or sqlite_temp_master) table of the database
** identfied by the row pointed to by the SQL statement pCur->pDbList
** identified by the row pointed to by the SQL statement pCur->pDbList
** (iterating through a "PRAGMA database_list;" statement).
*/
if( sqlite3_column_int(pCur->pDbList, 0)==1 ){

View File

@ -77,7 +77,7 @@ const unsigned char ebcdicToAscii[] = {
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
** middle of identfiers. But many SQL implementations do.
** middle of identifiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
@ -398,7 +398,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
pParse->zTail = zSql;
i = 0;
assert( pzErrMsg!=0 );
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc);
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
if( pEngine==0 ){
db->mallocFailed = 1;
return SQLITE_NOMEM;

View File

@ -127,7 +127,7 @@ void sqlite3BeginTrigger(
** ^^^^^^^^
**
** To maintain backwards compatibility, ignore the database
** name on pTableName if we are reparsing our of SQLITE_MASTER.
** name on pTableName if we are reparsing out of SQLITE_MASTER.
*/
if( db->init.busy && iDb!=1 ){
sqlite3DbFree(db, pTableName->a[0].zDatabase);

View File

@ -327,7 +327,7 @@ void sqlite3Update(
}
/* If we are trying to update a view, realize that view into
** a ephemeral table.
** an ephemeral table.
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
@ -488,7 +488,7 @@ void sqlite3Update(
}
/* Populate the array of registers beginning at regNew with the new
** row data. This array is used to check constaints, create the new
** row data. This array is used to check constants, create the new
** table and index records, and as the values for any new.* references
** made by triggers.
**
@ -668,7 +668,7 @@ update_cleanup:
return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** thely may interfere with compilation of other functions in this file
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation). */
#ifdef isView
#undef isView
@ -681,7 +681,7 @@ update_cleanup:
/*
** Generate code for an UPDATE of a virtual table.
**
** The strategy is that we create an ephemerial table that contains
** The strategy is that we create an ephemeral table that contains
** for each row to be changed:
**
** (A) The original rowid of that row.
@ -689,7 +689,7 @@ update_cleanup:
** (C) The content of every column in the row.
**
** Then we loop over this ephemeral table and for each row in
** the ephermeral table call VUpdate.
** the ephemeral table call VUpdate.
**
** When finished, drop the ephemeral table.
**

View File

@ -204,7 +204,7 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** occur.
**
** 2002-Feb-14: This routine is extended to remove MS-Access style
** brackets from around identifers. For example: "[a-b-c]" becomes
** brackets from around identifiers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
int sqlite3Dequote(char *z){

View File

@ -87,7 +87,7 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
** step (3) requires additional temporary disk space approximately equal
** to the size of the original database for the rollback journal.
** Hence, temporary disk space that is approximately 2x the size of the
** orginal database is required. Every page of the database is written
** original database is required. Every page of the database is written
** approximately 3 times: Once for step (2) and twice for step (3).
** Two writes per page are required in step (3) because the original
** database content must be written into the rollback journal prior to

View File

@ -2560,7 +2560,7 @@ case OP_MakeRecord: {
** ------------------------------------------------------------------------
**
** Data(0) is taken from register P1. Data(1) comes from register P1+1
** and so froth.
** and so forth.
**
** Each type field is a varint representing the serial type of the
** corresponding data element (see sqlite3VdbeSerialType()). The
@ -3547,7 +3547,7 @@ case OP_SeekGT: { /* jump, in3 */
if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so covert it. */
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & (MEM_Int|MEM_Real))==0 ){
applyNumericAffinity(pIn3, 0);

View File

@ -238,7 +238,7 @@ struct Mem {
#endif
/*
** Each auxilliary data pointer stored by a user defined function
** Each auxiliary data pointer stored by a user defined function
** implementation calling sqlite3_set_auxdata() is stored in an instance
** of this structure. All such structures associated with a single VM
** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
@ -253,7 +253,7 @@ struct AuxData {
};
/*
** The "context" argument for a installable function. A pointer to an
** The "context" argument for an installable function. A pointer to an
** instance of this structure is the first argument to the routines used
** implement the SQL functions.
**

View File

@ -212,9 +212,12 @@ int sqlite3_value_type(sqlite3_value* pVal){
** The following routines are used by user-defined functions to specify
** the function result.
**
** The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the
** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
** result as a string or blob but if the string or blob is too large, it
** then sets the error code to SQLITE_TOOBIG
**
** The invokeValueDestructor(P,X) routine invokes destructor function X()
** on value P is not going to be used and need to be destroyed.
*/
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
@ -227,6 +230,22 @@ static void setResultStrOrError(
sqlite3_result_error_toobig(pCtx);
}
}
static int invokeValueDestructor(
const void *p, /* Value to destroy */
void (*xDel)(void*), /* The destructor */
sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */
){
assert( xDel!=SQLITE_DYNAMIC );
if( xDel==0 ){
/* noop */
}else if( xDel==SQLITE_TRANSIENT ){
/* noop */
}else{
xDel((void*)p);
}
if( pCtx ) sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
void sqlite3_result_blob(
sqlite3_context *pCtx,
const void *z,
@ -237,6 +256,20 @@ void sqlite3_result_blob(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, 0, xDel);
}
void sqlite3_result_blob64(
sqlite3_context *pCtx,
const void *z,
sqlite3_uint64 n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, 0, xDel);
}
}
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
@ -276,6 +309,21 @@ void sqlite3_result_text(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
}
void sqlite3_result_text64(
sqlite3_context *pCtx,
const char *z,
sqlite3_uint64 n,
void (*xDel)(void *),
unsigned char enc
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, enc, xDel);
}
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_text16(
sqlite3_context *pCtx,
@ -645,7 +693,7 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
}
/*
** Return the auxilary data pointer, if any, for the iArg'th argument to
** Return the auxiliary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
@ -660,7 +708,7 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
}
/*
** Set the auxilary data pointer and delete function, for the iArg'th
** Set the auxiliary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
@ -706,7 +754,7 @@ failed:
#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return the number of times the Step function of a aggregate has been
** Return the number of times the Step function of an aggregate has been
** called.
**
** This function is deprecated. Do not use it for new code. It is
@ -976,7 +1024,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
return columnName(
@ -992,7 +1040,7 @@ const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
return columnName(
@ -1008,7 +1056,7 @@ const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
** anything else which is not an unambiguous reference to a database column.
*/
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
return columnName(
@ -1125,6 +1173,20 @@ int sqlite3_bind_blob(
){
return bindText(pStmt, i, zData, nData, xDel, 0);
}
int sqlite3_bind_blob64(
sqlite3_stmt *pStmt,
int i,
const void *zData,
sqlite3_uint64 nData,
void (*xDel)(void*)
){
assert( xDel!=SQLITE_DYNAMIC );
if( nData>0x7fffffff ){
return invokeValueDestructor(zData, xDel, 0);
}else{
return bindText(pStmt, i, zData, nData, xDel, 0);
}
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
@ -1166,6 +1228,22 @@ int sqlite3_bind_text(
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
int sqlite3_bind_text64(
sqlite3_stmt *pStmt,
int i,
const char *zData,
sqlite3_uint64 nData,
void (*xDel)(void*),
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
if( nData>0x7fffffff ){
return invokeValueDestructor(zData, xDel, 0);
}else{
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
return bindText(pStmt, i, zData, nData, xDel, enc);
}
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
sqlite3_stmt *pStmt,
@ -1288,7 +1366,7 @@ int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
** Deprecated external interface. Internal/core SQLite code
** should call sqlite3TransferBindings.
**
** Is is misuse to call this routine with statements from different
** It is misuse to call this routine with statements from different
** database connections. But as this is a deprecated interface, we
** will not bother to check for that condition.
**

View File

@ -895,7 +895,7 @@ void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
** is readable but not writable, though it is cast to a writable value.
** The return of a dummy opcode allows the call to continue functioning
** after a OOM fault without having to check to see if the return from
** after an OOM fault without having to check to see if the return from
** this routine is a valid pointer. But because the dummy.opcode is 0,
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
@ -1610,9 +1610,9 @@ void sqlite3VdbeRewind(Vdbe *p){
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
** This function may be called exact once on a each virtual machine.
** This function may be called exactly once on each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
** to run. After this routine is called, futher calls to
** to run. After this routine is called, further calls to
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
@ -1990,7 +1990,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* The complex case - There is a multi-file write-transaction active.
** This requires a master journal file to ensure the transaction is
** committed atomicly.
** committed atomically.
*/
#ifndef SQLITE_OMIT_DISKIO
else{
@ -2638,7 +2638,7 @@ int sqlite3VdbeFinalize(Vdbe *p){
** from left to right), or
**
** * the corresponding bit in argument mask is clear (where the first
** function parameter corrsponds to bit 0 etc.).
** function parameter corresponds to bit 0 etc.).
*/
void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
AuxData **pp = &pVdbe->pAuxData;
@ -2742,7 +2742,7 @@ static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
** Something has moved cursor "p" out of place. Maybe the row it was
** pointed to was deleted out from under it. Or maybe the btree was
** rebalanced. Whatever the cause, try to restore "p" to the place it
** is suppose to be pointing. If the row was deleted out from under the
** is supposed to be pointing. If the row was deleted out from under the
** cursor, set the cursor to point to a NULL row.
*/
static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
@ -3267,7 +3267,7 @@ static int vdbeRecordCompareDebug(
assert( mem1.zMalloc==0 );
/* rc==0 here means that one of the keys ran out of fields and
** all the fields up to that point were equal. Return the the default_rc
** all the fields up to that point were equal. Return the default_rc
** value. */
rc = pPKey2->default_rc;
@ -3458,7 +3458,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
** or positive integer if key1 is less than, equal to or
** greater than key2. The {nKey1, pKey1} key must be a blob
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
** created by the OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
** sqlite3VdbeParseRecord.
**
@ -3648,7 +3648,7 @@ int sqlite3VdbeRecordCompare(
assert( mem1.zMalloc==0 );
/* rc==0 here means that one or both of the keys ran out of fields and
** all the fields up to that point were equal. Return the the default_rc
** all the fields up to that point were equal. Return the default_rc
** value. */
assert( CORRUPT_DB
|| vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)

View File

@ -37,7 +37,7 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
**
** (1) Memory in Mem.zMalloc and managed by the Mem object
** (2) Memory to be freed using Mem.xDel
** (3) An ephermal string or blob
** (3) An ephemeral string or blob
** (4) A static string or blob
*/
if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
@ -240,7 +240,7 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
** used for converting values to text for returning to the user (i.e. via
** sqlite3_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the later is an internal programming error.
** user and the latter is an internal programming error.
*/
int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
int fg = pMem->flags;
@ -405,7 +405,7 @@ static i64 doubleToInt64(double r){
** If pMem is an integer, then the value is exact. If pMem is
** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into a integer and return that. If pMem represents an
** it into an integer and return that. If pMem represents an
** an SQL-NULL value, return 0.
**
** If pMem represents a string value, its encoding might be changed.
@ -697,7 +697,7 @@ int sqlite3VdbeMemTooBig(Mem *p){
#ifdef SQLITE_DEBUG
/*
** This routine prepares a memory cell for modication by breaking
** This routine prepares a memory cell for modification by breaking
** its link to a shallow copy and by marking any current shallow
** copies of this cell as invalid.
**

View File

@ -2061,7 +2061,7 @@ static void *vdbePmaReaderBgInit(void *pCtx){
/*
** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK)
** on the the PmaReader object passed as the first argument.
** on the PmaReader object passed as the first argument.
**
** This call will initialize the various fields of the pReadr->pIncr
** structure and, if it is a multi-threaded IncrMerger, launch a

View File

@ -64,7 +64,7 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
** ALGORITHM: Scan the input string looking for host parameters in any of
** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within
** string literals, quoted identifier names, and comments. For text forms,
** the host parameter index is found by scanning the perpared
** the host parameter index is found by scanning the prepared
** statement for the corresponding OP_Variable opcode. Once the host
** parameter index is known, locate the value in p->aVar[]. Then render
** the value as a literal in place of the host parameter name.

View File

@ -574,7 +574,7 @@ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
** The argument to this macro must be of type u32. On a little-endian
** architecture, it returns the u32 value that results from interpreting
** the 4 bytes as a big-endian value. On a big-endian architecture, it
** returns the value that would be produced by intepreting the 4 bytes
** returns the value that would be produced by interpreting the 4 bytes
** of the input value as a little-endian integer.
*/
#define BYTESWAP32(x) ( \
@ -988,7 +988,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
/* If this is the first entry to be added to this hash-table, zero the
** entire hash table and aPgno[] array before proceding.
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
@ -1661,7 +1661,7 @@ static int walPagesize(Wal *pWal){
** database file.
**
** This routine uses and updates the nBackfill field of the wal-index header.
** This is the only routine tha will increase the value of nBackfill.
** This is the only routine that will increase the value of nBackfill.
** (A WAL reset or recovery will revert nBackfill to zero, but not increase
** its value.)
**
@ -1967,7 +1967,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
** wal-index from the WAL before returning.
**
** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
** changed by this opertion. If pWal->hdr is unchanged, set *pChanged
** changed by this operation. If pWal->hdr is unchanged, set *pChanged
** to 0.
**
** If the wal-index header is successfully read, return SQLITE_OK.
@ -2171,7 +2171,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** may have been appended to the log before READ_LOCK(0) was obtained.
** When holding READ_LOCK(0), the reader ignores the entire log file,
** which implies that the database file contains a trustworthy
** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
** happening, this is usually correct.
**
** However, if frames have been appended to the log (or if the log
@ -2839,7 +2839,7 @@ int sqlite3WalFrames(
**
** Padding and syncing only occur if this set of frames complete a
** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL
** or synchonous==OFF, then no padding or syncing are needed.
** or synchronous==OFF, then no padding or syncing are needed.
**
** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not
** needed and only the sync is done. If padding is needed, then the

View File

@ -19,7 +19,7 @@
/*
** Walk an expression tree. Invoke the callback once for each node
** of the expression, while decending. (In other words, the callback
** of the expression, while descending. (In other words, the callback
** is invoked before visiting children.)
**
** The return value from the callback should be one of the WRC_*

View File

@ -701,7 +701,7 @@ static int isLikeOrGlob(
** value of the variable means there is no need to invoke the LIKE
** function, then no OP_Variable will be added to the program.
** This causes problems for the sqlite3_bind_parameter_name()
** API. To workaround them, add a dummy OP_Variable here.
** API. To work around them, add a dummy OP_Variable here.
*/
int r1 = sqlite3GetTempReg(pParse);
sqlite3ExprCodeTarget(pParse, pRight, r1);
@ -821,7 +821,7 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
** appropriate for indexing exist.
**
** All examples A through E above satisfy case 2. But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** also satisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
**
@ -979,7 +979,7 @@ static void exprAnalyzeOrTerm(
}
if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceeded
** chngToIN set but t1 is not. This term will be either preceded
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
@ -1390,7 +1390,7 @@ static void exprAnalyze(
}
/*
** This function searches pList for a entry that matches the iCol-th column
** This function searches pList for an entry that matches the iCol-th column
** of index pIdx.
**
** If such an expression is found, its index in pList->a[] is returned. If
@ -2140,7 +2140,7 @@ static int whereRangeSkipScanEst(
** number of rows that the index scan is expected to visit without
** considering the range constraints. If nEq is 0, this is the number of
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
** to account for the range contraints pLower and pUpper.
** to account for the range constraints pLower and pUpper.
**
** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be
** used, a single range inequality reduces the search space by a factor of 4.
@ -3417,7 +3417,7 @@ static Bitmask codeOneLoopStart(
** B: <after the loop>
**
** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
** use an ephermeral index instead of a RowSet to record the primary
** use an ephemeral index instead of a RowSet to record the primary
** keys of the rows we have already seen.
**
*/
@ -3468,7 +3468,7 @@ static Bitmask codeOneLoopStart(
}
/* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset. Or, create an ephermeral index
** equivalent to an empty rowset. Or, create an ephemeral index
** capable of holding primary keys in the case of a WITHOUT ROWID.
**
** Also initialize regReturn to contain the address of the instruction
@ -4221,14 +4221,16 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
** the number of output rows by a factor of 10 and each additional term
** reduces the number of output rows by sqrt(2).
*/
static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
static void whereLoopOutputAdjust(
WhereClause *pWC, /* The WHERE clause */
WhereLoop *pLoop, /* The loop to adjust downward */
LogEst nRow /* Number of rows in the entire table */
){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j;
int nEq = 0; /* Number of = constraints not within likely()/unlikely() */
if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
return;
}
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
@ -4240,9 +4242,21 @@ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ){
pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1);
if( pTerm->truthProb<=0 ){
pLoop->nOut += pTerm->truthProb;
}else{
pLoop->nOut--;
if( pTerm->eOperator&WO_EQ ) nEq++;
}
}
}
/* TUNING: If there is at least one equality constraint in the WHERE
** clause that does not have a likelihood() explicitly assigned to it
** then do not let the estimated number of output rows exceed half
** the number of rows in the table. */
if( nEq && pLoop->nOut>nRow-10 ){
pLoop->nOut = nRow - 10;
}
}
/*
@ -4288,6 +4302,7 @@ static int whereLoopAddBtreeIndex(
LogEst saved_nOut; /* Original value of pNew->nOut */
int iCol; /* Index of the column in the table */
int rc = SQLITE_OK; /* Return code */
LogEst rSize; /* Number of rows in the table */
LogEst rLogSize; /* Logarithm of table size */
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
@ -4317,7 +4332,8 @@ static int whereLoopAddBtreeIndex(
saved_prereq = pNew->prereq;
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(pProbe->aiRowLogEst[0]);
rSize = pProbe->aiRowLogEst[0];
rLogSize = estLog(rSize);
/* Consider using a skip-scan if there are no WHERE clause constraints
** available for the left-most terms of the index, and if the average
@ -4494,7 +4510,7 @@ static int whereLoopAddBtreeIndex(
nOutUnadjusted = pNew->nOut;
pNew->rRun += nInMul + nIn;
pNew->nOut += nInMul + nIn;
whereLoopOutputAdjust(pBuilder->pWC, pNew);
whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
@ -4707,7 +4723,7 @@ static int whereLoopAddBtree(
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
/* TUNING: Each index lookup yields 20 rows in the table. This
** is more than the usual guess of 10 rows, since we have no way
** of knowning how selective the index will ultimately be. It would
** of knowing how selective the index will ultimately be. It would
** not be unreasonable to make this value much larger. */
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
@ -4748,7 +4764,7 @@ static int whereLoopAddBtree(
/* TUNING: Cost of full table scan is (N*3.0). */
pNew->rRun = rSize + 16;
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew);
whereLoopOutputAdjust(pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@ -4784,7 +4800,7 @@ static int whereLoopAddBtree(
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew);
whereLoopOutputAdjust(pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@ -5137,7 +5153,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
** strict. With GROUP BY and DISTINCT the only requirement is that
** equivalent rows appear immediately adjacent to one another. GROUP BY
** and DISTINCT do not require rows to appear in any particular order as long
** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT
** as equivalent rows are grouped together. Thus for GROUP BY and DISTINCT
** the pOrderBy terms can be matched in any order. With ORDER BY, the
** pOrderBy terms must be matched in strict left-to-right order.
*/

View File

@ -176,7 +176,7 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int);
** 1. Then using those as a basis to compute the N best WherePath objects
** of length 2. And so forth until the length of WherePaths equals the
** number of nodes in the FROM clause. The best (lowest cost) WherePath
** at the end is the choosen query plan.
** at the end is the chosen query plan.
*/
struct WherePath {
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */

View File

@ -156,8 +156,14 @@ do_test aggnested-3.2 {
(SELECT value1 as xyz, max(x1) AS pqr
FROM t1
GROUP BY id1);
SELECT
(SELECT sum(value2<>xyz) FROM t2)
FROM
(SELECT value1 as xyz, max(x1) AS pqr
FROM t1
GROUP BY id1);
}
} {0}
} {1 0}
do_test aggnested-3.3 {
db eval {
DROP TABLE IF EXISTS t1;

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ do_test auth2-1.1 {
INSERT INTO t1 VALUES(1,2,3);
}
set ::flist {}
proc auth {code arg1 arg2 arg3 arg4} {
proc auth {code arg1 arg2 arg3 arg4 args} {
if {$code=="SQLITE_FUNCTION"} {
lappend ::flist $arg2
if {$arg2=="max"} {
@ -80,7 +80,7 @@ sqlite3 db test.db
sqlite3 db2 test.db
proc auth {args} {
global authargs
append authargs $args\n
append authargs [lrange $args 0 4]\n
return SQLITE_OK
}
db auth auth

View File

@ -30,7 +30,7 @@ if {[catch {db auth {}} msg]} {
db cache size 0
db authorizer ::auth
proc auth {code arg1 arg2 arg3 arg4} {
proc auth {code arg1 arg2 arg3 arg4 args} {
if {$code=="SQLITE_DELETE"} {
return $::authcode
}

View File

@ -1554,7 +1554,7 @@ ifcapable auth {
}
} {}
proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK}
db auth auth
# An insert on the parent table must read the child key of any deferred

View File

@ -170,7 +170,7 @@ foreach {q r} [array get fts4aa_res] {
# Should get the same search results when an authorizer prevents
# all PRAGMA statements.
#
proc no_pragma_auth {code arg1 arg2 arg3 arg4} {
proc no_pragma_auth {code arg1 arg2 arg3 arg4 args} {
if {$code=="SQLITE_PRAGMA"} {return SQLITE_DENY}
return SQLITE_OK;
}

View File

@ -56,14 +56,16 @@ do_test minmax4-1.5 {
do_test minmax4-1.6 {
db eval {
SELECT p, min(q) FROM t1;
SELECT p FROM (SELECT p, min(q) FROM t1);
}
} {1 2}
} {1 2 1}
do_test minmax4-1.7 {
db eval {
INSERT INTO t1 VALUES(5,0);
SELECT p, max(q) FROM t1;
SELECT p FROM (SELECT max(q), p FROM t1);
}
} {3 4}
} {3 4 3}
do_test minmax4-1.8 {
db eval {
SELECT p, min(q) FROM t1;
@ -73,8 +75,9 @@ do_test minmax4-1.9 {
db eval {
INSERT INTO t1 VALUES(6,1);
SELECT p, max(q) FROM t1;
SELECT p FROM (SELECT max(q), p FROM t1);
}
} {3 4}
} {3 4 3}
do_test minmax4-1.10 {
db eval {
SELECT p, min(q) FROM t1;

View File

@ -561,7 +561,7 @@ do_test savepoint-8-2 {
#
ifcapable auth {
proc auth {args} {
eval lappend ::authdata $args
eval lappend ::authdata [lrange $args 0 4]
return SQLITE_OK
}
db auth auth
@ -583,7 +583,7 @@ ifcapable auth {
} {SQLITE_SAVEPOINT RELEASE sp1 {} {}}
proc auth {args} {
eval lappend ::authdata $args
eval lappend ::authdata [lrange $args 0 4]
return SQLITE_DENY
}
db auth auth

257
test/userauth01.test Normal file
View File

@ -0,0 +1,257 @@
# 2014-09-10
#
# 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 tests of the SQLITE_USER_AUTHENTICATION extension.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix userauth01
ifcapable !userauth {
finish_test
return
}
# Create a no-authentication-required database
#
do_execsql_test userauth01-1.0 {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1),(2.5),('three'),(x'4444'),(NULL);
SELECT quote(x) FROM t1 ORDER BY x;
SELECT name FROM sqlite_master;
} {NULL 1 2.5 'three' X'4444' t1}
# Calling sqlite3_user_authenticate() on a no-authentication-required
# database connection is a harmless no-op.
#
do_test userauth01-1.1 {
sqlite3_user_authenticate db alice pw-4-alice
execsql {
SELECT quote(x) FROM t1 ORDER BY x;
SELECT name FROM sqlite_master;
}
} {NULL 1 2.5 'three' X'4444' t1}
# If sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
# database and A is false, then the call fails with an SQLITE_AUTH error.
#
do_test userauth01-1.2 {
sqlite3_user_add db bob pw-4-bob 0
} {SQLITE_AUTH}
do_test userauth01-1.3 {
execsql {
SELECT quote(x) FROM t1 ORDER BY x;
SELECT name FROM sqlite_master;
}
} {NULL 1 2.5 'three' X'4444' t1}
# When called on a no-authentication-required
# database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
# converts the database into an authentication-required database and
# logs the database connection D in using user U with password P,N.
#
do_test userauth01-1.4 {
sqlite3_user_add db alice pw-4-alice 1
} {SQLITE_OK}
do_test userauth01-1.5 {
execsql {
SELECT quote(x) FROM t1 ORDER BY x;
SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
SELECT name FROM sqlite_master ORDER BY name;
}
} {NULL 1 2.5 'three' X'4444' alice 1 sqlite_user t1}
# The sqlite3_user_add() interface can be used (by an admin user only)
# to create a new user.
#
do_test userauth01-1.6 {
sqlite3_user_add db bob pw-4-bob 0
sqlite3_user_add db cindy pw-4-cindy 0
sqlite3_user_add db david pw-4-david 0
execsql {
SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
}
} {alice 1 bob 0 cindy 0 david 0}
# The sqlite_user table is inaccessible (unreadable and unwriteable) to
# non-admin users and is read-only for admin users. However, if the same
#
do_test userauth01-1.7 {
sqlite3 db2 test.db
sqlite3_user_authenticate db2 cindy pw-4-cindy
db2 eval {
SELECT quote(x) FROM t1 ORDER BY x;
SELECT name FROM sqlite_master ORDER BY name;
}
} {NULL 1 2.5 'three' X'4444' sqlite_user t1}
do_test userauth01-1.8 {
catchsql {
SELECT uname, isadmin FROM sqlite_user ORDER BY uname;
} db2
} {1 {no such table: sqlite_user}}
# Any user can change their own password.
#
do_test userauth01-1.9 {
sqlite3_user_change db2 cindy xyzzy-cindy 0
} {SQLITE_OK}
do_test userauth01-1.10 {
sqlite3_user_authenticate db2 cindy pw-4-cindy
} {SQLITE_AUTH}
do_test userauth01-1.11 {
sqlite3_user_authenticate db2 cindy xyzzy-cindy
} {SQLITE_OK}
do_test userauth01-1.12 {
sqlite3_user_change db alice xyzzy-alice 1
} {SQLITE_OK}
do_test userauth01-1.13 {
sqlite3_user_authenticate db alice pw-4-alice
} {SQLITE_AUTH}
do_test userauth01-1.14 {
sqlite3_user_authenticate db alice xyzzy-alice
} {SQLITE_OK}
# No user may change their own admin privilege setting.
#
do_test userauth01-1.15 {
sqlite3_user_change db alice xyzzy-alice 0
} {SQLITE_AUTH}
do_test userauth01-1.16 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 0}
do_test userauth01-1.17 {
sqlite3_user_change db2 cindy xyzzy-cindy 1
} {SQLITE_AUTH}
do_test userauth01-1.18 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 0}
# The sqlite3_user_change() interface can be used to change a users
# login credentials or admin privilege.
#
do_test userauth01-1.20 {
sqlite3_user_change db david xyzzy-david 1
} {SQLITE_OK}
do_test userauth01-1.21 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 1}
do_test userauth01-1.22 {
sqlite3_user_authenticate db2 david xyzzy-david
} {SQLITE_OK}
do_test userauth01-1.23 {
db2 eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 1}
do_test userauth01-1.24 {
sqlite3_user_change db david pw-4-david 0
} {SQLITE_OK}
do_test userauth01-1.25 {
sqlite3_user_authenticate db2 david pw-4-david
} {SQLITE_OK}
do_test userauth01-1.26 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 0}
do_test userauth01-1.27 {
catchsql {SELECT uname, isadmin FROM sqlite_user ORDER BY uname} db2
} {1 {no such table: sqlite_user}}
# Only an admin user can change another users login
# credentials or admin privilege setting.
#
do_test userauth01-1.30 {
sqlite3_user_change db2 bob xyzzy-bob 1
} {SQLITE_AUTH}
do_test userauth01-1.31 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 bob 0 cindy 0 david 0}
# The sqlite3_user_delete() interface can be used (by an admin user only)
# to delete a user.
#
do_test userauth01-1.40 {
sqlite3_user_delete db bob
} {SQLITE_OK}
do_test userauth01-1.41 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 cindy 0 david 0}
do_test userauth01-1.42 {
sqlite3_user_delete db2 cindy
} {SQLITE_AUTH}
do_test userauth01-1.43 {
sqlite3_user_delete db2 alice
} {SQLITE_AUTH}
do_test userauth01-1.44 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 cindy 0 david 0}
# The currently logged-in user cannot be deleted
#
do_test userauth01-1.50 {
sqlite3_user_delete db alice
} {SQLITE_AUTH}
do_test userauth01-1.51 {
db eval {SELECT uname, isadmin FROM sqlite_user ORDER BY uname}
} {alice 1 cindy 0 david 0}
# When ATTACH-ing new database files to a connection, each newly attached
# database that is an authentication-required database is checked using
# the same username and password as supplied to the main database. If that
# check fails, then the ATTACH command fails with an SQLITE_AUTH error.
#
do_test userauth01-1.60 {
forcedelete test3.db
sqlite3 db3 test3.db
sqlite3_user_add db3 alice xyzzy-alice 1
} {SQLITE_OK}
do_test userauth01-1.61 {
db3 eval {
CREATE TABLE t3(a,b,c); INSERT INTO t3 VALUES(1,2,3);
SELECT * FROM t3;
}
} {1 2 3}
do_test userauth01-1.62 {
db eval {
ATTACH 'test3.db' AS aux;
SELECT * FROM t1, t3 ORDER BY x LIMIT 1;
DETACH aux;
}
} {{} 1 2 3}
do_test userauth01-1.63 {
sqlite3_user_change db alice pw-4-alice 1
sqlite3_user_authenticate db alice pw-4-alice
catchsql {
ATTACH 'test3.db' AS aux;
}
} {1 {unable to open database: test3.db}}
do_test userauth01-1.64 {
sqlite3_extended_errcode db
} {SQLITE_AUTH}
do_test userauth01-1.65 {
db eval {PRAGMA database_list}
} {~/test3.db/}
# The sqlite3_set_authorizer() callback is modified to take a 7th parameter
# which is the username of the currently logged in user, or NULL for a
# no-authentication-required database.
#
proc auth {args} {
lappend ::authargs $args
return SQLITE_OK
}
do_test authuser01-2.1 {
unset -nocomplain ::authargs
db auth auth
db eval {SELECT x FROM t1}
set ::authargs
} {/SQLITE_SELECT {} {} {} {} alice/}
finish_test

View File

@ -25,7 +25,7 @@ set ::auth_fail 0
set ::auth_log [list]
set ::auth_filter [list SQLITE_READ SQLITE_UPDATE SQLITE_SELECT SQLITE_PRAGMA]
proc auth {code arg1 arg2 arg3 arg4} {
proc auth {code arg1 arg2 arg3 arg4 args} {
if {[lsearch $::auth_filter $code]>-1} {
return SQLITE_OK
}

View File

@ -373,50 +373,271 @@ do_execsql_test whereJ-2.2 {
############################################################################
ifcapable stat4 {
# Create and populate table.
do_execsql_test 3.1 { CREATE TABLE t1(a, b, c) }
for {set i 0} {$i < 32} {incr i 2} {
for {set x 0} {$x < 100} {incr x} {
execsql { INSERT INTO t1 VALUES($i, $x, $c) }
incr c
}
execsql { INSERT INTO t1 VALUES($i+1, 5, $c) }
# Create and populate table.
do_execsql_test 3.1 { CREATE TABLE t1(a, b, c) }
for {set i 0} {$i < 32} {incr i 2} {
for {set x 0} {$x < 100} {incr x} {
execsql { INSERT INTO t1 VALUES($i, $x, $c) }
incr c
}
do_execsql_test 3.2 {
SELECT a, count(*) FROM t1 GROUP BY a HAVING a < 8;
} {
0 100 1 1 2 100 3 1 4 100 5 1 6 100 7 1
}
do_execsql_test 3.3 {
CREATE INDEX idx_ab ON t1(a, b);
CREATE INDEX idx_c ON t1(c);
ANALYZE;
} {}
# This one should use index "idx_c".
do_eqp_test 3.4 {
SELECT * FROM t1 WHERE
a = 4 AND b BETWEEN 20 AND 80 -- Matches 80 rows
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
} {
0 0 0 {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
}
# This one should use index "idx_ab".
do_eqp_test 3.5 {
SELECT * FROM t1 WHERE
a = 5 AND b BETWEEN 20 AND 80 -- Matches 1 row
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
} {
0 0 0 {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
}
execsql { INSERT INTO t1 VALUES($i+1, 5, $c) }
incr c
}
do_execsql_test 3.2 {
SELECT a, count(*) FROM t1 GROUP BY a HAVING a < 8;
} {
0 100 1 1 2 100 3 1 4 100 5 1 6 100 7 1
}
do_execsql_test 3.3 {
CREATE INDEX idx_ab ON t1(a, b);
CREATE INDEX idx_c ON t1(c);
ANALYZE;
} {}
# This one should use index "idx_c".
do_eqp_test 3.4 {
SELECT * FROM t1 WHERE
a = 4 AND b BETWEEN 20 AND 80 -- Matches 80 rows
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
} {
0 0 0 {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
}
# This one should use index "idx_ab".
do_eqp_test 3.5 {
SELECT * FROM t1 WHERE
a = 5 AND b BETWEEN 20 AND 80 -- Matches 1 row
AND
c BETWEEN 150 AND 160 -- Matches 10 rows
} {
0 0 0 {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
}
###########################################################################################
# Reset the database and setup for a test case derived from actual SQLite users
#
db close
sqlite3 db test.db
do_execsql_test 4.1 {
CREATE TABLE le(
le_id largeint,
xid char(31),
type smallint,
name char(255) DEFAULT '',
mtime largeint DEFAULT 0,
muuid int DEFAULT 0
);
CREATE TABLE cx(
cx_id largeint,
code char(31),
type smallint,
name char(31),
description varchar,
role smallint,
mtime largeint DEFAULT 0,
muuid int DEFAULT 0,
le_id largeint DEFAULT 0,
imco smallint DEFAULT 0
);
CREATE TABLE px(
px_id largeint,
cx_id largeint,
px_tid largeint,
name char(31),
description varchar DEFAULT '',
ia smallint,
sl smallint,
le_id largeint DEFAULT 0,
mtime largeint DEFAULT 0,
muuid int DEFAULT 0
);
CREATE INDEX le_id on le (le_id);
CREATE INDEX c_id on cx (cx_id);
CREATE INDEX c_leid on cx (le_id);
CREATE INDEX p_id on px (px_id);
CREATE INDEX p_cid0 on px (cx_id);
CREATE INDEX p_pt on px (px_tid);
CREATE INDEX p_leid on px (le_id);
} {}
do_execsql_test 4.2 {
ANALYZE sqlite_master;
INSERT INTO sqlite_stat1 VALUES('le','le_id','1979 1');
INSERT INTO sqlite_stat1 VALUES('cx','c_leid','852 171');
INSERT INTO sqlite_stat1 VALUES('cx','c_id','852 1');
INSERT INTO sqlite_stat1 VALUES('px','p_leid','114443 63');
INSERT INTO sqlite_stat1 VALUES('px','p_pt','114443 22889');
INSERT INTO sqlite_stat1 VALUES('px','p_cid0','114443 181');
INSERT INTO sqlite_stat1 VALUES('px','p_id','114443 1');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','162 162','162 162',X'030202013903fb');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','208 208','208 208',X'0302020253012d');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','219 219','219 219',X'030202025e0131');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','248 248','248 248',X'030202027b014e');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','265 265','265 265',X'030202028c015f');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','358 358','358 358',X'03020202e901bc');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','439 439','439 439',X'030202033a020d');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','657 657','657 657',X'030202041402b4');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','659 659','659 659',X'030202041602b6');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','681 681','681 681',X'030202042c02cc');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','831 831','831 831',X'03020204c20482');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','852 852','852 852',X'03020204d70497');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','870 870','870 870',X'03020204e904a9');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','879 879','879 879',X'03020204f204b2');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1099 1099','1099 1099',X'03020205ce058e');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1273 1273','1273 1273',X'030202067c05a9');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1319 1319','1319 1319',X'03020206e30730');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1330 1330','1330 1330',X'0302020700035b');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1539 1539','1539 1539',X'03020207d105d8');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1603 1603','1603 1603',X'03020208390780');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1759 1759','1759 1759',X'030202092f0618');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1843 1843','1843 1843',X'03020209880650');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1915 1915','1915 1915',X'03020209d0068b');
INSERT INTO sqlite_stat4 VALUES('le','le_id','1 1','1927 1927','1927 1927',X'03020209dc0697');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 94','0 94',X'0308015f');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 189','0 189',X'03080200be');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 284','0 284',X'0308020120');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 379','0 379',X'030802017f');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 474','0 474',X'03080201de');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 569','0 569',X'030802023d');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 664','0 664',X'030802029f');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','846 1','0 759','0 759',X'03080202fe');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','3 1','846 847','1 847',X'0301024500e6');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','1 1','849 849','2 849',X'03010246027e');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','1 1','850 850','3 850',X'0301024700c9');
INSERT INTO sqlite_stat4 VALUES('cx','c_leid','1 1','851 851','4 851',X'03010248027f');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','94 94','94 94',X'03020200b801a8');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','113 113','113 113',X'03020200d101ad');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','171 171','171 171',X'030201011d2a');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','177 177','177 177',X'030202012600f2');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','189 189','189 189',X'030202013501c8');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','206 206','206 206',X'030201014f2d');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','231 231','231 231',X'030202016d00fc');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','284 284','284 284',X'03020201b702d0');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','291 291','291 291',X'03020101c042');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','311 311','311 311',X'03020201d801e7');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','339 339','339 339',X'03020101f74b');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','347 347','347 347',X'03020202030118');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','379 379','379 379',X'030202022f01fa');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','393 393','393 393',X'030201023f55');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','407 407','407 407',X'03020202500201');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','413 413','413 413',X'03020102565a');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','468 468','468 468',X'030201029468');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','474 474','474 474',X'030202029a0211');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','517 517','517 517',X'03020102cc76');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','548 548','548 548',X'03020202f00223');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','569 569','569 569',X'03020203090087');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','664 664','664 664',X'03020203740163');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','759 759','759 759',X'03020203e800b3');
INSERT INTO sqlite_stat4 VALUES('cx','c_id','1 1','803 803','803 803',X'030202041b026f');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 12715','0 12715',X'030802345b');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 25431','0 25431',X'0308026718');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 38147','0 38147',X'030803009a5c');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 50863','0 50863',X'03080300cdbe');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 63579','0 63579',X'0308030100e8');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 76295','0 76295',X'03080301351d');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 89011','0 89011',X'03080301674c');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110728 1','0 101727','0 101727',X'030803019b99');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','28 1','110824 110843','16 110843',X'0301037a0107f1');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','53 1','110873 110875','25 110875',X'0302020095275a');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','32 1','110927 110936','27 110936',X'030203009b009b4a');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','51 1','110980 111017','30 111017',X'03020300a4016c00');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','67 1','111047 111059','38 111059',X'03020200af2611');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','60 1','111136 111156','43 111156',X'03020300bc009aeb');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','42 1','111222 111239','59 111239',X'03020300d200b17b');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','36 1','111264 111266','60 111266',X'03020200d426d6');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','27 1','111733 111757','159 111757',X'030203014e017e1b');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','36 1','111760 111773','160 111773',X'030203014f00a2b9');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','29 1','111822 111833','167 111833',X'0302030176009c22');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','75 1','113031 113095','1190 113095',X'030203068501912c');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','132 1','113230 113263','1252 113263',X'0302030711009ee6');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','110 1','113851 113918','1572 113918',X'03020308e9011ca2');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','78 1','114212 114217','1791 114217',X'03020209e13b24');
INSERT INTO sqlite_stat4 VALUES('px','p_leid','112 1','114303 114351','1799 114351',X'03020309ea0128f2');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 12715','0 12715',X'030802477e');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 25431','0 25431',X'0308027c20');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 38147','0 38147',X'03080300c211');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 50863','0 50863',X'03080300fbe5');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 63579','0 63579',X'0308030140ff');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 76295','0 76295',X'03080301792d');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','89824 1','0 89011','0 89011',X'03080301bb68');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','24217 1','89824 101727','1 101727',X'03090300da12');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','154 1','114041 114154','2 114154',X'0301030200e5e9');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','198 1','114195 114351','3 114351',X'03010303015cb1');
INSERT INTO sqlite_stat4 VALUES('px','p_pt','50 1','114393 114441','4 114441',X'0301030401b2ef');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','3867 1','3 3736','2 3736',X'03010337015c6a');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','4194 1','4177 8209','5 8209',X'0301033b015075');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','4335 1','8371 11129','6 11129',X'0301033d0156fc');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1740 1','12706 12715','7 12715',X'0301023e34b9');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1680 1','14446 15487','8 15487',X'0301033f011694');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','7163 1','20116 25431','32 25431',X'03020300a400ed26');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1525 1','29100 29302','42 29302',X'03020200bb00d1');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','3703 1','30655 33323','45 33323',X'03020300be013fa5');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','2612 1','37767 38147','61 38147',X'03020200e32828');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1882 1','40545 41584','63 41584',X'03020300ea01a35a');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','6984 1','44110 50863','73 50863',X'0302030102017467');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1728 1','51230 51680','75 51680',X'030203010400b3e0');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','2805 1','55491 57936','95 57936',X'030203014101a004');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','2837 1','58934 59506','103 59506',X'030203015900a283');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','94 1','63492 63579','137 63579',X'0302030191016319');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','3573 1','63591 64497','140 64497',X'030203019c00822e');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','5037 1','70917 73033','160 73033',X'03020301c70091d9');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1940 1','75954 76295','161 76295',X'03020201c817f1');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1927 1','83926 84371','209 84371',X'03020202114295');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1522 1','86601 88117','213 88117',X'030203021b01b7b5');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','210 1','88906 89011','226 89011',X'030203022800dbbb');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','6165 1','92125 98066','258 98066',X'030203024d0189ac');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','2900 1','100721 101727','293 101727',X'030203027500cf39');
INSERT INTO sqlite_stat4 VALUES('px','p_cid0','1501 1','110012 110154','503 110154',X'0302020380493a');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','11129 11129','11129 11129',X'03030300d84e014d51');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','12715 12715','12715 12715',X'03030200de816f51');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','13030 13030','13030 13030',X'03030200e05b6fc4');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','25431 25431','25431 25431',X'0303030123df00efb0');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','29302 29302','29302 29302',X'030302013a2812c7');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','35463 35463','35463 35463',X'03030301666e00f866');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','38147 38147','38147 38147',X'030302017a391b74');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','38525 38525','38525 38525',X'030303017c6e00fb58');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','50863 50863','50863 50863',X'03030201b68724dd');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','58461 58461','58461 58461',X'03030201d95b2e1e');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','59506 59506','59506 59506',X'03030301dd7000a0fb');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','63468 63468','63468 63468',X'03030301ecea011405');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','63579 63579','63579 63579',X'03030201ed5932d5');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','64497 64497','64497 64497',X'03030301f0ef00a680');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','73033 73033','73033 73033',X'0303030225b90190e5');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','75650 75650','75650 75650',X'030303023a19019362');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','76295 76295','76295 76295',X'030303023e9801940c');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','79152 79152','79152 79152',X'030303024be50196b9');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','83249 83249','83249 83249',X'0303030261750123b1');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','89011 89011','89011 89011',X'030303027b3900c3af');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','98066 98066','98066 98066',X'03030302a76500ce54');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','101590 101590','101590 101590',X'03030302b63d00d3b5');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','101727 101727','101727 101727',X'03030202b6f24e9b');
INSERT INTO sqlite_stat4 VALUES('px','p_id','1 1','107960 107960','107960 107960',X'03030302d8ce0136ad');
ANALYZE sqlite_master;
} {}
# The following query should do a full table scan of cx in the outer loop.
# It is not correct to search table px using indx p_pt in the outer loop
# with cx in the middle loop. Test case from Bloomberg on 2014-09-05.
#
do_execsql_test 4.2 {
EXPLAIN QUERY PLAN
SELECT
px.name,
px.description
FROM
le,
cx,
px
WHERE
cx.code = '2990'
AND cx.type=2
AND px.cx_id = cx.cx_id
AND px.px_tid = 0
AND px.le_id = le.le_id;
} {/.*SCAN TABLE cx.*SEARCH TABLE px.*SEARCH TABLE le.*/}
finish_test

View File

@ -1621,7 +1621,7 @@ ifcapable auth {
}
} {}
proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK}
db auth auth
# An insert on the parent table must read the child key of any deferred