Upgraded SQLite 3 library to version 3.3.13

This commit is contained in:
Ilia Alshanetsky 2007-02-20 00:09:43 +00:00
parent c6402df3a7
commit 03e5b080a3
21 changed files with 1588 additions and 1275 deletions

2
NEWS
View file

@ -4,7 +4,7 @@ PHP NEWS
- Upgraded libraries bundled in the Windows distribution. (Edin)
. c-client (imap) to version 2006e
. libpq (PostgreSQL) to version 8.2.3
- Upgraded SQLite 3 to version 3.3.12 (Ilia)
- Upgraded SQLite 3 to version 3.3.13 (Ilia)
- Upgraded PCRE to version 7.0 (Nuno)
- Added --ri switch to CLI which allows to check extension information. (Marcus)
- Added tidyNode::getParent() method (John, Nuno)

View file

@ -1 +1 @@
3.3.12
3.3.13

View file

@ -5890,6 +5890,7 @@ int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){
** aResult[7] = Header size in bytes
** aResult[8] = Local payload size
** aResult[9] = Parent page number
** aResult[10]= Page number of the first overflow page
**
** This routine is used for testing and debugging only.
*/
@ -5938,6 +5939,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
}else{
aResult[9] = pPage->pParent->pgno;
}
if( tmpCur.info.iOverflow ){
aResult[10] = get4byte(&tmpCur.info.pCell[tmpCur.info.iOverflow]);
}else{
aResult[10] = 0;
}
releaseTempCursor(&tmpCur);
return SQLITE_OK;
}

View file

@ -1222,6 +1222,10 @@ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite3FindCollSeq(). This routine
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
sqlite3 *db = pParse->db;
@ -2457,7 +2461,7 @@ void sqlite3CreateIndex(
const char *zColName = pListItem->zName;
Column *pTabCol;
int requestedSortOrder;
char *zColl; /* Collation sequence */
char *zColl; /* Collation sequence name */
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@ -2467,6 +2471,12 @@ void sqlite3CreateIndex(
pTab->zName, zColName);
goto exit_create_index;
}
/* TODO: Add a test to make sure that the same column is not named
** more than once within the same index. Only the first instance of
** the column will ever be used by the optimizer. Note that using the
** same column more than once cannot be an error because that would
** break backwards compatibility - it needs to be a warning.
*/
pIndex->aiColumn[i] = j;
if( pListItem->pExpr ){
assert( pListItem->pExpr->pColl );

View file

@ -195,6 +195,11 @@ static CollSeq *findCollSeqEntry(
**
** If the entry specified is not found and 'create' is true, then create a
** new entry. Otherwise return NULL.
**
** A separate function sqlite3LocateCollSeq() is a wrapper around
** this routine. sqlite3LocateCollSeq() invokes the collation factory
** if necessary and generates an error message if the collating sequence
** cannot be found.
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db,

View file

@ -106,7 +106,8 @@ void sqlite3DeleteFrom(
AuthContext sContext; /* Authorization context */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
int iDb;
int iDb; /* Database number */
int memCnt = 0; /* Memory cell used for change counting */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
@ -204,7 +205,8 @@ void sqlite3DeleteFrom(
** we are counting rows.
*/
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
memCnt = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
@ -221,7 +223,7 @@ void sqlite3DeleteFrom(
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
addr2 = sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
@ -251,7 +253,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* End the database scan loop.
@ -354,6 +356,7 @@ void sqlite3DeleteFrom(
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);

View file

@ -49,6 +49,24 @@ char sqlite3ExprAffinity(Expr *pExpr){
return pExpr->affinity;
}
/*
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken. Return a pointer to the revised expression.
** The collating sequence is marked as "explicit" using the EP_ExpCollate
** flag. An explicit collating sequence will override implicit
** collating sequences.
*/
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
CollSeq *pColl;
if( pExpr==0 ) return 0;
pColl = sqlite3LocateCollSeq(pParse, (char*)pName->z, pName->n);
if( pColl ){
pExpr->pColl = pColl;
pExpr->flags |= EP_ExpCollate;
}
return pExpr;
}
/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
@ -158,9 +176,20 @@ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
** type.
*/
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pLeft);
if( !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pRight);
CollSeq *pColl;
assert( pLeft );
assert( pRight );
if( pLeft->flags & EP_ExpCollate ){
assert( pLeft->pColl );
pColl = pLeft->pColl;
}else if( pRight->flags & EP_ExpCollate ){
assert( pRight->pColl );
pColl = pRight->pColl;
}else{
pColl = sqlite3ExprCollSeq(pParse, pLeft);
if( !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pRight);
}
}
return pColl;
}
@ -205,8 +234,18 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
if( pToken ){
assert( pToken->dyn==0 );
pNew->span = pNew->token = *pToken;
}else if( pLeft && pRight ){
sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
}else if( pLeft ){
if( pRight ){
sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
if( pRight->flags && EP_ExpCollate ){
pNew->flags |= EP_ExpCollate;
pNew->pColl = pRight->pColl;
}
}
if( pLeft->flags && EP_ExpCollate ){
pNew->flags |= EP_ExpCollate;
pNew->pColl = pLeft->pColl;
}
}
return pNew;
}
@ -890,7 +929,9 @@ static int lookupName(
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->affinity = pTab->aCol[j].affinity;
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
if( (pExpr->flags & EP_ExpCollate)==0 ){
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
}
if( i<pSrcList->nSrc-1 ){
if( pItem[1].jointype & JT_NATURAL ){
/* If this match occurred in the left table of a natural join,
@ -946,7 +987,9 @@ static int lookupName(
cnt++;
pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
pExpr->affinity = pTab->aCol[iCol].affinity;
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
if( (pExpr->flags & EP_ExpCollate)==0 ){
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
}
pExpr->pTab = pTab;
break;
}
@ -1046,7 +1089,7 @@ static int lookupName(
n = sizeof(Bitmask)*8-1;
}
assert( pMatch->iCursor==pExpr->iTable );
pMatch->colUsed |= 1<<n;
pMatch->colUsed |= ((Bitmask)1)<<n;
}
lookupname_end:

View file

@ -271,6 +271,25 @@ static void randomFunc(
sqlite3_result_int64(context, r);
}
/*
** Implementation of randomblob(N). Return a random blob
** that is N bytes long.
*/
static void randomBlob(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int n;
unsigned char *p;
assert( argc==1 );
n = sqlite3_value_int(argv[0]);
if( n<1 ) n = 1;
p = sqlite3_malloc(n);
sqlite3Randomness(n, p);
sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
}
/*
** Implementation of the last_insert_rowid() SQL function. The return
** value is the same as the sqlite3_last_insert_rowid() API function.
@ -547,6 +566,12 @@ static void versionFunc(
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/*
** EXPERIMENTAL - This is not an official function. The interface may
@ -572,10 +597,6 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
break;
}
case SQLITE_BLOB: {
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
char *zText = 0;
int nBlob = sqlite3_value_bytes(argv[0]);
char const *zBlob = sqlite3_value_blob(argv[0]);
@ -621,11 +642,41 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
/*
** The hex() function. Interpret the argument as a blob. Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i, n;
const unsigned char *pBlob;
char *zHex, *z;
assert( argc==1 );
pBlob = sqlite3_value_blob(argv[0]);
n = sqlite3_value_bytes(argv[0]);
z = zHex = sqlite3_malloc(n*2 + 1);
if( zHex==0 ) return;
for(i=0; i<n; i++, pBlob++){
unsigned char c = *pBlob;
*(z++) = hexdigits[(c>>4)&0xf];
*(z++) = hexdigits[c&0xf];
}
*z = 0;
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
}
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
*/
static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
static void soundexFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
char zResult[8];
const u8 *zIn;
int i, j;
@ -1021,8 +1072,10 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
{ "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
{ "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
{ "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
{ "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },

View file

@ -28,9 +28,9 @@
#define OP_NotNull 67 /* same as TK_NOTNULL */
#define OP_Rowid 23
#define OP_Real 126 /* same as TK_FLOAT */
#define OP_String8 88 /* same as TK_STRING */
#define OP_String8 89 /* same as TK_STRING */
#define OP_And 62 /* same as TK_AND */
#define OP_BitNot 87 /* same as TK_BITNOT */
#define OP_BitNot 88 /* same as TK_BITNOT */
#define OP_VFilter 24
#define OP_NullRow 25
#define OP_Noop 26
@ -84,8 +84,8 @@
#define OP_Halt 65
#define OP_Expire 74
#define OP_Or 61 /* same as TK_OR */
#define OP_DropIndex 86
#define OP_IdxInsert 89
#define OP_DropIndex 85
#define OP_IdxInsert 87
#define OP_ShiftLeft 77 /* same as TK_LSHIFT */
#define OP_FifoRead 90
#define OP_Column 91
@ -117,7 +117,7 @@
#define OP_VOpen 114
#define OP_AggFinal 115
#define OP_OpenWrite 116
#define OP_Negative 85 /* same as TK_UMINUS */
#define OP_Negative 86 /* same as TK_UMINUS */
#define OP_Le 71 /* same as TK_LE */
#define OP_VNext 117
#define OP_AbsValue 118
@ -154,7 +154,7 @@
#define NOPUSH_MASK_2 0xedaf
#define NOPUSH_MASK_3 0xf1eb
#define NOPUSH_MASK_4 0xfffe
#define NOPUSH_MASK_5 0x62ef
#define NOPUSH_MASK_5 0x61ef
#define NOPUSH_MASK_6 0xbfcf
#define NOPUSH_MASK_7 0x23bf
#define NOPUSH_MASK_8 0xf87b

View file

@ -565,7 +565,7 @@ static sqlite3LockingStyle sqlite3TestLockingStyle(const char *filePath,
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if (fcntl(fd, F_GETLK, (int) &lockInfo) != -1) {
if (fcntl(fd, F_GETLK, &lockInfo) != -1) {
return posixLockingStyle;
}
@ -1000,10 +1000,14 @@ int sqlite3UnixIsDirWritable(char *zBuf){
*/
static int seekAndRead(unixFile *id, void *pBuf, int cnt){
int got;
i64 newOffset;
#ifdef USE_PREAD
got = pread(id->h, pBuf, cnt, id->offset);
#else
lseek(id->h, id->offset, SEEK_SET);
newOffset = lseek(id->h, id->offset, SEEK_SET);
if( newOffset!=id->offset ){
return -1;
}
got = read(id->h, pBuf, cnt);
#endif
if( got>0 ){
@ -1043,10 +1047,14 @@ static int unixRead(OsFile *id, void *pBuf, int amt){
*/
static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
int got;
i64 newOffset;
#ifdef USE_PREAD
got = pwrite(id->h, pBuf, cnt, id->offset);
#else
lseek(id->h, id->offset, SEEK_SET);
newOffset = lseek(id->h, id->offset, SEEK_SET);
if( newOffset!=id->offset ){
return -1;
}
got = write(id->h, pBuf, cnt);
#endif
if( got>0 ){
@ -1160,13 +1168,26 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
#if HAVE_FULLFSYNC
if( fullSync ){
rc = fcntl(fd, F_FULLFSYNC, 0);
}else
#endif /* HAVE_FULLFSYNC */
}else{
rc = 1;
}
/* If the FULLFSYNC failed, fall back to attempting an fsync().
* It shouldn't be possible for fullfsync to fail on the local
* file system (on OSX), so failure indicates that FULLFSYNC
* isn't supported for this file system. So, attempt an fsync
* and (for now) ignore the overhead of a superfluous fcntl call.
* It'd be better to detect fullfsync support once and avoid
* the fcntl call every time sync is called.
*/
if( rc ) rc = fsync(fd);
#else
if( dataOnly ){
rc = fdatasync(fd);
}else{
rc = fsync(fd);
}
#endif /* HAVE_FULLFSYNC */
#endif /* defined(SQLITE_NO_SYNC) */
return rc;

File diff suppressed because it is too large Load diff

View file

@ -82,19 +82,19 @@
#define TK_SLASH 82
#define TK_REM 83
#define TK_CONCAT 84
#define TK_UMINUS 85
#define TK_UPLUS 86
#define TK_BITNOT 87
#define TK_STRING 88
#define TK_JOIN_KW 89
#define TK_CONSTRAINT 90
#define TK_DEFAULT 91
#define TK_NULL 92
#define TK_PRIMARY 93
#define TK_UNIQUE 94
#define TK_CHECK 95
#define TK_REFERENCES 96
#define TK_COLLATE 97
#define TK_COLLATE 85
#define TK_UMINUS 86
#define TK_UPLUS 87
#define TK_BITNOT 88
#define TK_STRING 89
#define TK_JOIN_KW 90
#define TK_CONSTRAINT 91
#define TK_DEFAULT 92
#define TK_NULL 93
#define TK_PRIMARY 94
#define TK_UNIQUE 95
#define TK_CHECK 96
#define TK_REFERENCES 97
#define TK_AUTOINCR 98
#define TK_ON 99
#define TK_DELETE 100

View file

@ -205,6 +205,7 @@ id(A) ::= ID(X). {A = X;}
%left PLUS MINUS.
%left STAR SLASH REM.
%left CONCAT.
%left COLLATE.
%right UMINUS UPLUS BITNOT.
// And "ids" is an identifer-or-string.
@ -515,24 +516,21 @@ using_opt(U) ::= . {U = 0;}
orderby_opt(A) ::= . {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). {
A = sqlite3ExprListAppend(X,Y,C.n>0?&C:0);
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
A = sqlite3ExprListAppend(X,Y,0);
if( A ) A->a[A->nExpr-1].sortOrder = Z;
}
sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). {
A = sqlite3ExprListAppend(0,Y,C.n>0?&C:0);
sortlist(A) ::= sortitem(Y) sortorder(Z). {
A = sqlite3ExprListAppend(0,Y,0);
if( A && A->a ) A->a[0].sortOrder = Z;
}
sortitem(A) ::= expr(X). {A = X;}
%type sortorder {int}
%type collate {Token}
sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
sortorder(A) ::= . {A = SQLITE_SO_ASC;}
collate(C) ::= . {C.z = 0; C.n = 0;}
collate(C) ::= COLLATE id(X). {C = X;}
%type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete($$);}
@ -642,6 +640,9 @@ expr(A) ::= VARIABLE(X). {
Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
sqlite3ExprAssignVarNumber(pParse, pExpr);
}
expr(A) ::= expr(E) COLLATE id(C). {
A = sqlite3ExprSetColl(pParse, E, &C);
}
%ifndef SQLITE_OMIT_CAST
expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
A = sqlite3Expr(TK_CAST, E, 0, &T);
@ -877,6 +878,10 @@ idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). {
}
idxitem(A) ::= nm(X). {A = X;}
%type collate {Token}
collate(C) ::= . {C.z = 0; C.n = 0;}
collate(C) ::= COLLATE id(X). {C = X;}
///////////////////////////// The DROP INDEX command /////////////////////////
//

View file

@ -1950,10 +1950,9 @@ static int multiSelect(
apColl = pKeyInfo->aColl;
for(i=0; i<nOrderByExpr; i++, pOTerm++, apColl++, pSortOrder++){
Expr *pExpr = pOTerm->pExpr;
char *zName = pOTerm->zName;
assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
if( zName ){
*apColl = sqlite3LocateCollSeq(pParse, zName, -1);
if( (pExpr->flags & EP_ExpCollate) ){
assert( pExpr->pColl!=0 );
*apColl = pExpr->pColl;
}else{
*apColl = aCopy[pExpr->iColumn];
}
@ -2476,8 +2475,14 @@ static int processOrderGroupBy(
Expr *pE = pOrderBy->a[i].pExpr;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol>0 && iCol<=pEList->nExpr ){
CollSeq *pColl = pE->pColl;
int flags = pE->flags & EP_ExpCollate;
sqlite3ExprDelete(pE);
pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
if( pColl && flags ){
pE->pColl = pColl;
pE->flags |= flags;
}
}else{
sqlite3ErrorMsg(pParse,
"%s BY column number %d out of range - should be "
@ -2912,23 +2917,15 @@ int sqlite3Select(
}
#endif
/* If there is an ORDER BY clause, resolve any collation sequences
** names that have been explicitly specified and create a sorting index.
**
** This sorting index might end up being unused if the data can be
/* If there is an ORDER BY clause, then this sorting
** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
*/
if( pOrderBy ){
struct ExprList_item *pTerm;
KeyInfo *pKeyInfo;
for(i=0, pTerm=pOrderBy->a; i<pOrderBy->nExpr; i++, pTerm++){
if( pTerm->zName ){
pTerm->pExpr->pColl = sqlite3LocateCollSeq(pParse, pTerm->zName, -1);
}
}
if( pParse->nErr ){
goto select_end;
}

View file

@ -1021,6 +1021,7 @@ struct Expr {
#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */
#define EP_Dequoted 0x40 /* True if the string has been dequoted */
#define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */
/*
** These macros can be used to test, set, or clear bits in the
@ -1078,8 +1079,12 @@ struct IdList {
/*
** The bitmask datatype defined below is used for various optimizations.
**
** Changing this from a 64-bit to a 32-bit type limits the number of
** tables in a join to 32 instead of 64. But it also reduces the size
** of the library by 738 bytes on ix86.
*/
typedef unsigned int Bitmask;
typedef u64 Bitmask;
/*
** The following structure describes the FROM clause of a SELECT statement.
@ -1108,7 +1113,7 @@ struct SrcList {
Select *pSelect; /* A SELECT statement used in place of a table name */
u8 isPopulated; /* Temporary table associated with SELECT is populated */
u8 jointype; /* Type of join between this able and the previous */
i16 iCursor; /* The VDBE cursor number used to access this table */
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */
@ -1773,6 +1778,7 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckIndexCollSeq(Parse *, Index *);
int sqlite3CheckObjectName(Parse *, const char *);

View file

@ -1055,7 +1055,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}
nByte = strlen(zSql);
rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
@ -1081,7 +1081,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);

View file

@ -610,6 +610,46 @@ static void sqlite3ExecFunc(
sqliteFree(x.z);
}
/*
** Implementation of tkt2213func(), a scalar function that takes exactly
** one argument. It has two interesting features:
**
** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
** If the three pointers returned are not the same an SQL error is raised.
**
** * Otherwise it returns a copy of the text representation of it's
** argument in such a way as the VDBE representation is a Mem* cell
** with the MEM_Term flag clear.
**
** Ticket #2213 can therefore be tested by evaluating the following
** SQL expression:
**
** tkt2213func(tkt2213func('a string'));
*/
static void tkt2213Function(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int nText;
unsigned char const *zText1;
unsigned char const *zText2;
unsigned char const *zText3;
nText = sqlite3_value_bytes(argv[0]);
zText1 = sqlite3_value_text(argv[0]);
zText2 = sqlite3_value_text(argv[0]);
zText3 = sqlite3_value_text(argv[0]);
if( zText1!=zText2 || zText2!=zText3 ){
sqlite3_result_error(context, "tkt2213 is not fixed", -1);
}else{
char *zCopy = (char *)sqlite3_malloc(nText);
memcpy(zCopy, zText1, nText);
sqlite3_result_text(context, zCopy, nText, sqlite3_free);
}
}
/*
** Usage: sqlite_test_create_function DB
**
@ -651,6 +691,10 @@ static int test_create_function(
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
hex16Func, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
tkt2213Function, 0, 0);
}
#ifndef SQLITE_OMIT_UTF16
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also

View file

@ -577,7 +577,7 @@ static int btree_integrity_check(
}
pBt = sqlite3TextToPtr(argv[1]);
nRoot = argc-2;
aRoot = malloc( sizeof(int)*(argc-2) );
aRoot = (int*)malloc( sizeof(int)*(argc-2) );
for(i=0; i<argc-2; i++){
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
}
@ -586,7 +586,7 @@ static int btree_integrity_check(
#else
zResult = 0;
#endif
free(aRoot);
free((void*)aRoot);
if( zResult ){
Tcl_AppendResult(interp, zResult, 0);
sqliteFree(zResult);
@ -1186,6 +1186,7 @@ static int btree_payload_size(
** aResult[7] = Header size in bytes
** aResult[8] = Local payload size
** aResult[9] = Parent page number
** aResult[10]= Page number of the first overflow page
*/
static int btree_cursor_info(
void *NotUsed,
@ -1197,7 +1198,7 @@ static int btree_cursor_info(
int rc;
int i, j;
int up;
int aResult[10];
int aResult[11];
char zBuf[400];
if( argc!=2 && argc!=3 ){
@ -1225,6 +1226,76 @@ static int btree_cursor_info(
return SQLITE_OK;
}
/*
** Copied from btree.c:
*/
static u32 get4byte(unsigned char *p){
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
/*
** btree_ovfl_info BTREE CURSOR
**
** Given a cursor, return the sequence of pages number that form the
** overflow pages for the data of the entry that the cursor is point
** to.
*/
static int btree_ovfl_info(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
Btree *pBt;
BtCursor *pCur;
Pager *pPager;
int rc;
int n;
int dataSize;
u32 pgno;
void *pPage;
int aResult[11];
char zElem[100];
Tcl_DString str;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" BTREE CURSOR", 0);
return TCL_ERROR;
}
pBt = sqlite3TextToPtr(argv[1]);
pCur = sqlite3TextToPtr(argv[2]);
if( (*(void**)pCur) != (void*)pBt ){
Tcl_AppendResult(interp, "Cursor ", argv[2], " does not belong to btree ",
argv[1], 0);
return TCL_ERROR;
}
pPager = sqlite3BtreePager(pBt);
rc = sqlite3BtreeCursorInfo(pCur, aResult, 0);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
dataSize = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserve(pBt);
Tcl_DStringInit(&str);
n = aResult[6] - aResult[8];
n = (n + dataSize - 1)/dataSize;
pgno = (u32)aResult[10];
while( pgno && n-- ){
sprintf(zElem, "%d", pgno);
Tcl_DStringAppendElement(&str, zElem);
if( sqlite3pager_get(pPager, pgno, &pPage)!=SQLITE_OK ){
Tcl_DStringFree(&str);
Tcl_AppendResult(interp, "unable to get page ", zElem, 0);
return TCL_ERROR;
}
pgno = get4byte((unsigned char*)pPage);
sqlite3pager_unref(pPage);
}
Tcl_DStringResult(interp, &str);
return SQLITE_OK;
}
/*
** The command is provided for the purpose of setting breakpoints.
** in regression test scripts.
@ -1440,6 +1511,7 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
{ "btree_from_db", (Tcl_CmdProc*)btree_from_db },
{ "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size },
{ "btree_cursor_info", (Tcl_CmdProc*)btree_cursor_info },
{ "btree_ovfl_info", (Tcl_CmdProc*)btree_ovfl_info },
{ "btree_cursor_list", (Tcl_CmdProc*)btree_cursor_list },
};
int i;

View file

@ -103,6 +103,7 @@ void sqlite3Update(
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int memCnt = 0; /* Memory cell used for counting rows changed */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
@ -311,7 +312,8 @@ void sqlite3Update(
/* Initialize the count of updated rows
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
memCnt = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
if( triggers_exist ){
@ -469,7 +471,7 @@ void sqlite3Update(
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* If there are triggers, close all the cursors after each iteration
@ -514,6 +516,7 @@ void sqlite3Update(
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);

View file

@ -137,6 +137,7 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
}
pMem->xDel = 0;
pMem->z = z;
pMem->flags |= MEM_Term;
}
return SQLITE_OK;
}

View file

@ -43,6 +43,7 @@ int sqlite3_where_trace = 0;
/* Forward reference
*/
typedef struct WhereClause WhereClause;
typedef struct ExprMaskSet ExprMaskSet;
/*
** The query generator uses an array of instances of this structure to
@ -106,6 +107,7 @@ struct WhereTerm {
*/
struct WhereClause {
Parse *pParse; /* The parser context */
ExprMaskSet *pMaskSet; /* Mapping of table indices to bitmasks */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@ -138,7 +140,6 @@ struct WhereClause {
** numbers all get mapped into bit numbers that begin with 0 and contain
** no gaps.
*/
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
int n; /* Number of assigned cursor values */
int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */
@ -186,8 +187,13 @@ struct ExprMaskSet {
/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(WhereClause *pWC, Parse *pParse){
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
Parse *pParse, /* The parsing context */
ExprMaskSet *pMaskSet /* Mapping from table indices to bitmasks */
){
pWC->pParse = pParse;
pWC->pMaskSet = pMaskSet;
pWC->nTerm = 0;
pWC->nSlot = ARRAYSIZE(pWC->aStatic);
pWC->a = pWC->aStatic;
@ -463,7 +469,7 @@ static WhereTerm *findTerm(
}
/* Forward reference */
static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);
static void exprAnalyze(SrcList*, WhereClause*, int);
/*
** Call exprAnalyze on all terms in a WHERE clause.
@ -472,12 +478,11 @@ static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);
*/
static void exprAnalyzeAll(
SrcList *pTabList, /* the FROM clause */
ExprMaskSet *pMaskSet, /* table masks */
WhereClause *pWC /* the WHERE clause to be analyzed */
){
int i;
for(i=pWC->nTerm-1; i>=0; i--){
exprAnalyze(pTabList, pMaskSet, pWC, i);
exprAnalyze(pTabList, pWC, i);
}
}
@ -592,11 +597,11 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
*/
static void exprAnalyze(
SrcList *pSrc, /* the FROM clause */
ExprMaskSet *pMaskSet, /* table masks */
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
WhereTerm *pTerm = &pWC->a[idxTerm];
ExprMaskSet *pMaskSet = pWC->pMaskSet;
Expr *pExpr = pTerm->pExpr;
Bitmask prereqLeft;
Bitmask prereqAll;
@ -679,7 +684,7 @@ static void exprAnalyze(
pNewExpr = sqlite3Expr(ops[i], sqlite3ExprDup(pExpr->pLeft),
sqlite3ExprDup(pList->a[i].pExpr), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pMaskSet, pWC, idxNew);
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
}
@ -708,9 +713,9 @@ static void exprAnalyze(
WhereTerm *pOrTerm;
assert( (pTerm->flags & TERM_DYNAMIC)==0 );
whereClauseInit(&sOr, pWC->pParse);
whereClauseInit(&sOr, pWC->pParse, pMaskSet);
whereSplit(&sOr, pExpr, TK_OR);
exprAnalyzeAll(pSrc, pMaskSet, &sOr);
exprAnalyzeAll(pSrc, &sOr);
assert( sOr.nTerm>0 );
j = 0;
do{
@ -750,7 +755,7 @@ static void exprAnalyze(
transferJoinMarkings(pNew, pExpr);
pNew->pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pMaskSet, pWC, idxNew);
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
pTerm->nChild = 1;
@ -787,10 +792,10 @@ or_not_possible:
}
pNewExpr1 = sqlite3Expr(TK_GE, sqlite3ExprDup(pLeft), pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pMaskSet, pWC, idxNew1);
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3Expr(TK_LT, sqlite3ExprDup(pLeft), pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pMaskSet, pWC, idxNew2);
exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
if( isComplete ){
pWC->a[idxNew1].iParent = idxTerm;
@ -836,6 +841,25 @@ or_not_possible:
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}
/*
** Return TRUE if any of the expressions in pList->a[iFirst...] contain
** a reference to any table other than the iBase table.
*/
static int referencesOtherTables(
ExprList *pList, /* Search expressions in ths list */
ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */
int iFirst, /* Be searching with the iFirst-th expression */
int iBase /* Ignore references to this table */
){
Bitmask allowed = ~getMask(pMaskSet, iBase);
while( iFirst<pList->nExpr ){
if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
return 1;
}
}
return 0;
}
/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
@ -858,6 +882,7 @@ or_not_possible:
*/
static int isSortingIndex(
Parse *pParse, /* Parsing context */
ExprMaskSet *pMaskSet, /* Mapping from table indices to bitmaps */
Index *pIdx, /* The index we are testing */
int base, /* Cursor number for the table to be sorted */
ExprList *pOrderBy, /* The ORDER BY clause */
@ -894,7 +919,7 @@ static int isSortingIndex(
if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
/* Can not use an index sort on anything that is not a column in the
** left-most table of the FROM clause */
return 0;
break;
}
pColl = sqlite3ExprCollSeq(pParse, pExpr);
if( !pColl ){
@ -941,11 +966,12 @@ static int isSortingIndex(
}
j++;
pTerm++;
if( iColumn<0 ){
if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
/* If the indexed column is the primary key and everything matches
** so far, then we are assured that the index can be used to sort
** because the primary key is unique and so none of the other columns
** will make any difference
** so far and none of the ORDER BY terms to the right reference other
** tables in the join, then we are assured that the index can be used
** to sort because the primary key is unique and so none of the other
** columns will make any difference
*/
j = nTerm;
}
@ -957,9 +983,12 @@ static int isSortingIndex(
** this index can be used for sorting. */
return 1;
}
if( j==pIdx->nColumn && pIdx->onError!=OE_None ){
if( pIdx->onError!=OE_None && i==pIdx->nColumn
&& !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
/* All terms of this index match some prefix of the ORDER BY clause
** and this index is UNIQUE, so this index can be used for sorting. */
** and the index is UNIQUE and no terms on the tail of the ORDER BY
** clause reference other tables in a join. If this is all true then
** the order by clause is superfluous. */
return 1;
}
return 0;
@ -973,6 +1002,7 @@ static int isSortingIndex(
static int sortableByRowid(
int base, /* Cursor number for table to be sorted */
ExprList *pOrderBy, /* The ORDER BY clause */
ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */
int *pbRev /* Set to 1 if ORDER BY is DESC */
){
Expr *p;
@ -980,7 +1010,8 @@ static int sortableByRowid(
assert( pOrderBy!=0 );
assert( pOrderBy->nExpr>0 );
p = pOrderBy->a[0].pExpr;
if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 ){
if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1
&& !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){
*pbRev = pOrderBy->a[0].sortOrder;
return 1;
}
@ -1298,7 +1329,7 @@ static double bestIndex(
*/
if( pProbe==0 &&
findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
(pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, &rev)) ){
(pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
*pFlags = 0;
*ppIndex = 0;
*pnEq = 0;
@ -1360,7 +1391,7 @@ static double bestIndex(
/* If the table scan does not satisfy the ORDER BY clause, increase
** the cost by NlogN to cover the expense of sorting. */
if( pOrderBy ){
if( sortableByRowid(iCur, pOrderBy, &rev) ){
if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
if( rev ){
flags |= WHERE_REVERSE;
@ -1444,7 +1475,7 @@ static double bestIndex(
*/
if( pOrderBy ){
if( (flags & WHERE_COLUMN_IN)==0 &&
isSortingIndex(pParse,pProbe,iCur,pOrderBy,nEq,&rev) ){
isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
if( flags==0 ){
flags = WHERE_COLUMN_RANGE;
}
@ -1832,7 +1863,7 @@ WhereInfo *sqlite3WhereBegin(
** subexpression is separated by an AND operator.
*/
initMaskSet(&maskSet);
whereClauseInit(&wc, pParse);
whereClauseInit(&wc, pParse, &maskSet);
whereSplit(&wc, pWhere, TK_AND);
/* Allocate and initialize the WhereInfo structure that will become the
@ -1863,7 +1894,7 @@ WhereInfo *sqlite3WhereBegin(
for(i=0; i<pTabList->nSrc; i++){
createMask(&maskSet, pTabList->a[i].iCursor);
}
exprAnalyzeAll(pTabList, &maskSet, &wc);
exprAnalyzeAll(pTabList, &wc);
if( sqlite3MallocFailed() ){
goto whereBeginNoMem;
}