classes. (Dmitry, Michael Wallner)
- Added "new_link" parameter to mssql_connect(). Bug #34369. (Frank)
- Upgraded bundled SQLite library for PDO:SQLite to 3.2.5 (Ilia)
+- Upgraded SQLite 2 library in ext/sqlite to 2.8.16 (Ilia)
- Upgraded PCRE library to version 6.2. (Andrei)
- Upgraded bundled libraries in Windows distribution. (Edin)
. zlib 1.2.3
* concatenation of orig and val is returned. The original orig is deleted
* (using sqliteFree()).
*/
-static char *append_val(char * orig, char const * val)
-{
+static char *append_val(char * orig, char const * val){
+ char *z;
if( !orig ){
- return sqliteStrDup( val );
+ z = sqliteStrDup( val );
} else{
- char * ret = 0;
- sqliteSetString(&ret, orig, val, (char*)0);
+ z = 0;
+ sqliteSetString(&z, orig, val, (char*)0);
sqliteFree( orig );
- return ret;
}
- assert(0);
+ return z;
}
/*
pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
pCur->pTree = sqliteHashFind(&tree->tblHash, 0, iTable);
+ assert( pCur->pTree );
pCur->pRbtree = tree;
pCur->iTree = iTable;
pCur->pOps = &sqliteRbtreeCursorOps;
pCur->wrFlag = wrFlag;
pCur->pShared = pCur->pTree->pCursors;
pCur->pTree->pCursors = pCur;
-
assert( (*ppCur)->pTree );
return SQLITE_OK;
if( !pCur->pNode ) return 0;
if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
- return amt;
}else{
memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
- return pCur->pNode->nKey-offset;
+ amt = pCur->pNode->nKey-offset;
}
- assert(0);
+ return amt;
}
static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
if( !pCur->pNode ) return 0;
if( (amt + offset) <= pCur->pNode->nData ){
memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
- return amt;
}else{
memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
- return pCur->pNode->nData-offset;
+ amt = pCur->pNode->nData-offset;
}
- assert(0);
+ return amt;
}
static int memRbtreeCloseCursor(RbtCursor* pCur)
assert(!"Cannot call sqliteRbtreeCursorDump");
return SQLITE_OK;
}
+#endif
static struct Pager *memRbtreePager(Rbtree* tree)
{
- assert(!"Cannot call sqliteRbtreePager");
- return SQLITE_OK;
+ return 0;
}
-#endif
/*
** Return the full pathname of the underlying database file.
(char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
(const char*(*)(Btree*)) memRbtreeGetFilename,
(int(*)(Btree*,Btree*)) memRbtreeCopyFile,
-
+ (struct Pager*(*)(Btree*)) memRbtreePager,
#ifdef SQLITE_TEST
(int(*)(Btree*,int,int)) memRbtreePageDump,
- (struct Pager*(*)(Btree*)) memRbtreePager
#endif
};
if( pName && !db->init.busy ){
Index *pISameName; /* Another index with the same name */
Table *pTSameName; /* A table with same name as the index */
- zName = sqliteStrNDup(pName->z, pName->n);
+ zName = sqliteTableNameFromToken(pName);
if( zName==0 ) goto exit_create_index;
if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
sqliteErrorMsg(pParse, "index %s already exists", zName);
sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
if( zName==0 ) goto exit_create_index;
}else{
- zName = sqliteStrNDup(pName->z, pName->n);
+ zName = sqliteTableNameFromToken(pName);
}
/* Check for authorization to create an index.
case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
case 'W': /* Fall thru */
case 'j': {
- int n;
+ int n; /* Number of days since 1st day of year */
DateTime y = x;
y.validJD = 0;
y.M = 1;
y.D = 1;
computeJD(&y);
- n = x.rJD - y.rJD + 1;
+ n = x.rJD - y.rJD;
if( zFmt[i]=='W' ){
- sprintf(&z[j],"%02d",(n+6)/7);
+ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
+ wd = ((int)(x.rJD+0.5)) % 7;
+ sprintf(&z[j],"%02d",(n+7-wd)/7);
j += 2;
}else{
- sprintf(&z[j],"%03d",n);
+ sprintf(&z[j],"%03d",n+1);
j += 3;
}
break;
** external linkage.
*/
void sqliteRegisterDateTimeFunctions(sqlite *db){
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
static struct {
char *zName;
int nArg;
int dataType;
void (*xFunc)(sqlite_func*,int,const char**);
} aFuncs[] = {
-#ifndef SQLITE_OMIT_DATETIME_FUNCS
{ "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
{ "date", -1, SQLITE_TEXT, dateFunc },
{ "time", -1, SQLITE_TEXT, timeFunc },
{ "datetime", -1, SQLITE_TEXT, datetimeFunc },
{ "strftime", -1, SQLITE_TEXT, strftimeFunc },
-#endif
};
int i;
sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
}
}
+#endif
}
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
- pNew->token.z = sqliteStrDup(p->token.z);
+ pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
if( pNew==0 ) return 0;
pNew->nExpr = pNew->nAlloc = p->nExpr;
pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
- if( pItem==0 ) return 0; /* Leaks memory after a malloc failure */
+ if( pItem==0 ){
+ sqliteFree(pNew);
+ return 0;
+ }
for(i=0; i<p->nExpr; i++, pItem++){
Expr *pNewExpr, *pOldExpr;
pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite_func *context, int argc, const char **argv){
- char *z;
+ unsigned char *z;
int i;
if( argc<1 || argv[0]==0 ) return;
- z = sqlite_set_result_string(context, argv[0], -1);
+ z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
if( z==0 ) return;
for(i=0; z[i]; i++){
if( islower(z[i]) ) z[i] = toupper(z[i]);
}
}
static void lowerFunc(sqlite_func *context, int argc, const char **argv){
- char *z;
+ unsigned char *z;
int i;
if( argc<1 || argv[0]==0 ) return;
- z = sqlite_set_result_string(context, argv[0], -1);
+ z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
if( z==0 ) return;
for(i=0; z[i]; i++){
if( isupper(z[i]) ) z[i] = tolower(z[i]);
int mask; /* 0 for min() or 0xffffffff for max() */
assert( argc==2 );
+ if( argv[0]==0 ) return; /* Ignore NULL values */
if( argv[1][0]=='n' ){
xCompare = sqliteCompare;
}else{
xCompare = strcmp;
}
mask = (int)sqlite_user_data(context);
+ assert( mask==0 || mask==-1 );
p = sqlite_aggregate_context(context, sizeof(*p));
- if( p==0 || argc<1 || argv[0]==0 ) return;
+ if( p==0 || argc<1 ) return;
if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
int len;
- if( !p->zBuf[0] ){
+ if( p->zBuf[0] ){
sqliteFree(p->z);
}
len = strlen(argv[0]);
if( len < sizeof(p->zBuf)-1 ){
p->z = &p->zBuf[1];
- p->zBuf[0] = 1;
+ p->zBuf[0] = 0;
}else{
p->z = sqliteMalloc( len+1 );
- p->zBuf[0] = 0;
+ p->zBuf[0] = 1;
if( p->z==0 ) return;
}
strcpy(p->z, argv[0]);
static void minMaxFinalize(sqlite_func *context){
MinMaxCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && p->z ){
+ if( p && p->z && p->zBuf[0]<2 ){
sqlite_set_result_string(context, p->z, strlen(p->z));
}
- if( p && !p->zBuf[0] ){
+ if( p && p->zBuf[0] ){
sqliteFree(p->z);
}
}
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- void *pArg = aFuncs[i].argType==2 ? (void*)(-1) : db;
+ void *pArg;
+ switch( aFuncs[i].argType ){
+ case 0: pArg = 0; break;
+ case 1: pArg = db; break;
+ case 2: pArg = (void*)(-1); break;
+ }
sqlite_create_function(db, aFuncs[i].zName,
aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
if( aFuncs[i].xFunc ){
}
}
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
- void *pArg = aAggs[i].argType==2 ? (void*)(-1) : db;
+ void *pArg;
+ switch( aAggs[i].argType ){
+ case 0: pArg = 0; break;
+ case 1: pArg = db; break;
+ case 2: pArg = (void*)(-1); break;
+ }
sqlite_create_aggregate(db, aAggs[i].zName,
aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
BtCursor *curMain;
int size;
Table *pTab;
- char *azArg[6];
+ char const *azArg[6];
char zDbNum[30];
int meta[SQLITE_N_BTREE_META];
InitData initData;
+ char const *zMasterSchema;
+ char const *zMasterName;
+ char *zSql = 0;
/*
** The master database table has a structure like this
")"
;
- /* The following SQL will read the schema from the master tables.
- ** The first version works with SQLite file formats 2 or greater.
- ** The second version is for format 1 files.
- **
- ** Beginning with file format 2, the rowid for new table entries
- ** (including entries in sqlite_master) is an increasing integer.
- ** So for file format 2 and later, we can play back sqlite_master
- ** and all the CREATE statements will appear in the right order.
- ** But with file format 1, table entries were random and so we
- ** have to make sure the CREATE TABLEs occur before their corresponding
- ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
- ** CREATE TRIGGER in file format 1 because those constructs did
- ** not exist then.)
+ assert( iDb>=0 && iDb<db->nDb );
+
+ /* zMasterSchema and zInitScript are set to point at the master schema
+ ** and initialisation script appropriate for the database being
+ ** initialised. zMasterName is the name of the master table.
*/
- static char init_script[] =
- "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
- "UNION ALL "
- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
- static char older_init_script[] =
- "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
- "UNION ALL "
- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
- "WHERE type='table' "
- "UNION ALL "
- "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
- "WHERE type='index'";
-
-
- assert( iDb>=0 && iDb!=1 && iDb<db->nDb );
-
- /* Construct the schema tables: sqlite_master and sqlite_temp_master
+ if( iDb==1 ){
+ zMasterSchema = temp_master_schema;
+ zMasterName = TEMP_MASTER_NAME;
+ }else{
+ zMasterSchema = master_schema;
+ zMasterName = MASTER_NAME;
+ }
+
+ /* Construct the schema table.
*/
sqliteSafetyOff(db);
azArg[0] = "table";
- azArg[1] = MASTER_NAME;
+ azArg[1] = zMasterName;
azArg[2] = "2";
- azArg[3] = master_schema;
+ azArg[3] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[4] = zDbNum;
azArg[5] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
- sqliteInitCallback(&initData, 5, azArg, 0);
- pTab = sqliteFindTable(db, MASTER_NAME, "main");
+ sqliteInitCallback(&initData, 5, (char **)azArg, 0);
+ pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
- }
- if( iDb==0 ){
- azArg[1] = TEMP_MASTER_NAME;
- azArg[3] = temp_master_schema;
- azArg[4] = "1";
- sqliteInitCallback(&initData, 5, azArg, 0);
- pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
- if( pTab ){
- pTab->readOnly = 1;
- }
+ }else{
+ return SQLITE_NOMEM;
}
sqliteSafetyOn(db);
sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
- }else if( db->file_format!=meta[2] || db->file_format<4 ){
+ }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
assert( db->file_format>=4 );
if( meta[2]==0 ){
sqliteSetString(pzErrMsg, "cannot attach empty database: ",
*/
assert( db->init.busy );
sqliteSafetyOff(db);
- if( iDb==0 ){
- rc = sqlite_exec(db,
- db->file_format>=2 ? init_script : older_init_script,
- sqliteInitCallback, &initData, 0);
+
+ /* The following SQL will read the schema from the master tables.
+ ** The first version works with SQLite file formats 2 or greater.
+ ** The second version is for format 1 files.
+ **
+ ** Beginning with file format 2, the rowid for new table entries
+ ** (including entries in sqlite_master) is an increasing integer.
+ ** So for file format 2 and later, we can play back sqlite_master
+ ** and all the CREATE statements will appear in the right order.
+ ** But with file format 1, table entries were random and so we
+ ** have to make sure the CREATE TABLEs occur before their corresponding
+ ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
+ ** CREATE TRIGGER in file format 1 because those constructs did
+ ** not exist then.)
+ */
+ if( db->file_format>=2 ){
+ sqliteSetString(&zSql,
+ "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
+ db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
}else{
- char *zSql = 0;
sqliteSetString(&zSql,
- "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
- db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
- rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
- sqliteFree(zSql);
+ "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
+ db->aDb[iDb].zName, "\".", zMasterName,
+ " WHERE type IN ('table', 'index')"
+ " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
}
+ rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
+
+ sqliteFree(zSql);
sqliteSafetyOn(db);
sqliteBtreeCloseCursor(curMain);
if( sqlite_malloc_failed ){
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
- if( iDb==0 ){
- DbSetProperty(db, 1, DB_SchemaLoaded);
- }
}else{
sqliteResetInternalSchema(db, iDb);
}
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
- assert( i!=1 ); /* Should have been initialized together with 0 */
+ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
rc = sqliteInitOne(db, i, pzErrMsg);
if( rc ){
sqliteResetInternalSchema(db, i);
}
}
+
+ /* Once all the other databases have been initialised, load the schema
+ ** for the TEMP database. This is loaded last, as the TEMP database
+ ** schema may contain references to objects in other databases.
+ */
+ if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
+ rc = sqliteInitOne(db, 1, pzErrMsg);
+ if( rc ){
+ sqliteResetInternalSchema(db, 1);
+ }
+ }
+
db->init.busy = 0;
if( rc==SQLITE_OK ){
db->flags |= SQLITE_Initialized;
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
int i, j;
- char *zDir;
+ const char *zDir;
char zTempPath[SQLITE_TEMPNAME_SIZE];
if( sqlite_temp_directory==0 ){
GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
#endif
}
+#ifdef SQLITE_NOSYNC
+# define fsync(X) 0
+#endif
+
/*
** Make sure all writes to a particular file are committed to disk.
**
int nsd; /* Number of significant digits returned */
#endif
+ func(arg,"",0);
count = length = 0;
bufpt = 0;
for(; (c=(*fmt))!=0; ++fmt){
}
}
}
- if( pM->zText && nNewChar>0 ){
- memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
- pM->nChar += nNewChar;
+ if( pM->zText ){
+ if( nNewChar>0 ){
+ memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
+ pM->nChar += nNewChar;
+ }
pM->zText[pM->nChar] = 0;
}
}
sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
}
+/*
+** Add code to implement the OFFSET and LIMIT
+*/
+static void codeLimiter(
+ Vdbe *v, /* Generate code into this VM */
+ Select *p, /* The SELECT statement being coded */
+ int iContinue, /* Jump here to skip the current record */
+ int iBreak, /* Jump here to end the loop */
+ int nPop /* Number of times to pop stack when jumping */
+){
+ if( p->iOffset>=0 ){
+ int addr = sqliteVdbeCurrentAddr(v) + 2;
+ if( nPop>0 ) addr++;
+ sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
+ if( nPop>0 ){
+ sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
+ }
+ sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
+ }
+ if( p->iLimit>=0 ){
+ sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
+ }
+}
+
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
){
Vdbe *v = pParse->pVdbe;
int i;
+ int hasDistinct; /* True if the DISTINCT keyword is present */
if( v==0 ) return 0;
assert( pEList!=0 );
/* If there was a LIMIT clause on the SELECT statement, then do the check
** to see if this row should be output.
*/
- if( pOrderBy==0 ){
- if( p->iOffset>=0 ){
- int addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
- sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
- }
- if( p->iLimit>=0 ){
- sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
- }
+ hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
+ if( pOrderBy==0 && !hasDistinct ){
+ codeLimiter(v, p, iContinue, iBreak, 0);
}
/* Pull the requested columns.
** and this row has been seen before, then do not make this row
** part of the result.
*/
- if( distinct>=0 && pEList && pEList->nExpr>0 ){
+ if( hasDistinct ){
#if NULL_ALWAYS_DISTINCT
sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
#endif
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
+ if( pOrderBy==0 ){
+ codeLimiter(v, p, iContinue, iBreak, nColumn);
+ }
}
switch( eDest ){
if( eDest==SRT_Sorter ) return;
sqliteVdbeAddOp(v, OP_Sort, 0, 0);
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
- if( p->iOffset>=0 ){
- sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, addr);
- }
- if( p->iLimit>=0 ){
- sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
- }
+ codeLimiter(v, p, addr, end2, 1);
switch( eDest ){
case SRT_Callback: {
sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
}else{
char zBuf[30];
sprintf(zBuf, "column%d", i+1);
- pTab->aCol[i].zName = sqliteStrDup(zBuf);
+ aCol[i].zName = sqliteStrDup(zBuf);
}
+ sqliteDequote(aCol[i].zName);
}
pTab->iPKey = -1;
return pTab;
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
- Token *pName; /* text of name of TABLE */
+ char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT && pE->pLeft ){
- pName = &pE->pLeft->token;
+ zTName = sqliteTableNameFromToken(&pE->pLeft->token);
}else{
- pName = 0;
+ zTName = 0;
}
for(i=0; i<pTabList->nSrc; i++){
Table *pTab = pTabList->a[i].pTab;
if( zTabName==0 || zTabName[0]==0 ){
zTabName = pTab->zName;
}
- if( pName && (zTabName==0 || zTabName[0]==0 ||
- sqliteStrNICmp(pName->z, zTabName, pName->n)!=0 ||
- zTabName[pName->n]!=0) ){
+ if( zTName && (zTabName==0 || zTabName[0]==0 ||
+ sqliteStrICmp(zTName, zTabName)!=0) ){
continue;
}
tableSeen = 1;
}
}
if( !tableSeen ){
- if( pName ){
- sqliteErrorMsg(pParse, "no such table: %T", pName);
+ if( zTName ){
+ sqliteErrorMsg(pParse, "no such table: %s", zTName);
}else{
sqliteErrorMsg(pParse, "no tables specified");
}
rc = 1;
}
+ sqliteFree(zTName);
}
}
sqliteExprListDelete(pEList);
}else{
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
+ if( seekOp==OP_Rewind ){
+ sqliteVdbeAddOp(v, OP_String, 0, 0);
+ sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
+ sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
+ seekOp = OP_MoveTo;
+ }
sqliteVdbeAddOp(v, seekOp, base+1, 0);
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
/*
** The version of the SQLite library.
*/
-#define SQLITE_VERSION "--VERS--"
+#ifdef SQLITE_VERSION
+# undef SQLITE_VERSION
+#else
+# define SQLITE_VERSION "--VERS--"
+#endif
/*
** The version string is also compiled into the library so that a program
int datatype /* The datatype for this function */
);
#define SQLITE_NUMERIC (-1)
-#define SQLITE_TEXT (-2)
+/* #define SQLITE_TEXT (-2) // See below */
#define SQLITE_ARGS (-3)
+/*
+** SQLite version 3 defines SQLITE_TEXT differently. To allow both
+** version 2 and version 3 to be included, undefine them both if a
+** conflict is seen. Define SQLITE2_TEXT to be the version 2 value.
+*/
+#ifdef SQLITE_TEXT
+# undef SQLITE_TEXT
+#else
+# define SQLITE_TEXT (-2)
+#endif
+#define SQLITE2_TEXT (-2)
+
+
+
/*
** The user function implementations call one of the following four routines
** in order to return their results. The first parameter to each of these
/*
** The version of the SQLite library.
*/
-#define SQLITE_VERSION "2.8.11"
+#define SQLITE_VERSION "2.8.16"
/*
** The version string is also compiled into the library so that a program
#ifndef UINT16_TYPE
# define UINT16_TYPE unsigned short int
#endif
+#ifndef INT16_TYPE
+# define INT16_TYPE short int
+#endif
#ifndef UINT8_TYPE
# define UINT8_TYPE unsigned char
#endif
#endif
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
+typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef UINT8_TYPE i8; /* 1-byte signed integer */
typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
** now be identified by a database name, a dot, then the table name: ID.ID.
*/
struct SrcList {
- u16 nSrc; /* Number of tables or subqueries in the FROM clause */
- u16 nAlloc; /* Number of entries allocated in a[] below */
+ i16 nSrc; /* Number of tables or subqueries in the FROM clause */
+ i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
- return *a - *b;
+ return UpperToLower[*a] - UpperToLower[*b];
}
int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
register unsigned char *a, *b;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
- return N<0 ? 0 : *a - *b;
+ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}
/*
return rc;
}
-/*
-** This callback is used to transfer PRAGMA settings from one database
-** to the other. The value in argv[0] should be passed to a pragma
-** identified by ((vacuumStruct*)pArg)->zPragma.
-*/
-static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){
- vacuumStruct *p = (vacuumStruct*)pArg;
- char zBuf[200];
- assert( argc==1 );
- if( argv==0 ) return 0;
- assert( argv[0]!=0 );
- assert( strlen(p->zPragma)<100 );
- assert( strlen(argv[0])<30 );
- sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]);
- p->rc = execsql(p->pzErrMsg, p->dbNew, zBuf);
- return p->rc;
-}
-
/*
** Generate a random name of 20 character in length.
*/
char *zErrMsg; /* Error message */
vacuumStruct sVac; /* Information passed to callbacks */
- /* These are all of the pragmas that need to be transferred over
- ** to the new database */
- static const char *zPragma[] = {
- "default_synchronous",
- "default_cache_size",
- /* "default_temp_store", */
- };
-
if( db->flags & SQLITE_InTrans ){
sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
sVac.dbOld = db;
sVac.dbNew = dbNew;
sVac.pzErrMsg = pzErrMsg;
- for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){
- char zBuf[200];
- assert( strlen(zPragma[i])<100 );
- sprintf(zBuf, "PRAGMA %s;", zPragma[i]);
- sVac.zPragma = zPragma[i];
- rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
- }
if( rc==SQLITE_OK ){
rc = sqlite_exec(db,
"SELECT type, name, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='view'",
vacuumCallback1, &sVac, &zErrMsg);
}
+ if( rc==SQLITE_OK ){
+ int meta1[SQLITE_N_BTREE_META];
+ int meta2[SQLITE_N_BTREE_META];
+ sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
+ sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
+ meta2[1] = meta1[1]+1;
+ meta2[3] = meta1[3];
+ meta2[4] = meta1[4];
+ meta2[6] = meta1[6];
+ rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
+ }
if( rc==SQLITE_OK ){
rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
sqlite_exec(db, "COMMIT", 0, 0, 0);
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
pTos->flags |= MEM_Ephem;
}
+ if( pTos->flags & MEM_AggCtx ){
+ Release(pTos);
+ pTos->flags = MEM_Null;
+ }
break;
}
break;
}
}else{
- assert( pSet->prev );
- pSet->prev = sqliteHashNext(pSet->prev);
+ if( pSet->prev ){
+ pSet->prev = sqliteHashNext(pSet->prev);
+ }
if( pSet->prev==0 ){
break;
}else{
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
int n; /* Number of assigned cursor values */
- int ix[32]; /* Cursor assigned to each bit */
+ int ix[31]; /* Cursor assigned to each bit */
};
/*
unsigned int mask = 0;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
- return getMask(pMaskSet, p->iTable);
+ mask = getMask(pMaskSet, p->iTable);
+ if( mask==0 ) mask = -1;
+ return mask;
}
if( p->pRight ){
mask = exprTableUsage(pMaskSet, p->pRight);
return pMatch;
}
+/*
+** Disable a term in the WHERE clause. Except, do not disable the term
+** if it controls a LEFT OUTER JOIN and it did not originate in the ON
+** or USING clause of that join.
+**
+** Consider the term t2.z='ok' in the following queries:
+**
+** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
+** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
+** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
+**
+** The t2.z='ok' is disabled in the in (2) because it did not originate
+** in the ON clause. The term is disabled in (3) because it is not part
+** of a LEFT OUTER JOIN. In (1), the term is not disabled.
+**
+** Disabling a term causes that term to not be tested in the inner loop
+** of the join. Disabling is an optimization. We would get the correct
+** results if nothing were ever disabled, but joins might run a little
+** slower. The trick is to disable as much as we can without disabling
+** too much. If we disabled in (1), we'd get the wrong answer.
+** See ticket #813.
+*/
+static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
+ Expr *pExpr = *ppExpr;
+ if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
+ *ppExpr = 0;
+ }
+}
+
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an (opaque) structure that contains
}else{
sqliteExprCode(pParse, aExpr[k].p->pLeft);
}
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
haveKey = 0;
){
if( pX->op==TK_EQ ){
sqliteExprCode(pParse, pX->pRight);
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
if( pX->op==TK_IN && nColumn==1 ){
pLevel->inOp = OP_Next;
pLevel->inP1 = pX->iTable;
}
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
}
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pLeft);
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
}
sqliteVdbeAddOp(v, OP_ForceInt,
aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
}else{
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
}
}else{
testOp = OP_Gt;
}
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
}
start = sqliteVdbeCurrentAddr(v);
pLevel->op = OP_Next;
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pRight);
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pLeft);
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
}
){
sqliteExprCode(pParse, pExpr->pRight);
leFlag = pExpr->op==TK_LE;
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
){
sqliteExprCode(pParse, pExpr->pLeft);
leFlag = pExpr->op==TK_GE;
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
}
){
sqliteExprCode(pParse, pExpr->pRight);
geFlag = pExpr->op==TK_GE;
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
){
sqliteExprCode(pParse, pExpr->pLeft);
geFlag = pExpr->op==TK_LE;
- aExpr[k].p = 0;
+ disableTerm(pLevel, &aExpr[k].p);
break;
}
}