Merge all recent trunk changes into the sessions branch.

FossilOrigin-Name: 6406b77f2c447751a2fbb16f01c61cdcfd6af59e
This commit is contained in:
drh 2014-09-21 22:49:20 +00:00
commit 6b011d83b4
65 changed files with 2551 additions and 734 deletions

103
ext/misc/showauth.c Normal file
View File

@ -0,0 +1,103 @@
/*
** 2014-09-21
**
** 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 SQLite extension adds a debug "authorizer" callback to the database
** connection. The callback merely writes the authorization request to
** standard output and returns SQLITE_OK.
**
** This extension can be used (for example) in the command-line shell to
** trace the operation of the authorizer.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <stdio.h>
/*
** Display the authorization request
*/
static int authCallback(
void *pClientData,
int op,
const char *z1,
const char *z2,
const char *z3,
const char *z4
){
const char *zOp;
char zOpSpace[50];
switch( op ){
case SQLITE_CREATE_INDEX: zOp = "CREATE_INDEX"; break;
case SQLITE_CREATE_TABLE: zOp = "CREATE_TABLE"; break;
case SQLITE_CREATE_TEMP_INDEX: zOp = "CREATE_TEMP_INDEX"; break;
case SQLITE_CREATE_TEMP_TABLE: zOp = "CREATE_TEMP_TABLE"; break;
case SQLITE_CREATE_TEMP_TRIGGER: zOp = "CREATE_TEMP_TRIGGER"; break;
case SQLITE_CREATE_TEMP_VIEW: zOp = "CREATE_TEMP_VIEW"; break;
case SQLITE_CREATE_TRIGGER: zOp = "CREATE_TRIGGER"; break;
case SQLITE_CREATE_VIEW: zOp = "CREATE_VIEW"; break;
case SQLITE_DELETE: zOp = "DELETE"; break;
case SQLITE_DROP_INDEX: zOp = "DROP_INDEX"; break;
case SQLITE_DROP_TABLE: zOp = "DROP_TABLE"; break;
case SQLITE_DROP_TEMP_INDEX: zOp = "DROP_TEMP_INDEX"; break;
case SQLITE_DROP_TEMP_TABLE: zOp = "DROP_TEMP_TABLE"; break;
case SQLITE_DROP_TEMP_TRIGGER: zOp = "DROP_TEMP_TRIGGER"; break;
case SQLITE_DROP_TEMP_VIEW: zOp = "DROP_TEMP_VIEW"; break;
case SQLITE_DROP_TRIGGER: zOp = "DROP_TRIGGER"; break;
case SQLITE_DROP_VIEW: zOp = "DROP_VIEW"; break;
case SQLITE_INSERT: zOp = "INSERT"; break;
case SQLITE_PRAGMA: zOp = "PRAGMA"; break;
case SQLITE_READ: zOp = "READ"; break;
case SQLITE_SELECT: zOp = "SELECT"; break;
case SQLITE_TRANSACTION: zOp = "TRANSACTION"; break;
case SQLITE_UPDATE: zOp = "UPDATE"; break;
case SQLITE_ATTACH: zOp = "ATTACH"; break;
case SQLITE_DETACH: zOp = "DETACH"; break;
case SQLITE_ALTER_TABLE: zOp = "ALTER_TABLE"; break;
case SQLITE_REINDEX: zOp = "REINDEX"; break;
case SQLITE_ANALYZE: zOp = "ANALYZE"; break;
case SQLITE_CREATE_VTABLE: zOp = "CREATE_VTABLE"; break;
case SQLITE_DROP_VTABLE: zOp = "DROP_VTABLE"; break;
case SQLITE_FUNCTION: zOp = "FUNCTION"; break;
case SQLITE_SAVEPOINT: zOp = "SAVEPOINT"; break;
case SQLITE_COPY: zOp = "COPY"; break;
case SQLITE_RECURSIVE: zOp = "RECURSIVE"; break;
default: {
sqlite3_snprintf(sizeof(zOpSpace), zOpSpace, "%d", op);
zOp = zOpSpace;
break;
}
}
if( z1==0 ) z1 = "NULL";
if( z2==0 ) z2 = "NULL";
if( z3==0 ) z3 = "NULL";
if( z4==0 ) z4 = "NULL";
printf("AUTH: %s,%s,%s,%s,%s\n", zOp, z1, z2, z3, z4);
return SQLITE_OK;
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_showauth_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_set_authorizer(db, authCallback, 0);
return rc;
}

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
TCCX += -I$(TOP)/ext/session
# Object files for the SQLite library.
@ -68,7 +68,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
@ -220,7 +220,9 @@ SRC += \
SRC += \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/sqlite3session.h
SRC += \
$(TOP)/ext/userauth/userauth.c \
$(TOP)/ext/userauth/sqlite3userauth.h
# Generated source code files
#
@ -385,6 +387,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.
@ -567,6 +571,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
sqlite3session.o: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c

130
manifest
View File

@ -1,5 +1,5 @@
C Merge\ssupport\sfor\slarge\sfiles\son\sAndroid\sfrom\strunk.
D 2014-09-08T15:04:24.810
C Merge\sall\srecent\strunk\schanges\sinto\sthe\ssessions\sbranch.
D 2014-09-21T22:49:20.257
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -116,6 +116,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 56739fab8c2ed6a9e2dac5592a88d281a999c43b
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
@ -160,10 +161,13 @@ F ext/session/sessionfault.test e7965159a73d385c1a4af12d82c3a039ebdd71a6
F ext/session/sqlite3session.c 4c7689bd8286147f7d9bf5d4b6ca5e7e7ee588ab
F ext/session/sqlite3session.h 66c14a2f6193c47773770307636e88c43db6f839
F ext/session/test_session.c a252fb669d3a1b3552ee7b87fe610debc0afeb7b
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 4dfbd8fbc91ee5732554b31a205960241c4fc059
F main.mk 7711bc77822814799b853271ee19ac79e98bfb4b
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@ -178,36 +182,36 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
F src/analyze.c 79383a54fee3b7f1fb03dd4c8c8115583f506de5
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/analyze.c 6290a109be876daaa242cd7216f97240f5401776
F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
F src/btree.c b1c1cd1cc3ae2e433a23b9a6c9ab53805707d8cd
F src/btree.c 6aa61c0e3d20d1d1acc8fb33d8f0ebd675305d3c
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h e0ecb5dba292722039a7540beb3fc448103273cc
F src/build.c 8cb237719c185eec7bd8449b2e747491ded11932
F src/build.c 8dbca25988045fbf2a33c9631c42706fa6449e60
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/ctime.c 16cd19215d9fd849ee2b7509b092f2e0bbd6a958
F src/date.c 57a7f9ba9f6b4d5268f5e411739066a611f99036
F src/delete.c de3d07d6602b90ae6e8bdebeb7b3265bb846377f
F src/expr.c 441a7e24e2f7bea9475778fa8acce9e8a69ca8f0
F src/expr.c 4f101c8ddc6d5a22303c88278069f5261562a9a8
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
F src/func.c 0517037766e18eff7dce298e6b3a8e6311df75ec
F src/func.c 1629ccdd8ef3f19d7accc9d9287190489469ff81
F src/global.c 5110fa12e09729b84eee0191c984ec4008e21937
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 92e955206fadb4d1184161d00894b32c90879e86
F src/insert.c 4f6df86bbed2d7b59e4601730407876825dd7b71
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab
F src/main.c faf3629e61ba31912b474316c02f173878ddd566
F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
F src/main.c 1010acfb69ccd62e34e3b83664537450225c74e2
F src/malloc.c 5bb99ee1e08ad58e457063cf79ce521db0e24195
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
@ -224,32 +228,32 @@ F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c addd023b26c623fec4dedc110fc4370a65b4768c
F src/os_unix.c 9096a1b1449182e67e759f59994eee04113bc587
F src/os_win.c 0a4042ef35f322e86fa01f6c8884c5e645b911e7
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
F src/pager.c 31da9594ad4c3b5851bb6fe1a95c33835ab7ddce
F src/pager.c caab007743821d96752597c9cfd7351654697b06
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c 2048affdb09a04478b5fc6e64cb1083078d369be
F src/parse.y b98772da2bb5415970085b707203f92569400aa8
F src/pcache.c 4121a0571c18581ee9f82f086d5e2030051ebd6a
F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
F src/pcache1.c dab8ab930d4a73b99768d881185994f34b80ecaa
F src/pragma.c 14bcdb504128a476cce5bbc086d5226c5e46c225
F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d
F src/printf.c e74925089a85e3c9f0e315595f41c139d3d118c2
F src/pragma.c 3f3e959390a10c0131676f0e307acce372777e0f
F src/prepare.c 6ef0cf2f9274982988ed6b7cab1be23147e94196
F src/printf.c 3a47f526b173813d9a7f4e7044007771ba68cde1
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 0d1621e45fffe4b4396477cf46e41a84b0145ffb
F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c b4457526cee73c0b69fad42f799f619b1d5a8a8a
F src/shell.c ec6d5f630ed617dc80cbc35d9e45fe47f07923db
F src/sqlite.h.in 70de5c9e5ac117363db78d144c7e6f1f65d007a1
F src/select.c a83ed8bc2a31c131e3addb6f0488b68334085e7b
F src/shell.c 85aae71dcc9bd6df28047b95ab631eb0ac91401f
F src/sqlite.h.in 1af072be5ed8902c8c12b5b105487d0efedd00b4
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 1f40357fb9b12a80c5a3b2b109fd249b009213d4
F src/sqliteInt.h 4d6c5c87324c2b6218c01a0895c0d298fffb5aff
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 35f074ded974804602e3ed89576a74c9b7255c93
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 4e28a53e66bad8d014a510ef0205f5497c712b08
F src/tclsqlite.c 9d0073dda76ab2508c8fde50950f4556fe2fdafb
F src/test1.c 22bfe1ce9f2f3746d682093a475ec0a33e0e55d8
F src/table.c 2e99ef7ef16187e17033d9398dc962ce22dab5cb
F src/tclsqlite.c 684c317b85f4729de12909bfad80d3f5500357cf
F src/test1.c 523cd70ded28db71af9a30ec184cbe0957de9575
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
@ -262,11 +266,11 @@ 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 a65043d01ad3bd2dfe9a3aa7e39a9935b069f6aa
F src/test_config.c 5a2a9a580f9c2dfd2ffd52966fd361f2148909d1
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_func.c 14e543ae4d905ee31dc322b2f8d31bfac1769d45
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
@ -295,30 +299,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 722872c816887fd66931333c59570ebd9622a95f
F src/tokenize.c 3df63041994f55afeb168b463ec836e8f1c50e7c
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
F src/update.c b9e5295d3a78e96b7c2978c4f9d224d06880f031
F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
F src/vdbe.c 16b7d573a683e70a1e502332c5f90dd48fa34736
F src/vdbe.h ca3b6df299adce6e2f499c57e42ae54f142ae823
F src/vdbeInt.h 0dec00acd7e490a456a0ebaa6f478de94da7b52d
F src/vdbeapi.c d63985095b5d24b522fc206c547df1683a4e73ee
F src/vdbeaux.c 264284931ecd079076ab40a71522570107b8e723
F src/vdbe.c 5e6d4ef36cfff2bacb4d11eccc99bd55c76692f5
F src/vdbe.h d61daeffed696e21630759de9e135ee298ad9573
F src/vdbeInt.h 0e6e8d18199cef7dd5e9fa5de8490f60806259f0
F src/vdbeapi.c cdded67e36d2a20f6d1c7d56f008a646557d2bf0
F src/vdbeaux.c 07b0045d0f34d0ad70c1c42ff75246a7e64e4e87
F src/vdbeblob.c d65b01f439df63911ac3d7a9a85c15503965f2c3
F src/vdbemem.c dc36ea9fe26c25550c50085f388167086ef7d73a
F src/vdbesort.c ab39574ec6e0c6213bd2a5c09cca9f9f8ba98450
F src/vdbetrace.c 16d39c1ef7d1f4a3a7464bea3b7b4bdd7849c415
F src/vdbemem.c 5096fe50a1bd12bc2294a8b27ca6e6d1b15ef607
F src/vdbesort.c 5c1bacf90578d22b630fbf6ed98ccf60d83435ef
F src/vdbetrace.c 4f29b04edb0cec3d5fcd9b566d9f0e75c8984362
F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f
F src/wal.c 10e7de7ce90865a68153f001a61f1d985cd17983
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 839b5e1db2507e221ad1c308f148a8519ed750be
F src/where.c 0888567c0e01a41b6001647e333f8ccfd3ae7d36
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
@ -349,9 +353,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
@ -492,7 +496,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
@ -590,7 +594,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
@ -725,7 +729,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
@ -752,7 +756,7 @@ F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/orderby1.test 12426f99518cde45f34215ca6a0ebc0e9bc5c77a
F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
@ -798,7 +802,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
@ -859,6 +863,7 @@ F test/sort.test 15e1d3014abc3f6d4357ed81b93b82117aefd235
F test/sort2.test 269f4f50c6e468cc32b302ae7ff0add8338ec6de
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
F test/sort4.test 6c37d85f7cd28d50cce222fcab84ccd771e105cb
F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f
F test/sortfault.test b8e35177f97438b930ee87c9419ca2599e8073e1
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
@ -874,7 +879,7 @@ F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
F test/subquery2.test 91e1e364072aeff431d1f9689b15147e421d88c7
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
@ -1071,6 +1076,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
@ -1081,7 +1087,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
@ -1153,7 +1159,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
@ -1191,7 +1197,7 @@ F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/showdb.c bd073a78bce714a0e42d92ea474b3eb8cb53be5d
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
F tool/showstat4.c c39279d6bd37cb999b634f0064f6f86ad7af008f
F tool/showwal.c 3209120269cdf9380f091459e47b776b4f81dfd3
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
F tool/spaceanal.tcl 8e50b217c56a6a086a1b47eac9d09c5cd65b996f
@ -1210,7 +1216,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 d4cce2c71e64ab7b6a65a81b88b69445ed859351 ad7063aa1a0db32cdbe71815545b2edca57d3bcc
R 4a5cc1720b7ac28a8c5dae667ce4d5c3
P c2885c6bb24cc55178467e57e77bf71df58b3b13 d5880abd63c83c88e135257373afa0a3fd88297e
R 9d7f30c83131a55806d3c1dd053387df
U drh
Z 6dac05eb8bc8db62f0a6dc6a2d623660
Z c53e54ee2e290caf615c330d235d140a

View File

@ -1 +1 @@
c2885c6bb24cc55178467e57e77bf71df58b3b13
6406b77f2c447751a2fbb16f01c61cdcfd6af59e

View File

@ -1201,7 +1201,8 @@ static void analyzeOneTable(
/* Add the entry to the stat1 table. */
callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
assert( "BBB"[0]==SQLITE_AFF_TEXT );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
@ -1264,7 +1265,8 @@ static void analyzeOneTable(
sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
assert( "BBB"[0]==SQLITE_AFF_TEXT );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);

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

@ -606,7 +606,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 ){
@ -4746,14 +4746,14 @@ int sqlite3BtreeMovetoUnpacked(
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
@ -4774,7 +4774,7 @@ int sqlite3BtreeMovetoUnpacked(
sqlite3_free(pCellKey);
goto moveto_finish;
}
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
c = xRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
assert(

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;
}
@ -1143,7 +1177,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
** estimate is scaled so that the size of an integer is 1. */
if( pszEst ){
*pszEst = 1; /* default size is approx 4 bytes */
if( aff<=SQLITE_AFF_NONE ){
if( aff<SQLITE_AFF_NUMERIC ){
if( zChar ){
while( zChar[0] ){
if( sqlite3Isdigit(zChar[0]) ){
@ -1514,8 +1548,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
static const char * const azType[] = {
/* SQLITE_AFF_TEXT */ " TEXT",
/* SQLITE_AFF_NONE */ "",
/* SQLITE_AFF_TEXT */ " TEXT",
/* SQLITE_AFF_NUMERIC */ " NUM",
/* SQLITE_AFF_INTEGER */ " INT",
/* SQLITE_AFF_REAL */ " REAL"
@ -1527,15 +1561,15 @@ static char *createTableStmt(sqlite3 *db, Table *p){
k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, pCol->zName);
assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 );
assert( pCol->affinity-SQLITE_AFF_TEXT < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_TEXT );
assert( pCol->affinity-SQLITE_AFF_NONE >= 0 );
assert( pCol->affinity-SQLITE_AFF_NONE < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_NONE );
testcase( pCol->affinity==SQLITE_AFF_TEXT );
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
zType = azType[pCol->affinity - SQLITE_AFF_NONE];
len = sqlite3Strlen30(zType);
assert( pCol->affinity==SQLITE_AFF_NONE
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
@ -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 );
@ -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;

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

@ -1069,6 +1069,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
sqlite3SelectSetName(pNew, p->zSelName);
return pNew;
}
#else
@ -2432,16 +2433,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)

View File

@ -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);
}
/*
@ -1491,6 +1492,7 @@ static void minmaxStep(
sqlite3SkipAccumulatorLoad(context);
}
}else{
pBest->db = sqlite3_context_db_handle(context);
sqlite3VdbeMemCopy(pBest, pArg);
}
}
@ -1662,10 +1664,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 +1699,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 +1722,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

@ -56,13 +56,13 @@ void sqlite3OpenTable(
**
** Character Column affinity
** ------------------------------
** 'a' TEXT
** 'b' NONE
** 'c' NUMERIC
** 'd' INTEGER
** 'e' REAL
** 'A' NONE
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
** 'F' REAL
**
** An extra 'd' is appended to the end of the string to cover the
** An extra 'D' is appended to the end of the string to cover the
** rowid that appears as the last column in every index.
**
** Memory for the buffer containing the column index affinity string
@ -111,11 +111,11 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
**
** Character Column affinity
** ------------------------------
** 'a' TEXT
** 'b' NONE
** 'c' NUMERIC
** 'd' INTEGER
** 'e' REAL
** 'A' NONE
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
** 'E' REAL
*/
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
int i;

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;
@ -2587,7 +2591,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.
*/

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
@ -307,10 +305,10 @@ void *sqlite3Malloc(int n){
p = 0;
}else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm(n, &p);
mallocWithAlarm((int)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
@ -447,17 +451,23 @@ int sqlite3MallocSize(void *p){
return sqlite3GlobalConfig.m.xSize(p);
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
return db->lookaside.sz;
if( db==0 ){
return sqlite3MallocSize(p);
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
return sqlite3GlobalConfig.m.xSize(p);
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
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 +529,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,12 +547,12 @@ 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 ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
@ -552,7 +562,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
sqlite3MallocAlarm((int)nBytes);
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
if( pNew ){
@ -572,6 +582,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,10 +599,10 @@ 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);
memset(p, 0, (size_t)n);
}
return p;
}
@ -594,10 +611,10 @@ 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);
memset(p, 0, (size_t)n);
}
return p;
}
@ -620,7 +637,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 +681,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) );
@ -685,7 +702,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc(p, n);
pNew = sqlite3_realloc64(p, n);
if( !pNew ){
sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
db->mallocFailed = 1;
@ -701,7 +718,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 +748,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;
@ -739,7 +756,7 @@ char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
assert( (n&0x7fffffff)==n );
zNew = sqlite3DbMallocRaw(db, n+1);
if( zNew ){
memcpy(zNew, z, n);
memcpy(zNew, z, (size_t)n);
zNew[n] = 0;
}
return zNew;

View File

@ -4997,7 +4997,7 @@ IOMETHODS(
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
1, /* shared memory is disabled */
3, /* shared memory is disabled */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */

View File

@ -2428,7 +2428,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;
@ -7230,7 +7230,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
** is empty, return 0.
*/
int sqlite3PagerWalFramesize(Pager *pPager){
assert( pPager->eState==PAGER_READER );
assert( pPager->eState>=PAGER_READER );
return sqlite3WalFramesize(pPager->pWal);
}
#endif

View File

@ -459,9 +459,33 @@ multiselect_op(A) ::= UNION(OP). {A = @OP;}
multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;}
%endif SQLITE_OMIT_COMPOUND_SELECT
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
#if SELECTTRACE_ENABLED
/* Populate the Select.zSelName[] string that is used to help with
** query planner debugging, to differentiate between multiple Select
** objects in a complex query.
**
** If the SELECT keyword is immediately followed by a C-style comment
** then extract the first few alphanumeric characters from within that
** comment to be the zSelName value. Otherwise, the label is #N where
** is an integer that is incremented with each SELECT statement seen.
*/
if( A!=0 ){
const char *z = S.z+6;
int i;
sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "#%d",
++pParse->nSelect);
while( z[0]==' ' ) z++;
if( z[0]=='/' && z[1]=='*' ){
z += 2;
while( z[0]==' ' ) z++;
for(i=0; sqlite3Isalnum(z[i]); i++){}
sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "%.*s", i, z);
}
}
#endif /* SELECTRACE_ENABLED */
}
oneselect(A) ::= values(X). {A = X;}

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
@ -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

@ -1397,6 +1397,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

@ -14,6 +14,21 @@
*/
#include "sqliteInt.h"
/*
** If the strchrnul() library function is available, then set
** HAVE_STRCHRNUL. If that routine is not available, this module
** will supply its own. The built-in version is slower than
** the glibc version so the glibc version is definitely preferred.
*/
#if !defined(HAVE_STRCHRNUL)
# if defined(linux)
# define HAVE_STRCHRNUL 1
# else
# define HAVE_STRCHRNUL 0
# endif
#endif
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
@ -224,9 +239,13 @@ void sqlite3VXPrintf(
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
bufpt = (char *)fmt;
while( (c=(*++fmt))!='%' && c!=0 ){};
#if HAVE_STRCHRNUL
fmt = strchrnul(fmt, '%');
#else
do{ fmt++; }while( *fmt && *fmt != '%' );
#endif
sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
if( c==0 ) break;
if( *fmt==0 ) break;
}
if( (c=(*++fmt))==0 ){
sqlite3StrAccumAppend(pAccum, "%", 1);

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
@ -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

@ -14,6 +14,20 @@
*/
#include "sqliteInt.h"
/*
** Trace output macros
*/
#if SELECTTRACE_ENABLED
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
#endif
/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
@ -126,6 +140,18 @@ Select *sqlite3SelectNew(
return pNew;
}
#if SELECTTRACE_ENABLED
/*
** Set the name of a Select object
*/
void sqlite3SelectSetName(Select *p, const char *zName){
if( p && zName ){
sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName);
}
}
#endif
/*
** Delete the given Select structure and all of its substructures.
*/
@ -488,7 +514,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 +550,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 ){
@ -3131,8 +3157,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 +3223,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
@ -3267,8 +3300,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
@ -3342,6 +3381,8 @@ static int flattenSubquery(
}
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
pSub->zSelName, pSub, iFrom));
/* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
@ -3394,6 +3435,7 @@ static int flattenSubquery(
p->pLimit = 0;
p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0);
sqlite3SelectSetName(pNew, pSub->zSelName);
p->pOffset = pOffset;
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
@ -3406,6 +3448,9 @@ static int flattenSubquery(
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
SELECTTRACE(2,pParse,p,
("compound-subquery flattener creates %s.%p as peer\n",
pNew->zSelName, pNew));
}
if( db->mallocFailed ) return 1;
}
@ -3535,8 +3580,23 @@ static int flattenSubquery(
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
/* At this point, any non-zero iOrderByCol values indicate that the
** ORDER BY column expression is identical to the iOrderByCol'th
** expression returned by SELECT statement pSub. Since these values
** do not necessarily correspond to columns in SELECT statement pParent,
** zero them before transfering the ORDER BY clause.
**
** Not doing this may cause an error if a subsequent call to this
** function attempts to flatten a compound sub-query into pParent
** (the only way this can happen is if the compound sub-query is
** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
ExprList *pOrderBy = pSub->pOrderBy;
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].u.x.iOrderByCol = 0;
}
assert( pParent->pOrderBy==0 );
pParent->pOrderBy = pSub->pOrderBy;
assert( pSub->pPrior==0 );
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}else if( pParent->pOrderBy ){
substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
@ -4052,6 +4112,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
sqlite3WalkSelect(pWalker, pFrom->pSelect);
}
#endif
@ -4586,6 +4647,10 @@ int sqlite3Select(
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
pParse->nSelectIndent++;
SELECTTRACE(1,pParse,p, ("begin processing\n"));
#endif
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
@ -4742,6 +4807,10 @@ int sqlite3Select(
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#endif
@ -5341,6 +5410,10 @@ select_end:
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}

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>
@ -3188,6 +3191,13 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
extern int sqlite3SelectTrace;
sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
}else
#endif
#if defined(SQLITE_ENABLE_SESSION)
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
OpenSession *pSession = &p->aSession[0];
@ -3718,6 +3728,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
@ -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);
@ -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*));

View File

@ -250,6 +250,23 @@ 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*);
};
/*
@ -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

@ -47,6 +47,15 @@
# define _LARGEFILE_SOURCE 1
#endif
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
# define _BSD_SOURCE
#endif
/*
** For MinGW, check to see if we can include the header file containing its
** version information, among other things. Normally, this internal MinGW
@ -104,15 +113,6 @@
#pragma warn -spa /* Suspicious pointer arithmetic */
#endif
/* Needed for various definitions... */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
# define _BSD_SOURCE
#endif
/*
** Include standard header files as necessary
*/
@ -706,6 +706,16 @@ extern const int sqlite3one;
# undef SQLITE_ENABLE_STAT3_OR_STAT4
#endif
/*
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
#else
# define SELECTTRACE_ENABLED 0
#endif
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@ -989,6 +999,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.
*/
@ -1063,8 +1112,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
@ -1090,7 +1138,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.
@ -1108,6 +1155,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
};
/*
@ -1253,6 +1303,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
@ -1300,6 +1351,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
@ -1386,18 +1440,18 @@ struct CollSeq {
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
** the speed a little by numbering the values consecutively.
**
** But rather than start with 0 or 1, we begin with 'a'. That way,
** But rather than start with 0 or 1, we begin with 'A'. That way,
** when multiple affinity types are concatenated into a string and
** used as the P4 operand, they will be more readable.
**
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison.
** for a numeric type is a single comparison. And the NONE type is first.
*/
#define SQLITE_AFF_TEXT 'a'
#define SQLITE_AFF_NONE 'b'
#define SQLITE_AFF_NUMERIC 'c'
#define SQLITE_AFF_INTEGER 'd'
#define SQLITE_AFF_REAL 'e'
#define SQLITE_AFF_NONE 'A'
#define SQLITE_AFF_TEXT 'B'
#define SQLITE_AFF_NUMERIC 'C'
#define SQLITE_AFF_INTEGER 'D'
#define SQLITE_AFF_REAL 'E'
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@ -1405,7 +1459,7 @@ struct CollSeq {
** The SQLITE_AFF_MASK values masks off the significant bits of an
** affinity value.
*/
#define SQLITE_AFF_MASK 0x67
#define SQLITE_AFF_MASK 0x47
/*
** Additional bit values that can be ORed with an affinity without
@ -1416,10 +1470,10 @@ struct CollSeq {
** operator is NULL. It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
/*
** An object of this type is created for each virtual table present in
@ -2222,17 +2276,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
@ -2259,6 +2318,9 @@ struct Select {
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
#if SELECTTRACE_ENABLED
char zSelName[12]; /* Symbolic name of this SELECT use for debugging */
#endif
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
@ -2283,13 +2345,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() */
/*
@ -2517,6 +2579,10 @@ struct Parse {
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
int nMaxArg; /* Max args passed to user function by sub-program */
#if SELECTTRACE_ENABLED
int nSelect; /* Number of SELECT statements seen */
int nSelectIndent; /* How far to indent SELECTTRACE() output */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@ -2943,15 +3009,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*);
@ -3255,6 +3321,11 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
#if SELECTTRACE_ENABLED
void sqlite3SelectSetName(Select*,const char*);
#else
# define sqlite3SelectSetName(A,B)
#endif
void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
@ -3492,7 +3563,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;
}
@ -73,7 +73,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
if( z==0 ) goto malloc_failed;
p->azResult[p->nData++] = z;
}
}else if( p->nColumn!=nCol ){
}else if( (int)p->nColumn!=nCol ){
sqlite3_free(p->zErrMsg);
p->zErrMsg = sqlite3_mprintf(
"sqlite3_get_table() called with two or more incompatible queries"

View File

@ -916,6 +916,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;
@ -968,6 +971,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";
@ -1785,8 +1791,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

@ -6497,6 +6497,132 @@ static int sorter_test_sort4_helper(
}
#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.
*/
@ -6734,6 +6860,13 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "load_static_extension", tclLoadStaticExtensionCmd },
{ "sorter_test_fakeheap", sorter_test_fakeheap },
{ "sorter_test_sort4_helper", sorter_test_sort4_helper },
#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;

View File

@ -615,6 +615,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

@ -504,7 +504,7 @@ static void test_extract(
sqlite3_result_value(context, &mem);
}
sqlite3DbFree(db, mem.zMalloc);
if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc);
}
}
@ -591,7 +591,7 @@ static void test_decode(
Tcl_ListObjAppendElement(0, pRet, pVal);
if( mem.zMalloc ){
if( mem.szMalloc ){
sqlite3DbFree(db, mem.zMalloc);
}
}

View File

@ -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

@ -314,12 +314,13 @@ SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
*z = 0;
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
c = pMem->flags;
sqlite3VdbeMemRelease(pMem);
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask);
pMem->enc = desiredEnc;
pMem->flags |= (MEM_Term);
pMem->z = (char*)zOut;
pMem->zMalloc = pMem->z;
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z);
translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)

View File

@ -219,7 +219,7 @@ static VdbeCursor *allocateCursor(
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
@ -252,13 +252,13 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
i64 iValue;
u8 enc = pRec->enc;
if( (pRec->flags&MEM_Str)==0 ) return;
assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
pRec->u.i = iValue;
pRec->flags |= MEM_Int;
}else{
pRec->r = rValue;
pRec->u.r = rValue;
pRec->flags |= MEM_Real;
if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec);
}
@ -287,7 +287,17 @@ static void applyAffinity(
char affinity, /* The affinity to be applied */
u8 enc /* Use this text encoding */
){
if( affinity==SQLITE_AFF_TEXT ){
if( affinity>=SQLITE_AFF_NUMERIC ){
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|| affinity==SQLITE_AFF_NUMERIC );
if( (pRec->flags & MEM_Int)==0 ){
if( (pRec->flags & MEM_Real)==0 ){
if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
}else{
sqlite3VdbeIntegerAffinity(pRec);
}
}
}else if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string
** representation.
@ -295,16 +305,6 @@ static void applyAffinity(
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
}
}else if( affinity!=SQLITE_AFF_NONE ){
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|| affinity==SQLITE_AFF_NUMERIC );
if( (pRec->flags & MEM_Int)==0 ){
if( (pRec->flags & MEM_Real)==0 ){
applyNumericAffinity(pRec,1);
}else{
sqlite3VdbeIntegerAffinity(pRec);
}
}
}
}
@ -339,13 +339,13 @@ void sqlite3ValueApplyAffinity(
/*
** pMem currently only holds a string type (or maybe a BLOB that we can
** interpret as a string if we want to). Compute its corresponding
** numeric type, if has one. Set the pMem->r and pMem->u.i fields
** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
@ -359,7 +359,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
** none.
**
** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
** But it does set pMem->r and pMem->u.i appropriately.
** But it does set pMem->u.r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
if( pMem->flags & (MEM_Int|MEM_Real) ){
@ -469,7 +469,7 @@ static void memTracePrint(Mem *p){
printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
printf(" r:%g", p->r);
printf(" r:%g", p->u.r);
#endif
}else if( p->flags & MEM_RowSet ){
printf(" (rowset)");
@ -650,7 +650,7 @@ int sqlite3VdbeExec(
assert( pOp->p2<=(p->nMem-p->nCursor) );
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
VdbeMemReleaseExtern(pOut);
if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
pOut->flags = MEM_Int;
}
@ -1012,7 +1012,7 @@ case OP_Int64: { /* out2-prerelease */
case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->flags = MEM_Real;
assert( !sqlite3IsNaN(*pOp->p4.pReal) );
pOut->r = *pOp->p4.pReal;
pOut->u.r = *pOp->p4.pReal;
break;
}
#endif
@ -1035,9 +1035,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
if( rc==SQLITE_TOOBIG ) goto too_big;
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
assert( pOut->zMalloc==pOut->z );
assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
assert( VdbeMemDynamic(pOut)==0 );
pOut->zMalloc = 0;
pOut->szMalloc = 0;
pOut->flags |= MEM_Static;
if( pOp->p4type==P4_DYNAMIC ){
sqlite3DbFree(db, pOp->p4.z);
@ -1089,7 +1089,7 @@ case OP_Null: { /* out2-prerelease */
while( cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
VdbeMemReleaseExtern(pOut);
sqlite3VdbeMemSetNull(pOut);
pOut->flags = nullFlag;
cnt--;
}
@ -1157,7 +1157,6 @@ case OP_Variable: { /* out2-prerelease */
** for P3 to be less than 1.
*/
case OP_Move: {
char *zMalloc; /* Holding variable for allocated memory */
int n; /* Number of registers left to copy */
int p1; /* Register to copy from */
int p2; /* Register to copy to */
@ -1175,17 +1174,12 @@ case OP_Move: {
assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
assert( memIsValid(pIn1) );
memAboutToChange(p, pOut);
sqlite3VdbeMemRelease(pOut);
zMalloc = pOut->zMalloc;
memcpy(pOut, pIn1, sizeof(Mem));
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
pOut->pScopyFrom += p1 - pOp->p2;
}
#endif
pIn1->flags = MEM_Undefined;
pIn1->xDel = 0;
pIn1->zMalloc = zMalloc;
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
@ -1490,7 +1484,7 @@ fp_math:
if( sqlite3IsNaN(rB) ){
goto arithmetic_result_is_null;
}
pOut->r = rB;
pOut->u.r = rB;
MemSetTypeFlag(pOut, MEM_Real);
if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
sqlite3VdbeIntegerAffinity(pOut);
@ -1765,7 +1759,7 @@ case OP_RealAffinity: { /* in1 */
** A NULL value is not changed by this routine. It remains NULL.
*/
case OP_Cast: { /* in1 */
assert( pOp->p2>=SQLITE_AFF_TEXT && pOp->p2<=SQLITE_AFF_REAL );
assert( pOp->p2>=SQLITE_AFF_NONE && pOp->p2<=SQLITE_AFF_REAL );
testcase( pOp->p2==SQLITE_AFF_TEXT );
testcase( pOp->p2==SQLITE_AFF_NONE );
testcase( pOp->p2==SQLITE_AFF_NUMERIC );
@ -1915,15 +1909,35 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}else{
/* Neither operand is NULL. Do a comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity ){
applyAffinity(pIn1, affinity, encoding);
applyAffinity(pIn3, affinity, encoding);
if( db->mallocFailed ) goto no_mem;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (pIn1->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
}
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3,0);
}
}else if( affinity==SQLITE_AFF_TEXT ){
if( (pIn1->flags & MEM_Str)==0 && (pIn1->flags & (MEM_Int|MEM_Real))!=0 ){
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
sqlite3VdbeMemStringify(pIn1, encoding, 1);
}
if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_Real );
sqlite3VdbeMemStringify(pIn3, encoding, 1);
}
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
ExpandBlob(pIn1);
ExpandBlob(pIn3);
if( pIn1->flags & MEM_Zero ){
sqlite3VdbeMemExpandBlob(pIn1);
flags1 &= ~MEM_Zero;
}
if( pIn3->flags & MEM_Zero ){
sqlite3VdbeMemExpandBlob(pIn3);
flags3 &= ~MEM_Zero;
}
if( db->mallocFailed ) goto no_mem;
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
switch( pOp->opcode ){
@ -1948,8 +1962,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
}
/* Undo any changes made by applyAffinity() to the input registers. */
pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
pIn1->flags = flags1;
pIn3->flags = flags3;
break;
}
@ -2117,10 +2131,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
case OP_Not: { /* same as TK_NOT, in1, out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1));
sqlite3VdbeMemSetNull(pOut);
if( (pIn1->flags & MEM_Null)==0 ){
pOut->flags = MEM_Int;
pOut->u.i = !sqlite3VdbeIntValue(pIn1);
}
break;
}
@ -2135,10 +2149,10 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */
case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
sqlite3VdbeMemSetNull(pOut);
if( (pIn1->flags & MEM_Null)==0 ){
pOut->flags = MEM_Int;
pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
}
break;
}
@ -2256,7 +2270,6 @@ case OP_Column: {
int p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
@ -2269,6 +2282,7 @@ case OP_Column: {
u32 szField; /* Number of bytes in the content of a field */
u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
u16 fx; /* pDest->flags value */
Mem *pReg; /* PseudoTable input register */
p2 = pOp->p2;
@ -2279,8 +2293,7 @@ case OP_Column: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( p2<pC->nField );
aType = pC->aType;
aOffset = aType + pC->nField;
aOffset = pC->aType + pC->nField;
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
#endif
@ -2361,7 +2374,7 @@ case OP_Column: {
}
/* Make sure at least the first p2+1 entries of the header have been
** parsed and valid information is in aOffset[] and aType[].
** parsed and valid information is in aOffset[] and pC->aType[].
*/
if( pC->nHdrParsed<=p2 ){
/* If there is more header available for parsing in the record, try
@ -2381,7 +2394,7 @@ case OP_Column: {
zData = pC->aRow;
}
/* Fill in aType[i] and aOffset[i] values through the p2-th field. */
/* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
i = pC->nHdrParsed;
offset = aOffset[i];
zHdr = zData + pC->iHdrOffset;
@ -2394,7 +2407,7 @@ case OP_Column: {
}else{
zHdr += sqlite3GetVarint32(zHdr, &t);
}
aType[i] = t;
pC->aType[i] = t;
szField = sqlite3VdbeSerialTypeLen(t);
offset += szField;
if( offset<szField ){ /* True if offset overflows */
@ -2441,61 +2454,61 @@ case OP_Column: {
}
/* Extract the content for the p2+1-th column. Control can only
** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
** reach this point if aOffset[p2], aOffset[p2+1], and pC->aType[p2] are
** all valid.
*/
assert( p2<pC->nHdrParsed );
assert( rc==SQLITE_OK );
assert( sqlite3VdbeCheckMemInvariants(pDest) );
if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
t = pC->aType[p2];
if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
** page - where the content is not on an overflow page */
VdbeMemReleaseExtern(pDest);
sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest);
}else{
/* This branch happens only when content is on overflow pages */
t = aType[p2];
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
|| (len = sqlite3VdbeSerialTypeLen(t))==0
){
/* Content is irrelevant for the typeof() function and for
** the length(X) function if X is a blob. So we might as well use
** bogus content rather than reading content from disk. NULL works
** for text and blob and whatever is in the payloadSize64 variable
** will work for everything else. Content is also irrelevant if
** the content length is 0. */
zData = t<=13 ? (u8*)&payloadSize64 : 0;
sMem.zMalloc = 0;
/* Content is irrelevant for
** 1. the typeof() function,
** 2. the length(X) function if X is a blob, and
** 3. if the content length is zero.
** So we might as well use bogus content rather than reading
** content from disk. NULL will work for the value for strings
** and blobs and whatever is in the payloadSize64 variable
** will work for everything else. */
sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest);
}else{
memset(&sMem, 0, sizeof(sMem));
sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
&sMem);
pDest);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
zData = (u8*)sMem.z;
}
sqlite3VdbeSerialGet(zData, t, pDest);
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
** dynamically allocated space over to the pDest structure.
** This prevents a memory copy. */
if( sMem.zMalloc ){
assert( sMem.z==sMem.zMalloc );
assert( VdbeMemDynamic(pDest)==0 );
assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
pDest->flags &= ~(MEM_Ephem|MEM_Static);
pDest->flags |= MEM_Term;
pDest->z = sMem.z;
pDest->zMalloc = sMem.zMalloc;
sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
pDest->flags &= ~MEM_Ephem;
}
}
pDest->enc = encoding;
op_column_out:
Deephemeralize(pDest);
/* If the column value is an ephemeral string, go ahead and persist
** that string in case the cursor moves before the column value is
** used. The following code does the equivalent of Deephemeralize()
** but does it faster. */
if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){
fx = pDest->flags & (MEM_Str|MEM_Blob);
assert( fx!=0 );
zData = (const u8*)pDest->z;
len = pDest->n;
if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem;
memcpy(pDest->z, zData, len);
pDest->z[len] = 0;
pDest->z[len+1] = 0;
pDest->flags = fx|MEM_Term;
}
op_column_error:
UPDATE_MAX_BLOBSIZE(pDest);
REGISTER_TRACE(pOp->p3, pDest);
@ -2646,9 +2659,9 @@ case OP_MakeRecord: {
/* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
*/
if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
goto no_mem;
}
zNewRecord = (u8 *)pOut->z;
@ -2669,7 +2682,6 @@ case OP_MakeRecord: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pOut->n = (int)nByte;
pOut->flags = MEM_Blob;
pOut->xDel = 0;
if( nZero ){
pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
@ -3559,7 +3571,7 @@ case OP_SeekGT: { /* jump, in3 */
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & (MEM_Int|MEM_Real))==0 ){
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3);
@ -3582,7 +3594,7 @@ case OP_SeekGT: { /* jump, in3 */
** (x > 4.9) -> (x >= 5)
** (x <= 4.9) -> (x < 5)
*/
if( pIn3->r<(double)iKey ){
if( pIn3->u.r<(double)iKey ){
assert( OP_SeekGE==(OP_SeekGT-1) );
assert( OP_SeekLT==(OP_SeekLE-1) );
assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
@ -3591,7 +3603,7 @@ case OP_SeekGT: { /* jump, in3 */
/* If the approximation iKey is smaller than the actual real search
** term, substitute <= for < and > for >=. */
else if( pIn3->r>(double)iKey ){
else if( pIn3->u.r>(double)iKey ){
assert( OP_SeekLE==(OP_SeekLT+1) );
assert( OP_SeekGT==(OP_SeekGE+1) );
assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
@ -4404,7 +4416,7 @@ case OP_RowData: {
goto too_big;
}
}
if( sqlite3VdbeMemGrow(pOut, n, 0) ){
if( sqlite3VdbeMemClearAndResize(pOut, n) ){
goto no_mem;
}
pOut->n = n;
@ -4914,7 +4926,7 @@ case OP_IdxGE: { /* jump */
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
res = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
if( (pOp->opcode&1)==(OP_IdxLT&1) ){
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
@ -5684,11 +5696,7 @@ case OP_AggStep: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
ctx.pMem = pMem = &aMem[pOp->p3];
pMem->n++;
t.flags = MEM_Null;
t.z = 0;
t.zMalloc = 0;
t.xDel = 0;
t.db = db;
sqlite3VdbeMemInit(&t, db, MEM_Null);
ctx.pOut = &t;
ctx.isError = 0;
ctx.pColl = 0;

View File

@ -214,10 +214,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER

View File

@ -161,25 +161,28 @@ struct VdbeFrame {
** integer etc.) of the same value.
*/
struct Mem {
sqlite3 *db; /* The associated database connection */
char *z; /* String or BLOB value */
double r; /* Real value */
union {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
int nZero; /* Used when bit MEM_Zero is set in flags */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
} u;
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
int n; /* Number of characters in string value, excluding '\0' */
char *z; /* String or BLOB value */
/* ShallowCopy only needs to copy the information above */
char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
int szMalloc; /* Size of the zMalloc allocation */
int iPadding1; /* Padding for 8-byte alignment */
sqlite3 *db; /* The associated database connection */
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
#endif
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */
};
/* One or more of the following flags are set to indicate the validOK
@ -267,13 +270,13 @@ struct AuxData {
*/
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
CollSeq *pColl; /* Collating sequence */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip skip accumulator loading if true */
u8 skipFlag; /* Skip accumulator loading if true */
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
};
@ -415,8 +418,8 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeHalt(Vdbe*);
@ -433,6 +436,7 @@ void sqlite3VdbeMemSetInt64(Mem*, i64);
#else
void sqlite3VdbeMemSetDouble(Mem*, double);
#endif
void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
void sqlite3VdbeMemSetNull(Mem*);
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
void sqlite3VdbeMemSetRowSet(Mem*);
@ -447,14 +451,12 @@ int sqlite3VdbeMemNumerify(Mem*);
void sqlite3VdbeMemCast(Mem*,u8,u8);
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseExternal(Mem *p);
#define VdbeMemDynamic(X) \
(((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
#define VdbeMemReleaseExtern(X) \
if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int);
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
int sqlite3VdbeCloseStatement(Vdbe *, int);
void sqlite3VdbeFrameDelete(VdbeFrame*);
int sqlite3VdbeFrameRestore(VdbeFrame *);

View File

@ -215,6 +215,9 @@ int sqlite3_value_type(sqlite3_value* pVal){
** 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,
@ -614,11 +662,10 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
Mem *pMem = p->pMem;
assert( (pMem->flags & MEM_Agg)==0 );
if( nByte<=0 ){
sqlite3VdbeMemReleaseExternal(pMem);
pMem->flags = MEM_Null;
sqlite3VdbeMemSetNull(pMem);
pMem->z = 0;
}else{
sqlite3VdbeMemGrow(pMem, nByte, 0);
sqlite3VdbeMemClearAndResize(pMem, nByte);
pMem->flags = MEM_Agg;
pMem->u.pDef = p->pFunc;
if( pMem->z ){
@ -755,11 +802,22 @@ static const Mem *columnNullValue(void){
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
__attribute__((aligned(8)))
#endif
= {0, "", (double)0, {0}, 0, MEM_Null, 0,
= {
/* .u = */ {0},
/* .flags = */ MEM_Null,
/* .enc = */ 0,
/* .n = */ 0,
/* .z = */ 0,
/* .zMalloc = */ 0,
/* .szMalloc = */ 0,
/* .iPadding1 = */ 0,
/* .db = */ 0,
/* .xDel = */ 0,
#ifdef SQLITE_DEBUG
0, 0, /* pScopyFrom, pFiller */
/* .pScopyFrom = */ 0,
/* .pFiller = */ 0,
#endif
0, 0 };
};
return &nullMem;
}
@ -1125,6 +1183,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, (int)nData, xDel, 0);
}
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
@ -1166,6 +1238,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, (int)nData, xDel, enc);
}
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
sqlite3_stmt *pStmt,
@ -1185,7 +1273,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
break;
}
case SQLITE_FLOAT: {
rc = sqlite3_bind_double(pStmt, i, pValue->r);
rc = sqlite3_bind_double(pStmt, i, pValue->u.r);
break;
}
case SQLITE_BLOB: {

View File

@ -10,9 +10,7 @@
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -699,7 +697,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
sqlite3ValueFree((sqlite3_value*)p4);
}else{
Mem *p = (Mem*)p4;
sqlite3DbFree(db, p->zMalloc);
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
sqlite3DbFree(db, p);
}
break;
@ -1077,7 +1075,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
}else if( pMem->flags & MEM_Int ){
sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
}else if( pMem->flags & MEM_Real ){
sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r);
}else if( pMem->flags & MEM_Null ){
sqlite3_snprintf(nTemp, zTemp, "NULL");
}else{
@ -1227,16 +1225,16 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd;
Mem *pEnd = &p[N];
sqlite3 *db = p->db;
u8 malloc_failed = db->mallocFailed;
if( db->pnBytesFreed ){
for(pEnd=&p[N]; p<pEnd; p++){
sqlite3DbFree(db, p->zMalloc);
}
do{
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
}while( (++p)<pEnd );
return;
}
for(pEnd=&p[N]; p<pEnd; p++){
do{
assert( (&p[1])==pEnd || p[0].db==p[1].db );
assert( sqlite3VdbeCheckMemInvariants(p) );
@ -1258,13 +1256,13 @@ static void releaseMemArray(Mem *p, int N){
testcase( p->flags & MEM_RowSet );
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->zMalloc ){
}else if( p->szMalloc ){
sqlite3DbFree(db, p->zMalloc);
p->zMalloc = 0;
p->szMalloc = 0;
}
p->flags = MEM_Undefined;
}
}while( (++p)<pEnd );
db->mallocFailed = malloc_failed;
}
}
@ -1427,7 +1425,7 @@ int sqlite3VdbeList(
pMem->u.i = pOp->p3; /* P3 */
pMem++;
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
if( sqlite3VdbeMemClearAndResize(pMem, 32) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
@ -1443,7 +1441,7 @@ int sqlite3VdbeList(
pMem++;
if( p->explain==1 ){
if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
@ -1454,7 +1452,7 @@ int sqlite3VdbeList(
pMem++;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
@ -1607,7 +1605,7 @@ void sqlite3VdbeRewind(Vdbe *p){
/*
** Prepare a virtual machine for execution for the first time after
** creating the virtual machine. This involves things such
** as allocating stack space and initializing the program counter.
** as allocating registers and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
@ -1819,11 +1817,7 @@ static void closeAllCursors(Vdbe *p){
}
/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open. It also deletes the values of
** variables in the aVar[] array.
** Clean up the VM after a single run.
*/
static void Cleanup(Vdbe *p){
sqlite3 *db = p->db;
@ -2950,8 +2944,8 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
u64 v;
u32 i;
if( serial_type==7 ){
assert( sizeof(v)==sizeof(pMem->r) );
memcpy(&v, &pMem->r, sizeof(v));
assert( sizeof(v)==sizeof(pMem->u.r) );
memcpy(&v, &pMem->u.r, sizeof(v));
swapMixedEndianFloat(v);
}else{
v = pMem->u.i;
@ -3021,10 +3015,10 @@ static u32 SQLITE_NOINLINE serialGet(
swapMixedEndianFloat(t2);
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
swapMixedEndianFloat(x);
memcpy(&pMem->r, &x, sizeof(x));
pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real;
memcpy(&pMem->u.r, &x, sizeof(x));
pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
}
return 8;
}
@ -3086,7 +3080,6 @@ u32 sqlite3VdbeSerialGet(
static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
pMem->z = (char *)buf;
pMem->n = (serial_type-12)/2;
pMem->xDel = 0;
pMem->flags = aFlag[serial_type&1];
return pMem->n;
}
@ -3162,18 +3155,18 @@ void sqlite3VdbeRecordUnpack(
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;
while( idx<szHdr && u<p->nField && d<=nKey ){
while( idx<szHdr && d<=nKey ){
u32 serial_type;
idx += getVarint32(&aKey[idx], serial_type);
pMem->enc = pKeyInfo->enc;
pMem->db = pKeyInfo->db;
/* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
pMem->zMalloc = 0;
pMem->szMalloc = 0;
pMem->z = 0;
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
pMem++;
u++;
if( (++u)>=p->nField ) break;
}
assert( u<=pKeyInfo->nField + 1 );
p->nField = u;
@ -3210,7 +3203,7 @@ static int vdbeRecordCompareDebug(
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
/* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
/* Compilers may complain that mem1.u.i is potentially uninitialized.
** We could initialize it, as shown here, to silence those complaints.
@ -3253,7 +3246,7 @@ static int vdbeRecordCompareDebug(
*/
rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
if( rc!=0 ){
assert( mem1.zMalloc==0 ); /* See comment below */
assert( mem1.szMalloc==0 ); /* See comment below */
if( pKeyInfo->aSortOrder[i] ){
rc = -rc; /* Invert the result for DESC sort order. */
}
@ -3266,7 +3259,7 @@ static int vdbeRecordCompareDebug(
** the following assert(). If the assert() fails, it indicates a
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
*/
assert( mem1.zMalloc==0 );
assert( mem1.szMalloc==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 default_rc
@ -3305,8 +3298,8 @@ static int vdbeCompareMemString(
int n1, n2;
Mem c1;
Mem c2;
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null);
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
@ -3321,6 +3314,18 @@ static int vdbeCompareMemString(
}
}
/*
** Compare two blobs. Return negative, zero, or positive if the first
** is less than, equal to, or greater than the second, respectively.
** If one blob is a prefix of the other, then the shorter is the lessor.
*/
static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
if( c ) return c;
return pB1->n - pB2->n;
}
/*
** Compare the values contained by the two memory cells, returning
** negative, zero or positive if pMem1 is less than, equal to, or greater
@ -3331,7 +3336,6 @@ static int vdbeCompareMemString(
** Two NULL values are considered equal by this function.
*/
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
int rc;
int f1, f2;
int combined_flags;
@ -3359,14 +3363,14 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
return 0;
}
if( (f1&MEM_Real)!=0 ){
r1 = pMem1->r;
r1 = pMem1->u.r;
}else if( (f1&MEM_Int)!=0 ){
r1 = (double)pMem1->u.i;
}else{
return 1;
}
if( (f2&MEM_Real)!=0 ){
r2 = pMem2->r;
r2 = pMem2->u.r;
}else if( (f2&MEM_Int)!=0 ){
r2 = (double)pMem2->u.i;
}else{
@ -3406,11 +3410,7 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
}
/* Both values must be blobs. Compare using memcmp(). */
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
if( rc==0 ){
rc = pMem1->n - pMem2->n;
}
return rc;
return sqlite3BlobCompare(pMem1, pMem2);
}
@ -3476,7 +3476,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
*/
int sqlite3VdbeRecordCompare(
static int vdbeRecordCompareWithSkip(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
@ -3511,7 +3511,7 @@ int sqlite3VdbeRecordCompare(
i = 0;
}
VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
|| CORRUPT_DB );
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
@ -3531,9 +3531,9 @@ int sqlite3VdbeRecordCompare(
}else if( serial_type==7 ){
double rhs = (double)pRhs->u.i;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( mem1.r<rhs ){
if( mem1.u.r<rhs ){
rc = -1;
}else if( mem1.r>rhs ){
}else if( mem1.u.r>rhs ){
rc = +1;
}
}else{
@ -3555,11 +3555,11 @@ int sqlite3VdbeRecordCompare(
}else if( serial_type==0 ){
rc = -1;
}else{
double rhs = pRhs->r;
double rhs = pRhs->u.r;
double lhs;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
lhs = mem1.r;
lhs = mem1.u.r;
}else{
lhs = (double)mem1.u.i;
}
@ -3634,7 +3634,7 @@ int sqlite3VdbeRecordCompare(
rc = -rc;
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
assert( mem1.zMalloc==0 ); /* See comment below */
assert( mem1.szMalloc==0 ); /* See comment below */
return rc;
}
@ -3647,7 +3647,7 @@ int sqlite3VdbeRecordCompare(
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
assert( mem1.zMalloc==0 );
assert( mem1.szMalloc==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 default_rc
@ -3658,6 +3658,13 @@ int sqlite3VdbeRecordCompare(
);
return pPKey2->default_rc;
}
int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
}
/*
** This function is an optimized version of sqlite3VdbeRecordCompare()
@ -3670,8 +3677,7 @@ int sqlite3VdbeRecordCompare(
*/
static int vdbeRecordCompareInt(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */
UnpackedRecord *pPKey2 /* Right key */
){
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
int serial_type = ((const u8*)pKey1)[1];
@ -3680,9 +3686,7 @@ static int vdbeRecordCompareInt(
u64 x;
i64 v = pPKey2->aMem[0].u.i;
i64 lhs;
UNUSED_PARAMETER(bSkip);
assert( bSkip==0 );
assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
switch( serial_type ){
case 1: { /* 1-byte signed integer */
@ -3732,10 +3736,10 @@ static int vdbeRecordCompareInt(
** (as gcc is clever enough to combine the two like cases). Other
** compilers might be similar. */
case 0: case 7:
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
default:
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
}
if( v>lhs ){
@ -3745,7 +3749,7 @@ static int vdbeRecordCompareInt(
}else if( pPKey2->nField>1 ){
/* The first fields of the two keys are equal. Compare the trailing
** fields. */
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
/* The first fields of the two keys are equal and there are no trailing
** fields. Return pPKey2->default_rc in this case. */
@ -3764,17 +3768,13 @@ static int vdbeRecordCompareInt(
*/
static int vdbeRecordCompareString(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip
UnpackedRecord *pPKey2 /* Right key */
){
const u8 *aKey1 = (const u8*)pKey1;
int serial_type;
int res;
UNUSED_PARAMETER(bSkip);
assert( bSkip==0 );
getVarint32(&aKey1[1], serial_type);
if( serial_type<12 ){
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
}else if( !(serial_type & 0x01) ){
@ -3796,7 +3796,7 @@ static int vdbeRecordCompareString(
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
res = pPKey2->default_rc;
}
@ -3878,8 +3878,6 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
u32 lenRowid; /* Size of the rowid */
Mem m, v;
UNUSED_PARAMETER(db);
/* Get the size of the index entry. Only indices entries of less
** than 2GiB are support - anything large must be database corruption.
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
@ -3891,7 +3889,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
/* Read in the complete content of the index entry */
memset(&m, 0, sizeof(m));
sqlite3VdbeMemInit(&m, db, 0);
rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
if( rc ){
return rc;
@ -3934,7 +3932,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Jump here if database corruption is detected after m has been
** allocated. Free the m object and return SQLITE_CORRUPT. */
idx_rowid_corruption:
testcase( m.zMalloc!=0 );
testcase( m.szMalloc!=0 );
sqlite3VdbeMemRelease(&m);
return SQLITE_CORRUPT_BKPT;
}
@ -3951,6 +3949,7 @@ idx_rowid_corruption:
** of the keys prior to the final rowid, not the entire key.
*/
int sqlite3VdbeIdxKeyCompare(
sqlite3 *db, /* Database connection */
VdbeCursor *pC, /* The cursor to compare against */
UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */
@ -3969,12 +3968,12 @@ int sqlite3VdbeIdxKeyCompare(
*res = 0;
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
sqlite3VdbeMemInit(&m, db, 0);
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
if( rc ){
return rc;
}
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}

View File

@ -26,11 +26,20 @@
** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
*/
int sqlite3VdbeCheckMemInvariants(Mem *p){
/* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
** function for Mem.z
/* If MEM_Dyn is set then Mem.xDel!=0.
** Mem.xDel is might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
/* MEM_Dyn may only be set if Mem.szMalloc==0 */
assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
/* Cannot be both MEM_Int and MEM_Real at the same time */
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@ -40,15 +49,14 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
** (3) An ephemeral string or blob
** (4) A static string or blob
*/
if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){
assert(
((p->z==p->zMalloc)? 1 : 0) +
((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) +
((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
);
}
return 1;
}
#endif
@ -102,7 +110,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
** blob if bPreserve is true. If bPreserve is false, any prior content
** in pMem->z is discarded.
*/
int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
assert( sqlite3VdbeCheckMemInvariants(pMem) );
assert( (pMem->flags&MEM_RowSet)==0 );
@ -111,20 +119,24 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
testcase( bPreserve && pMem->z==0 );
if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
assert( pMem->szMalloc==0
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
if( pMem->szMalloc<n ){
if( n<32 ) n = 32;
if( bPreserve && pMem->z==pMem->zMalloc ){
if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
bPreserve = 0;
}else{
sqlite3DbFree(pMem->db, pMem->zMalloc);
if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
if( pMem->zMalloc==0 ){
VdbeMemReleaseExtern(pMem);
sqlite3VdbeMemSetNull(pMem);
pMem->z = 0;
pMem->flags = MEM_Null;
pMem->szMalloc = 0;
return SQLITE_NOMEM;
}else{
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
}
@ -138,15 +150,36 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
pMem->z = pMem->zMalloc;
pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
pMem->xDel = 0;
return SQLITE_OK;
}
/*
** Make the given Mem object MEM_Dyn. In other words, make it so
** that any TEXT or BLOB content is stored in memory obtained from
** malloc(). In this way, we know that the memory is safe to be
** overwritten or altered.
** Change the pMem->zMalloc allocation to be at least szNew bytes.
** If pMem->zMalloc already meets or exceeds the requested size, this
** routine is a no-op.
**
** Any prior string or blob content in the pMem object may be discarded.
** The pMem->xDel destructor is called, if it exists. Though MEM_Str
** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
** values are preserved.
**
** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
** if unable to complete the resizing.
*/
int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
assert( szNew>=0 );
if( pMem->szMalloc<szNew ){
return sqlite3VdbeMemGrow(pMem, szNew, 0);
}
assert( (pMem->flags & MEM_Dyn)==0 );
pMem->z = pMem->zMalloc;
pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
return SQLITE_OK;
}
/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
@ -156,7 +189,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
assert( (pMem->flags&MEM_RowSet)==0 );
ExpandBlob(pMem);
f = pMem->flags;
if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
return SQLITE_NOMEM;
}
@ -254,7 +287,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
return SQLITE_NOMEM;
}
@ -268,7 +301,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
}else{
assert( fg & MEM_Real );
sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
}
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
@ -301,8 +334,8 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
ctx.pMem = pMem;
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
sqlite3DbFree(pMem->db, pMem->zMalloc);
assert( (pMem->flags & MEM_Dyn)==0 );
if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
memcpy(pMem, &t, sizeof(t));
rc = ctx.isError;
}
@ -310,29 +343,34 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
}
/*
** If the memory cell contains a string value that must be freed by
** invoking an external callback, free it now. Calling this function
** does not free any Mem.zMalloc buffer.
** If the memory cell contains a value that must be freed by
** invoking the external callback in Mem.xDel, then this routine
** will free that value. It also sets Mem.flags to MEM_Null.
**
** The VdbeMemReleaseExtern() macro invokes this routine if only if there
** is work for this routine to do.
** This is a helper routine for sqlite3VdbeMemSetNull() and
** for sqlite3VdbeMemRelease(). Use those other routines as the
** entry point for releasing Mem resources.
*/
void sqlite3VdbeMemReleaseExternal(Mem *p){
static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
assert( VdbeMemDynamic(p) );
if( p->flags&MEM_Agg ){
sqlite3VdbeMemFinalize(p, p->u.pDef);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else if( p->flags&MEM_Dyn ){
testcase( p->flags & MEM_Dyn );
}
if( p->flags&MEM_Dyn ){
assert( (p->flags&MEM_RowSet)==0 );
assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
p->xDel((void *)p->z);
p->xDel = 0;
}else if( p->flags&MEM_RowSet ){
sqlite3RowSetClear(p->u.pRowSet);
}else if( p->flags&MEM_Frame ){
sqlite3VdbeMemSetNull(p);
VdbeFrame *pFrame = p->u.pFrame;
pFrame->pParent = pFrame->v->pDelFrame;
pFrame->v->pDelFrame = pFrame;
}
p->flags = MEM_Null;
}
/*
@ -340,33 +378,35 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
** by p->xDel and memory in p->zMalloc.
**
** This is a helper routine invoked by sqlite3VdbeMemRelease() in
** the uncommon case when there really is memory in p that is
** need of freeing.
** the unusual case where there really is memory in p that needs
** to be freed.
*/
static SQLITE_NOINLINE void vdbeMemRelease(Mem *p){
static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
if( VdbeMemDynamic(p) ){
sqlite3VdbeMemReleaseExternal(p);
vdbeMemClearExternAndSetNull(p);
}
if( p->zMalloc ){
if( p->szMalloc ){
sqlite3DbFree(p->db, p->zMalloc);
p->zMalloc = 0;
p->szMalloc = 0;
}
p->z = 0;
}
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.flags==MEM_Str).
** Release any memory resources held by the Mem. Both the memory that is
** free by Mem.xDel and the Mem.zMalloc allocation are freed.
**
** Use this routine prior to clean up prior to abandoning a Mem, or to
** reset a Mem back to its minimum memory utilization.
**
** Use sqlite3VdbeMemSetNull() to release just the Mem.xDel space
** prior to inserting new content into the Mem.
*/
void sqlite3VdbeMemRelease(Mem *p){
assert( sqlite3VdbeCheckMemInvariants(p) );
if( VdbeMemDynamic(p) || p->zMalloc ){
vdbeMemRelease(p);
}else{
p->z = 0;
if( VdbeMemDynamic(p) || p->szMalloc ){
vdbeMemClear(p);
}
assert( p->xDel==0 );
}
/*
@ -418,7 +458,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
if( flags & MEM_Int ){
return pMem->u.i;
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->r);
return doubleToInt64(pMem->u.r);
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value = 0;
assert( pMem->z || pMem->n==0 );
@ -439,7 +479,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
return pMem->r;
return pMem->u.r;
}else if( pMem->flags & MEM_Int ){
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
@ -458,12 +498,13 @@ double sqlite3VdbeRealValue(Mem *pMem){
** MEM_Int if we can.
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
i64 ix;
assert( pMem->flags & MEM_Real );
assert( (pMem->flags & MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = doubleToInt64(pMem->r);
ix = doubleToInt64(pMem->u.r);
/* Only mark the value as an integer if
**
@ -475,11 +516,9 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
** the second condition under the assumption that addition overflow causes
** values to wrap around.
*/
if( pMem->r==(double)pMem->u.i
&& pMem->u.i>SMALLEST_INT64
&& pMem->u.i<LARGEST_INT64
){
pMem->flags |= MEM_Int;
if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
pMem->u.i = ix;
MemSetTypeFlag(pMem, MEM_Int);
}
}
@ -504,7 +543,7 @@ int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->r = sqlite3VdbeRealValue(pMem);
pMem->u.r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
@ -524,7 +563,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
pMem->r = sqlite3VdbeRealValue(pMem);
pMem->u.r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
sqlite3VdbeIntegerAffinity(pMem);
}
@ -578,20 +617,37 @@ void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
}
}
/*
** Initialize bulk memory to be a consistent Mem object.
**
** The minimum amount of initialization feasible is performed.
*/
void sqlite3VdbeMemInit(Mem *pMem, sqlite3 *db, u16 flags){
assert( (flags & ~MEM_TypeMask)==0 );
pMem->flags = flags;
pMem->db = db;
pMem->szMalloc = 0;
}
/*
** Delete any previous value and set the value stored in *pMem to NULL.
**
** This routine calls the Mem.xDel destructor to dispose of values that
** require the destructor. But it preserves the Mem.zMalloc memory allocation.
** To free all resources, use sqlite3VdbeMemRelease(), which both calls this
** routine to invoke the destructor and deallocates Mem.zMalloc.
**
** Use this routine to reset the Mem prior to insert a new value.
**
** Use sqlite3VdbeMemRelease() to complete erase the Mem prior to abandoning it.
*/
void sqlite3VdbeMemSetNull(Mem *pMem){
if( pMem->flags & MEM_Frame ){
VdbeFrame *pFrame = pMem->u.pFrame;
pFrame->pParent = pFrame->v->pDelFrame;
pFrame->v->pDelFrame = pFrame;
if( VdbeMemDynamic(pMem) ){
vdbeMemClearExternAndSetNull(pMem);
}else{
pMem->flags = MEM_Null;
}
if( pMem->flags & MEM_RowSet ){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
}
void sqlite3ValueSetNull(sqlite3_value *p){
sqlite3VdbeMemSetNull((Mem*)p);
@ -608,14 +664,7 @@ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
if( n<0 ) n = 0;
pMem->u.nZero = n;
pMem->enc = SQLITE_UTF8;
#ifdef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemGrow(pMem, n, 0);
if( pMem->z ){
pMem->n = n;
memset(pMem->z, 0, n);
}
#endif
pMem->z = 0;
}
/*
@ -624,7 +673,7 @@ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
** a 64-bit integer.
*/
static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemReleaseExternal(pMem);
sqlite3VdbeMemSetNull(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
}
@ -648,11 +697,9 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
** manifest type REAL.
*/
void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
if( sqlite3IsNaN(val) ){
sqlite3VdbeMemSetNull(pMem);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
sqlite3VdbeMemSetNull(pMem);
if( !sqlite3IsNaN(val) ){
pMem->u.r = val;
pMem->flags = MEM_Real;
}
}
@ -670,10 +717,11 @@ void sqlite3VdbeMemSetRowSet(Mem *pMem){
pMem->zMalloc = sqlite3DbMallocRaw(db, 64);
if( db->mallocFailed ){
pMem->flags = MEM_Null;
pMem->szMalloc = 0;
}else{
assert( pMem->zMalloc );
pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
sqlite3DbMallocSize(db, pMem->zMalloc));
pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc);
pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc);
assert( pMem->u.pRowSet!=0 );
pMem->flags = MEM_RowSet;
}
@ -730,9 +778,9 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
*/
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
assert( (pFrom->flags & MEM_RowSet)==0 );
VdbeMemReleaseExtern(pTo);
assert( pTo->db==pFrom->db );
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
if( (pFrom->flags&MEM_Static)==0 ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static );
@ -748,11 +796,9 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
assert( (pFrom->flags & MEM_RowSet)==0 );
VdbeMemReleaseExtern(pTo);
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
pTo->xDel = 0;
if( pTo->flags&(MEM_Str|MEM_Blob) ){
if( 0==(pFrom->flags&MEM_Static) ){
pTo->flags |= MEM_Ephem;
@ -777,8 +823,7 @@ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
sqlite3VdbeMemRelease(pTo);
memcpy(pTo, pFrom, sizeof(Mem));
pFrom->flags = MEM_Null;
pFrom->xDel = 0;
pFrom->zMalloc = 0;
pFrom->szMalloc = 0;
}
/*
@ -825,7 +870,8 @@ int sqlite3VdbeMemSetStr(
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){}
nByte = sqlite3Strlen30(z);
if( nByte>iLimit ) nByte = iLimit+1;
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
}
@ -844,14 +890,14 @@ int sqlite3VdbeMemSetStr(
if( nByte>iLimit ){
return SQLITE_TOOBIG;
}
if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
if( sqlite3VdbeMemClearAndResize(pMem, nAlloc) ){
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
}else if( xDel==SQLITE_DYNAMIC ){
sqlite3VdbeMemRelease(pMem);
pMem->zMalloc = pMem->z = (char *)z;
pMem->xDel = 0;
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->z = (char *)z;
@ -883,8 +929,11 @@ int sqlite3VdbeMemSetStr(
** key is true to get the key or false to get data. The result is written
** into the pMem element.
**
** The pMem structure is assumed to be uninitialized. Any prior content
** is overwritten without being freed.
** The pMem object must have been initialized. This routine will use
** pMem->zMalloc to hold the content from the btree, if possible. New
** pMem->zMalloc space will be allocated if necessary. The calling routine
** is responsible for making sure that the pMem object is eventually
** destroyed.
**
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
@ -901,6 +950,7 @@ int sqlite3VdbeMemFromBtree(
int rc = SQLITE_OK; /* Return code */
assert( sqlite3BtreeCursorIsValid(pCur) );
assert( !VdbeMemDynamic(pMem) );
/* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
** that both the BtShared and database handle mutexes are held. */
@ -913,23 +963,25 @@ int sqlite3VdbeMemFromBtree(
assert( zData!=0 );
if( offset+amt<=available ){
sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
pMem->flags = MEM_Blob|MEM_Term;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
}else{
pMem->flags = MEM_Null;
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
pMem->flags = MEM_Blob|MEM_Term;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
}
}
}
@ -1153,14 +1205,14 @@ static int valueFromExpr(
&& pVal!=0
){
sqlite3VdbeMemNumerify(pVal);
if( pVal->u.i==SMALLEST_INT64 ){
pVal->flags &= ~MEM_Int;
pVal->flags |= MEM_Real;
pVal->r = (double)SMALLEST_INT64;
if( pVal->flags & MEM_Real ){
pVal->u.r = -pVal->u.r;
}else if( pVal->u.i==SMALLEST_INT64 ){
pVal->u.r = -(double)SMALLEST_INT64;
MemSetTypeFlag(pVal, MEM_Real);
}else{
pVal->u.i = -pVal->u.i;
}
pVal->r = -pVal->r;
sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}else if( op==TK_NULL ){
@ -1468,7 +1520,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
Mem *aMem = pRec->aMem;
sqlite3 *db = aMem[0].db;
for(i=0; i<nCol; i++){
sqlite3DbFree(db, aMem[i].zMalloc);
if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc);
}
sqlite3KeyInfoUnref(pRec->pKeyInfo);
sqlite3DbFree(db, pRec);

View File

@ -602,8 +602,11 @@ static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){
static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){
int rc = SQLITE_OK;
if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){
rc = sqlite3OsFetch(pFile->pFd, 0, (int)pFile->iEof, (void**)pp);
testcase( rc!=SQLITE_OK );
sqlite3_file *pFd = pFile->pFd;
if( pFd->pMethods->iVersion>=3 ){
rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp);
testcase( rc!=SQLITE_OK );
}
}
return rc;
}
@ -758,7 +761,7 @@ static int vdbeSorterCompare(
if( pKey2 ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
}
/*
@ -1121,7 +1124,7 @@ void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
** the specific VFS implementation.
*/
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
if( nByte<=(i64)(db->nMaxSorterMmap) ){
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
int rc = sqlite3OsTruncate(pFd, nByte);
if( rc==SQLITE_OK ){
void *p = 0;
@ -2458,7 +2461,7 @@ int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
void *pKey; int nKey; /* Sorter key to copy into pOut */
pKey = vdbeSorterRowkey(pSorter, &nKey);
if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){
if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){
return SQLITE_NOMEM;
}
pOut->n = nKey;
@ -2514,6 +2517,6 @@ int sqlite3VdbeSorterCompare(
}
}
*pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2, 0);
*pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
return SQLITE_OK;
}

View File

@ -127,7 +127,7 @@ char *sqlite3VdbeExpandSql(
}else if( pVar->flags & MEM_Int ){
sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r);
}else if( pVar->flags & MEM_Str ){
int nOut; /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16

View File

@ -1913,7 +1913,7 @@ static void whereKeyStats(
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
do{
iTest = (iMin+i)/2;
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
if( res<0 ){
iMin = iTest+1;
}else{
@ -1928,16 +1928,16 @@ static void whereKeyStats(
if( res==0 ){
/* If (res==0) is true, then sample $i must be equal to pRec */
assert( i<pIdx->nSample );
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
|| pParse->db->mallocFailed );
}else{
/* Otherwise, pRec must be smaller than sample $i and larger than
** sample ($i-1). */
assert( i==pIdx->nSample
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
|| pParse->db->mallocFailed );
assert( i==0
|| sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
|| sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
|| pParse->db->mallocFailed );
}
#endif /* ifdef SQLITE_DEBUG */
@ -4560,6 +4560,7 @@ static int indexMightHelpWithOrderBy(
Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
if( pExpr->op!=TK_COLUMN ) return 0;
if( pExpr->iTable==iCursor ){
if( pExpr->iColumn<0 ) return 1;
for(jj=0; jj<pIndex->nKeyCol; jj++){
if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
}

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

@ -481,5 +481,19 @@ do_execsql_test 6.0 {
FROM abc;
} {hardware hardware hardware}
# Here is a test for a query-planner problem reported on the SQLite
# mailing list on 2014-09-18 by "Merike". Beginning with version 3.8.0,
# a separate sort was being used rather than using the single-column
# index. This was due to an oversight in the indexMightHelpWithOrderby()
# routine in where.c.
#
do_execsql_test 7.0 {
CREATE TABLE t7(a,b);
CREATE INDEX t7a ON t7(a);
CREATE INDEX t7ab ON t7(a,b);
EXPLAIN QUERY PLAN
SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
} {~/ORDER BY/}
finish_test

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

45
test/sort5.test Normal file
View File

@ -0,0 +1,45 @@
# 2014 September 15.
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sort5
#-------------------------------------------------------------------------
# Verify that sorting works with a version 1 sqlite3_io_methods structure.
#
testvfs tvfs -iversion 1 -default true
reset_db
do_execsql_test 1.0 {
PRAGMA mmap_size = 10000000;
PRAGMA cache_size = 10;
CREATE TABLE t1(a, b);
} {0}
do_test 1.1 {
execsql BEGIN
for {set i 0} {$i < 2000} {incr i} {
execsql { INSERT INTO t1 VALUES($i, randomblob(2000)) }
}
execsql COMMIT
} {}
do_execsql_test 1.2 {
CREATE INDEX i1 ON t1(b);
}
db close
tvfs delete
finish_test

View File

@ -103,5 +103,50 @@ do_execsql_test 2.2 {
LIMIT (SELECT a FROM t5)
} {2 3 3 6 4 10}
############################################################################
# Ticket http://www.sqlite.org/src/info/d11a6e908f (2014-09-20)
# Query planner fault on three-way nested join with compound inner SELECT
#
do_execsql_test 3.0 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1 (id INTEGER PRIMARY KEY, data TEXT);
INSERT INTO t1(id,data) VALUES(9,'nine-a');
INSERT INTO t1(id,data) VALUES(10,'ten-a');
INSERT INTO t1(id,data) VALUES(11,'eleven-a');
CREATE TABLE t2 (id INTEGER PRIMARY KEY, data TEXT);
INSERT INTO t2(id,data) VALUES(9,'nine-b');
INSERT INTO t2(id,data) VALUES(10,'ten-b');
INSERT INTO t2(id,data) VALUES(11,'eleven-b');
SELECT id FROM (
SELECT id,data FROM (
SELECT * FROM t1 UNION ALL SELECT * FROM t2
)
WHERE id=10 ORDER BY data
);
} {10 10}
do_execsql_test 3.1 {
SELECT data FROM (
SELECT 'dummy', data FROM (
SELECT data FROM t1 UNION ALL SELECT data FROM t1
) ORDER BY data
);
} {eleven-a eleven-a nine-a nine-a ten-a ten-a}
do_execsql_test 3.2 {
DROP TABLE IF EXISTS t3;
DROP TABLE IF EXISTS t4;
CREATE TABLE t3(id INTEGER, data TEXT);
CREATE TABLE t4(id INTEGER, data TEXT);
INSERT INTO t3 VALUES(4, 'a'),(2,'c');
INSERT INTO t4 VALUES(3, 'b'),(1,'d');
SELECT data, id FROM (
SELECT id, data FROM (
SELECT * FROM t3 UNION ALL SELECT * FROM t4
) ORDER BY data
);
} {a 4 b 3 c 2 d 1}
finish_test

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

@ -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

View File

@ -510,7 +510,7 @@ static void decode_btree_page(
int main(int argc, char **argv){
struct stat sbuf;
unsigned char zPgSz[2];
unsigned char zPgSz[4];
if( argc<2 ){
fprintf(stderr,"Usage: %s FILENAME ?PAGE? ...\n", argv[0]);
exit(1);
@ -522,9 +522,9 @@ int main(int argc, char **argv){
}
zPgSz[0] = 0;
zPgSz[1] = 0;
lseek(fd, 10, SEEK_SET);
read(fd, zPgSz, 2);
pagesize = zPgSz[0]*256 + zPgSz[1];
lseek(fd, 8, SEEK_SET);
read(fd, zPgSz, 4);
pagesize = zPgSz[1]*65536 + zPgSz[2]*256 + zPgSz[3];
if( pagesize==0 ) pagesize = 1024;
printf("Pagesize: %d\n", pagesize);
fstat(fd, &sbuf);