iliaa           Wed Apr 18 22:53:46 2007 UTC

  Modified files:              (Branch: PHP_5_2)
    /php-src    NEWS 
    /php-src/ext/pdo_sqlite/sqlite      VERSION 
    /php-src/ext/pdo_sqlite/sqlite/src  btree.c build.c callback.c 
                                        delete.c expr.c func.c insert.c 
                                        keywordhash.h main.c os_common.h 
                                        os_win.c pager.c pager.h parse.y 
                                        select.c sqliteInt.h test1.c 
                                        tokenize.c vdbe.c vdbeaux.c 
                                        vtab.c 
  Log:
  Upgraded SQLite 3 to version 3.3.16
  
  
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.653&r2=1.2027.2.547.2.654&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.653 php-src/NEWS:1.2027.2.547.2.654
--- php-src/NEWS:1.2027.2.547.2.653     Tue Apr 17 15:33:57 2007
+++ php-src/NEWS        Wed Apr 18 22:53:45 2007
@@ -1,6 +1,7 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? Apr 2007, PHP 5.2.2RC2
+- Upgraded SQLite 3 to version 3.3.16 (Ilia)
 - Fixed bug #41109 (recursiveiterator.inc says "implements" Iterator instead of
   "extends"). (Marcus)
 - Fixed bug #41093 (magic_quotes_gpc ignores first arrays keys). (Arpad, Ilia)
@@ -45,7 +46,6 @@
   . libpq (PostgreSQL) to version 8.2.3
   . libmysql (MySQL) to version 5.0.37
   . openssl to version 0.9.8e
-- Upgraded SQLite 3 to version 3.3.15 (Ilia)
 - Upgraded PCRE to version 7.0 (Nuno)
 - Updated timezone database to version 2007.3. (Derick)
 - Improved FastCGI SAPI to support external pipe and socket servers on win32.
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/VERSION?r1=1.3.2.3.2.4&r2=1.3.2.3.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/VERSION
diff -u php-src/ext/pdo_sqlite/sqlite/VERSION:1.3.2.3.2.4 
php-src/ext/pdo_sqlite/sqlite/VERSION:1.3.2.3.2.5
--- php-src/ext/pdo_sqlite/sqlite/VERSION:1.3.2.3.2.4   Mon Apr  9 16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/VERSION       Wed Apr 18 22:53:45 2007
@@ -1 +1 @@
-3.3.15
+3.3.16
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/btree.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/btree.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/btree.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/btree.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/btree.c:1.3.2.2.2.4       Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/btree.c   Wed Apr 18 22:53:45 2007
@@ -1396,13 +1396,20 @@
 /*
 ** Get a page from the pager.  Initialize the MemPage.pBt and
 ** MemPage.aData elements if needed.
+**
+** If the noContent flag is set, it means that we do not care about
+** the content of the page at this time.  So do not go to the disk
+** to fetch the content.  Just fill in the content with zeros for now.
+** If in the future we call sqlite3PagerWrite() on this page, that
+** means we have started to be concerned about content and the disk
+** read should occur at that point.
 */
-static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int clrFlag){
+static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int noContent){
   int rc;
   MemPage *pPage;
   DbPage *pDbPage;
 
-  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, clrFlag);
+  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
   if( rc ) return rc;
   pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
   pPage->aData = sqlite3PagerGetData(pDbPage);
@@ -1411,9 +1418,6 @@
   pPage->pgno = pgno;
   pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
   *ppPage = pPage;
-  if( clrFlag ){
-    sqlite3PagerDontRollback(pPage->pDbPage);
-  }
   return SQLITE_OK;
 }
 
@@ -3830,6 +3834,7 @@
           put4byte(&aData[4], k-1);
           rc = getPage(pBt, *pPgno, ppPage, 1);
           if( rc==SQLITE_OK ){
+            sqlite3PagerDontRollback((*ppPage)->pDbPage);
             rc = sqlite3PagerWrite((*ppPage)->pDbPage);
             if( rc!=SQLITE_OK ){
               releasePage(*ppPage);
@@ -3948,7 +3953,7 @@
         put4byte(&pTrunk->aData[4], k+1);
         put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
 #ifndef SQLITE_SECURE_DELETE
-        sqlite3PagerDontWrite(pBt->pPager, pPage->pgno);
+        sqlite3PagerDontWrite(pPage->pDbPage);
 #endif
       }
       TRACE(("FREE-PAGE: %d leaf on trunk page 
%d\n",pPage->pgno,pTrunk->pgno));
@@ -3982,7 +3987,7 @@
     if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){
       return SQLITE_CORRUPT_BKPT;
     }
-    rc = getPage(pBt, ovflPgno, &pOvfl, 0);
+    rc = getPage(pBt, ovflPgno, &pOvfl, nOvfl==0);
     if( rc ) return rc;
     if( nOvfl ){
       ovflPgno = get4byte(pOvfl->aData);
@@ -6561,18 +6566,31 @@
     rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage));
     sqlite3PagerUnref(pDbPage);
   }
+
+  /* If the file is shrinking, journal the pages that are being truncated
+  ** so that they can be rolled back if the commit fails.
+  */
   for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
     DbPage *pDbPage;
     if( i==iSkip ) continue;
     rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage);
     if( rc ) break;
     rc = sqlite3PagerWrite(pDbPage);
+    sqlite3PagerDontWrite(pDbPage);
+    /* Yeah.  It seems wierd to call DontWrite() right after Write().  But
+    ** that is because the names of those procedures do not exactly 
+    ** represent what they do.  Write() really means "put this page in the
+    ** rollback journal and mark it as dirty so that it will be written
+    ** to the database file later."  DontWrite() undoes the second part of
+    ** that and prevents the page from being written to the database.  The
+    ** page is still on the rollback journal, though.  And that is the whole
+    ** point of this loop: to put pages on the rollback journal. */
     sqlite3PagerUnref(pDbPage);
-    sqlite3PagerDontWrite(pBtTo->pPager, i);
   }
   if( !rc && nPage<nToPage ){
     rc = sqlite3PagerTruncate(pBtTo->pPager, nPage);
   }
+
   if( rc ){
     sqlite3BtreeRollback(pTo);
   }
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/build.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/build.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/build.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/build.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/build.c:1.3.2.2.2.4       Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/build.c   Wed Apr 18 22:53:45 2007
@@ -478,18 +478,11 @@
 ** foreign keys from the sqlite.aFKey hash table.  But it does destroy
 ** memory structures of the indices and foreign keys associated with 
 ** the table.
-**
-** Indices associated with the table are unlinked from the "db"
-** data structure if db!=NULL.  If db==NULL, indices attached to
-** the table are deleted, but it is assumed they have already been
-** unlinked.
 */
-void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
+void sqlite3DeleteTable(Table *pTable){
   Index *pIndex, *pNext;
   FKey *pFKey, *pNextFKey;
 
-  db = 0;
-
   if( pTable==0 ) return;
 
   /* Do not delete the table until the reference count reaches zero. */
@@ -509,7 +502,7 @@
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
   /* Delete all foreign keys associated with this table.  The keys
-  ** should have already been unlinked from the db->aFKey hash table 
+  ** should have already been unlinked from the pSchema->aFKey hash table 
   */
   for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
     pNextFKey = pFKey->pNextFrom;
@@ -561,7 +554,7 @@
       }
     }
 #endif
-    sqlite3DeleteTable(db, p);
+    sqlite3DeleteTable(p);
   }
   db->flags |= SQLITE_InternChanges;
 }
@@ -810,7 +803,7 @@
   pTable->iPKey = -1;
   pTable->pSchema = db->aDb[iDb].pSchema;
   pTable->nRef = 1;
-  if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
+  if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable);
   pParse->pNewTable = pTable;
 
   /* If this is the magic sqlite_sequence table used by autoincrement,
@@ -1484,7 +1477,7 @@
         p->aCol = pSelTab->aCol;
         pSelTab->nCol = 0;
         pSelTab->aCol = 0;
-        sqlite3DeleteTable(0, pSelTab);
+        sqlite3DeleteTable(pSelTab);
       }
     }
 
@@ -1712,7 +1705,7 @@
       pTable->aCol = pSelTab->aCol;
       pSelTab->nCol = 0;
       pSelTab->aCol = 0;
-      sqlite3DeleteTable(0, pSelTab);
+      sqlite3DeleteTable(pSelTab);
       pTable->pSchema->flags |= DB_UnresetViews;
     }else{
       pTable->nCol = 0;
@@ -2210,7 +2203,7 @@
     sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2);
     sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort,
                     "indexed columns are not unique", P3_STATIC);
-    assert( addr2==sqlite3VdbeCurrentAddr(v) );
+    assert( sqlite3MallocFailed() || addr2==sqlite3VdbeCurrentAddr(v) );
   }
   sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
   sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
@@ -2959,7 +2952,7 @@
     sqliteFree(pItem->zDatabase);
     sqliteFree(pItem->zName);
     sqliteFree(pItem->zAlias);
-    sqlite3DeleteTable(0, pItem->pTab);
+    sqlite3DeleteTable(pItem->pTab);
     sqlite3SelectDelete(pItem->pSelect);
     sqlite3ExprDelete(pItem->pOn);
     sqlite3IdListDelete(pItem->pUsing);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/callback.c?r1=1.1.2.2.2.2&r2=1.1.2.2.2.3&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/callback.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/callback.c:1.1.2.2.2.2 
php-src/ext/pdo_sqlite/sqlite/src/callback.c:1.1.2.2.2.3
--- php-src/ext/pdo_sqlite/sqlite/src/callback.c:1.1.2.2.2.2    Tue Feb 20 
00:09:42 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/callback.c        Wed Apr 18 22:53:45 2007
@@ -13,7 +13,7 @@
 ** This file contains functions used to access the internal hash tables
 ** of user defined functions and collation sequences.
 **
-** $Id: callback.c,v 1.1.2.2.2.2 2007/02/20 00:09:42 iliaa Exp $
+** $Id: callback.c,v 1.1.2.2.2.3 2007/04/18 22:53:45 iliaa Exp $
 */
 
 #include "sqliteInt.h"
@@ -344,7 +344,7 @@
   sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
   for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
     Table *pTab = sqliteHashData(pElem);
-    sqlite3DeleteTable(0, pTab);
+    sqlite3DeleteTable(pTab);
   }
   sqlite3HashClear(&temp1);
   pSchema->pSeqTab = 0;
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/delete.c?r1=1.3.2.2.2.2&r2=1.3.2.2.2.3&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/delete.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/delete.c:1.3.2.2.2.2 
php-src/ext/pdo_sqlite/sqlite/src/delete.c:1.3.2.2.2.3
--- php-src/ext/pdo_sqlite/sqlite/src/delete.c:1.3.2.2.2.2      Tue Feb 20 
00:09:42 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/delete.c  Wed Apr 18 22:53:45 2007
@@ -27,7 +27,7 @@
   struct SrcList_item *pItem;
   for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
     pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
-    sqlite3DeleteTable(pParse->db, pItem->pTab);
+    sqlite3DeleteTable(pItem->pTab);
     pItem->pTab = pTab;
     if( pTab ){
       pTab->nRef++;
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/expr.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/expr.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/expr.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/expr.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/expr.c:1.3.2.2.2.4        Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/expr.c    Wed Apr 18 22:53:45 2007
@@ -1420,7 +1420,9 @@
         int iParm = pExpr->iTable +  (((int)affinity)<<16);
         ExprList *pEList;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
-        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0);
+        if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) 
){
+          return;
+        }
         pEList = pExpr->pSelect->pEList;
         if( pEList && pEList->nExpr>0 ){ 
           keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
@@ -1491,7 +1493,9 @@
       }
       sqlite3ExprDelete(pSel->pLimit);
       pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one);
-      sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0);
+      if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){
+        return;
+      }
       break;
     }
   }
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/func.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/func.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/func.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/func.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/func.c:1.3.2.2.2.4        Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/func.c    Wed Apr 18 22:53:46 2007
@@ -655,8 +655,8 @@
   const unsigned char *pBlob;
   char *zHex, *z;
   assert( argc==1 );
-  pBlob = sqlite3_value_blob(argv[0]);
   n = sqlite3_value_bytes(argv[0]);
+  pBlob = sqlite3_value_blob(argv[0]);
   z = zHex = sqlite3_malloc(n*2 + 1);
   if( zHex==0 ) return;
   for(i=0; i<n; i++, pBlob++){
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/insert.c?r1=1.3.2.2.2.3&r2=1.3.2.2.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/insert.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/insert.c:1.3.2.2.2.3 
php-src/ext/pdo_sqlite/sqlite/src/insert.c:1.3.2.2.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/insert.c:1.3.2.2.2.3      Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/insert.c  Wed Apr 18 22:53:46 2007
@@ -705,7 +705,7 @@
         VdbeOp *pOp;
         sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
         pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
-        if( pOp->opcode==OP_Null ){
+        if( pOp && pOp->opcode==OP_Null ){
           appendFlag = 1;
           pOp->opcode = OP_NewRowid;
           pOp->p1 = base;
@@ -1374,10 +1374,10 @@
   int addr1, addr2;                /* Loop addresses */
   int emptyDestTest;               /* Address of test for empty pDest */
   int emptySrcTest;                /* Address of test for empty pSrc */
-  int memRowid = 0;                /* A memcell containing a rowid from pSrc */
   Vdbe *v;                         /* The VDBE we are building */
   KeyInfo *pKey;                   /* Key information for an index */
   int counterMem;                  /* Memory register used by AUTOINC */
+  int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
 
   if( pSelect==0 ){
     return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
@@ -1474,6 +1474,9 @@
     }
   }
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
+    if( pDestIdx->onError!=OE_None ){
+      destHasUniqueIdx = 1;
+    }
     for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
       if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
     }
@@ -1504,11 +1507,16 @@
   iDest = pParse->nTab++;
   counterMem = autoIncBegin(pParse, iDbDest, pDest);
   sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
-  if( pDest->iPKey<0 && pDest->pIndex!=0 ){
+  if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){
     /* If tables do not have an INTEGER PRIMARY KEY and there
     ** are indices to be copied and the destination is not empty,
     ** we have to disallow the transfer optimization because the
     ** the rowids might change which will mess up indexing.
+    **
+    ** Or if the destination has a UNIQUE index and is not empty,
+    ** we also disallow the transfer optimization because we cannot
+    ** insure that all entries in the union of DEST and SRC will be
+    ** unique.
     */
     addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0);
     emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
@@ -1518,11 +1526,6 @@
   }
   sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
   emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
-  if( pDest->pIndex!=0 ){
-    sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
-    memRowid = pParse->nMem++;
-    sqlite3VdbeAddOp(v, OP_MemStore, memRowid, pDest->iPKey>=0);
-  }
   if( pDest->iPKey>=0 ){
     addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
     sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -1562,13 +1565,6 @@
                    (char*)pKey, P3_KEYINFO_HANDOFF);
     addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
     sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0);
-    if( pDestIdx->onError!=OE_None ){
-      sqlite3VdbeAddOp(v, OP_MemLoad, memRowid, 0);
-      addr2 = sqlite3VdbeAddOp(v, OP_IsUnique, iDest, 0);
-      sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, 
-                    "UNIQUE constraint failed", P3_STATIC);
-      sqlite3VdbeJumpHere(v, addr2);
-    }
     sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1);
     sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1);
     sqlite3VdbeJumpHere(v, addr1);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h?r1=1.2.2.1.2.2&r2=1.2.2.1.2.3&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h
diff -u php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h:1.2.2.1.2.2 
php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h:1.2.2.1.2.3
--- php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h:1.2.2.1.2.2 Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h     Wed Apr 18 22:53:46 2007
@@ -2,7 +2,7 @@
 **
 ** The code in this file has been automatically generated by
 **
-**     $Header: /repository/php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h,v 
1.2.2.1.2.2 2007/04/09 16:35:11 iliaa Exp $
+**     $Header: /repository/php-src/ext/pdo_sqlite/sqlite/src/keywordhash.h,v 
1.2.2.1.2.3 2007/04/18 22:53:46 iliaa Exp $
 **
 ** The code in this file implements a function that determines whether
 ** or not a given identifier is really an SQL keyword.  The same thing
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/main.c?r1=1.3.2.2.2.3&r2=1.3.2.2.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/main.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/main.c:1.3.2.2.2.3 
php-src/ext/pdo_sqlite/sqlite/src/main.c:1.3.2.2.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/main.c:1.3.2.2.2.3        Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/main.c    Wed Apr 18 22:53:46 2007
@@ -127,8 +127,18 @@
   }
 #endif 
 
-  /* If there are any outstanding VMs, return SQLITE_BUSY. */
   sqlite3ResetInternalSchema(db, 0);
+
+  /* If a transaction is open, the ResetInternalSchema() call above
+  ** will not have called the xDisconnect() method on any virtual
+  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
+  ** call will do so. We need to do this before the check for active
+  ** SQL statements below, as the v-table implementation may be storing
+  ** some prepared statements internally.
+  */
+  sqlite3VtabRollback(db);
+
+  /* If there are any outstanding VMs, return SQLITE_BUSY. */
   if( db->pVdbe ){
     sqlite3Error(db, SQLITE_BUSY, 
         "Unable to close due to unfinalised statements");
@@ -149,8 +159,6 @@
     return SQLITE_ERROR;
   }
 
-  sqlite3VtabRollback(db);
-
   for(j=0; j<db->nDb; j++){
     struct Db *pDb = &db->aDb[j];
     if( pDb->pBt ){
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/os_common.h?r1=1.1.2.1.2.3&r2=1.1.2.1.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/os_common.h
diff -u php-src/ext/pdo_sqlite/sqlite/src/os_common.h:1.1.2.1.2.3 
php-src/ext/pdo_sqlite/sqlite/src/os_common.h:1.1.2.1.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/os_common.h:1.1.2.1.2.3   Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/os_common.h       Wed Apr 18 22:53:46 2007
@@ -97,6 +97,7 @@
          || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
                 { local_ioerr(); CODE; }
 static void local_ioerr(){
+  IOTRACE(("IOERR\n"));
   sqlite3_io_error_hit = 1;
 }
 #define SimulateDiskfullError(CODE) \
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/os_win.c?r1=1.3.2.1.2.3&r2=1.3.2.1.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/os_win.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/os_win.c:1.3.2.1.2.3 
php-src/ext/pdo_sqlite/sqlite/src/os_win.c:1.3.2.1.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/os_win.c:1.3.2.1.2.3      Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/os_win.c  Wed Apr 18 22:53:46 2007
@@ -408,6 +408,12 @@
     UnmapViewOfFile(pFile->shared);
     CloseHandle(pFile->hShared);
 
+    if( pFile->zDeleteOnClose ){
+      DeleteFileW(pFile->zDeleteOnClose);
+      sqliteFree(pFile->zDeleteOnClose);
+      pFile->zDeleteOnClose = 0;
+    }
+
     /* Done with the mutex */
     winceMutexRelease(pFile->hMutex);    
     CloseHandle(pFile->hMutex);
@@ -975,10 +981,6 @@
     }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
 #if OS_WINCE
     winceDestroyLock(pFile);
-    if( pFile->zDeleteOnClose ){
-      DeleteFileW(pFile->zDeleteOnClose);
-      sqliteFree(pFile->zDeleteOnClose);
-    }
 #endif
     OpenCounter(-1);
     sqliteFree(pFile);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/pager.c?r1=1.3.2.3.2.3&r2=1.3.2.3.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/pager.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/pager.c:1.3.2.3.2.3 
php-src/ext/pdo_sqlite/sqlite/src/pager.c:1.3.2.3.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/pager.c:1.3.2.3.2.3       Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/pager.c   Wed Apr 18 22:53:46 2007
@@ -162,6 +162,7 @@
   u8 dirty;                      /* TRUE if we need to write back changes */
   u8 needSync;                   /* Sync journal before writing this page */
   u8 alwaysRollback;             /* Disable DontRollback() for this page */
+  u8 needRead;                   /* Read content if PagerWrite() is called */
   short int nRef;                /* Number of users of this page */
   PgHdr *pDirty, *pPrevDirty;    /* Dirty pages */
   u32 notUsed;                   /* Buffer space */
@@ -293,19 +294,26 @@
   Pager *pNext;               /* Linked list of pagers in this thread */
 #endif
   char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
-  u32 iChangeCount;           /* Db change-counter for which cache is valid */
+  char dbFileVers[16];        /* Changes whenever database file changes */
 };
 
 /*
-** If SQLITE_TEST is defined then increment the variable given in
-** the argument
+** The following global variables hold counters used for
+** testing purposes only.  These variables do not exist in
+** a non-testing build.  These variables are not thread-safe.
 */
 #ifdef SQLITE_TEST
-# define TEST_INCR(x)  x++
+int sqlite3_pager_readdb_count = 0;    /* Number of full pages read from DB */
+int sqlite3_pager_writedb_count = 0;   /* Number of full pages written to DB */
+int sqlite3_pager_writej_count = 0;    /* Number of pages written to journal */
+int sqlite3_pager_pgfree_count = 0;    /* Number of cache pages freed */
+# define PAGER_INCR(v)  v++
 #else
-# define TEST_INCR(x)
+# define PAGER_INCR(v)
 #endif
 
+
+
 /*
 ** Journal files begin with the following magic string.  The data
 ** was obtained from /dev/random.  It is used only as a sanity check.
@@ -898,6 +906,8 @@
   PgHdr *pPg, *pNext;
   if( pPager->errCode ) return;
   for(pPg=pPager->pAll; pPg; pPg=pNext){
+    IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
+    PAGER_INCR(sqlite3_pager_pgfree_count);
     pNext = pPg->pNextAll;
     sqliteFree(pPg);
   }
@@ -1121,12 +1131,14 @@
 #ifdef SQLITE_CHECK_PAGES
     pPg->pageHash = pager_pagehash(pPg);
 #endif
-    CODEC1(pPager, pData, pPg->pgno, 3);
-
-    /* If this was page 1, then restore the value of Pager.iChangeCount */
+    /* If this was page 1, then restore the value of Pager.dbFileVers.
+    ** Do this before any decoding. */
     if( pgno==1 ){
-      pPager->iChangeCount = retrieve32bits(pPg, 24);
+      memcpy(&pPager->dbFileVers, 
&((u8*)pData)[24],sizeof(pPager->dbFileVers));
     }
+
+    /* Decode the page just read from disk */
+    CODEC1(pPager, pData, pPg->pgno, 3);
   }
   return rc;
 }
@@ -1219,51 +1231,6 @@
   return rc;
 }
 
-#if 0
-/*
-** Make every page in the cache agree with what is on disk.  In other words,
-** reread the disk to reset the state of the cache.
-**
-** This routine is called after a rollback in which some of the dirty cache
-** pages had never been written out to disk.  We need to roll back the
-** cache content and the easiest way to do that is to reread the old content
-** back from the disk.
-*/
-static int pager_reload_cache(Pager *pPager){
-  PgHdr *pPg;
-  int rc = SQLITE_OK;
-  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
-    char *zBuf = pPager->pTmpSpace;        /* Temp storage for one page */
-    if( !pPg->dirty ) continue;
-    if( (int)pPg->pgno <= pPager->origDbSize ){
-      rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
-      if( rc==SQLITE_OK ){
-        rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize);
-      }
-      PAGERTRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
-      if( rc ) break;
-      CODEC1(pPager, zBuf, pPg->pgno, 2);
-    }else{
-      memset(zBuf, 0, pPager->pageSize);
-    }
-    if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){
-      memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize);
-      if( pPager->xReiniter ){
-        pPager->xReiniter(pPg, pPager->pageSize);
-      }else{
-        memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
-      }
-    }
-    pPg->needSync = 0;
-    pPg->dirty = 0;
-#ifdef SQLITE_CHECK_PAGES
-    pPg->pageHash = pager_pagehash(pPg);
-#endif
-  }
-  pPager->pDirty = 0;
-  return rc;
-}
-#endif
 
 static void pager_truncate_cache(Pager *pPager);
 
@@ -2049,6 +2016,8 @@
       ppPg = &pPg->pNextAll;
     }else{
       *ppPg = pPg->pNextAll;
+      IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
+      PAGER_INCR(sqlite3_pager_pgfree_count);
       unlinkPage(pPg);
       makeClean(pPg);
       sqliteFree(pPg);
@@ -2470,9 +2439,13 @@
     if( pList->pgno<=pPager->dbSize ){
       char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
       PAGERTRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno);
-      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno))
+      IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
       rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize);
-      TEST_INCR(pPager->nWrite);
+      PAGER_INCR(sqlite3_pager_writedb_count);
+      PAGER_INCR(pPager->nWrite);
+      if( pList->pgno==1 ){
+        memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
+      }
     }
 #ifndef NDEBUG
     else{
@@ -2674,6 +2647,8 @@
           pTmp->pNextAll = pPg->pNextAll;
         }
         nReleased += sqliteAllocSize(pPg);
+        IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
+        PAGER_INCR(sqlite3_pager_pgfree_count);
         sqliteFree(pPg);
       }
 
@@ -2706,8 +2681,14 @@
     rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
                           pPager->pageSize);
   }
-  IOTRACE(("PGIN %p %d\n", pPager, pgno))
+  PAGER_INCR(sqlite3_pager_readdb_count);
+  PAGER_INCR(pPager->nRead);
+  IOTRACE(("PGIN %p %d\n", pPager, pgno));
   PAGERTRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
+  if( pgno==1 ){
+    memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24],
+                                              sizeof(pPager->dbFileVers));
+  }
   CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
   return rc;
 }
@@ -2808,16 +2789,21 @@
       if( pPager->pAll ){
         /* The shared-lock has just been acquired on the database file
         ** and there are already pages in the cache (from a previous
-        ** read or write transaction). If the value of the change-counter
-        ** stored in Pager.iChangeCount matches that found on page 1 of
-        ** the database file, then no database changes have occured since
-        ** the cache was last valid and it is safe to retain the cached
-        ** pages. Otherwise, if Pager.iChangeCount does not match the
-        ** change-counter on page 1 of the file, the current cache contents
-        ** must be discarded.
+        ** read or write transaction).  Check to see if the database
+        ** has been modified.  If the database has changed, flush the
+        ** cache.
+        **
+        ** Database changes is detected by looking at 15 bytes beginning
+        ** at offset 24 into the file.  The first 4 of these 16 bytes are
+        ** a 32-bit counter that is incremented with each change.  The
+        ** other bytes change randomly with each file change when
+        ** a codec is in use.
+        ** 
+        ** There is a vanishingly small chance that a change will not be 
+        ** deteched.  The chance of an undetected change is so small that
+        ** it can be neglected.
         */
-        u8 zC[4];
-        u32 iChangeCounter = 0;
+        char dbFileVers[sizeof(pPager->dbFileVers)];
         sqlite3PagerPagecount(pPager);
 
         if( pPager->errCode ){
@@ -2825,19 +2811,19 @@
         }
 
         if( pPager->dbSize>0 ){
-          /* Read the 4-byte change counter directly from the file. */
           rc = sqlite3OsSeek(pPager->fd, 24);
           if( rc!=SQLITE_OK ){
             return rc;
           }
-          rc = sqlite3OsRead(pPager->fd, zC, 4);
+          rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers));
           if( rc!=SQLITE_OK ){
             return rc;
           }
-          iChangeCounter = (zC[0]<<24) + (zC[1]<<16) + (zC[2]<<8) + zC[3];
+        }else{
+          memset(dbFileVers, 0, sizeof(dbFileVers));
         }
 
-        if( iChangeCounter!=pPager->iChangeCount ){
+        if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
           pager_reset(pPager);
         }
       }
@@ -2959,12 +2945,20 @@
 ** Since _lookup() never goes to disk, it never has to deal with locks
 ** or journal files.
 **
-** If clrFlag is false, the page contents are actually read from disk.
-** If clfFlag is true, it means the page is about to be erased and
-** rewritten without first being read so there is no point it doing
-** the disk I/O.
-*/
-int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int 
clrFlag){
+** If noContent is false, the page contents are actually read from disk.
+** If noContent is true, it means that we do not care about the contents
+** of the page at this time, so do not do a disk read.  Just fill in the
+** page content with zeros.  But mark the fact that we have not read the
+** content by setting the PgHdr.needRead flag.  Later on, if 
+** sqlite3PagerWrite() is called on this page, that means that the
+** content is needed and the disk read should occur at that point.
+*/
+int sqlite3PagerAcquire(
+  Pager *pPager,      /* The pager open on the database file */
+  Pgno pgno,          /* Page number to fetch */
+  DbPage **ppPage,    /* Write a pointer to the page here */
+  int noContent       /* Do not bother reading content from disk if true */
+){
   PgHdr *pPg;
   int rc;
 
@@ -3000,7 +2994,7 @@
     /* The requested page is not in the page cache. */
     int nMax;
     int h;
-    TEST_INCR(pPager->nMiss);
+    PAGER_INCR(pPager->nMiss);
     rc = pagerAllocatePage(pPager, &pPg);
     if( rc!=SQLITE_OK ){
       return rc;
@@ -3036,16 +3030,16 @@
     /* Populate the page with data, either by reading from the database
     ** file, or by setting the entire page to zero.
     */
-    if( nMax<(int)pgno || MEMDB || (clrFlag && !pPager->alwaysRollback) ){
+    if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){
       memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
+      pPg->needRead = noContent && !pPager->alwaysRollback;
+      IOTRACE(("ZERO %p %d\n", pPager, pgno));
     }else{
       rc = readDbPage(pPager, pPg, pgno);
       if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
         pPg->pgno = 0;
         sqlite3PagerUnref(pPg);
         return rc;
-      }else{
-        TEST_INCR(pPager->nRead);
       }
     }
 
@@ -3065,7 +3059,7 @@
   }else{
     /* The requested page is in the page cache. */
     assert(pPager->nRef>0 || pgno==1);
-    TEST_INCR(pPager->nHit);
+    PAGER_INCR(pPager->nHit);
     page_ref(pPg);
   }
   *ppPage = pPg;
@@ -3365,6 +3359,23 @@
 
   CHECK_PAGE(pPg);
 
+  /* If this page was previously acquired with noContent==1, that means
+  ** we didn't really read in the content of the page.  This can happen
+  ** (for example) when the page is being moved to the freelist.  But
+  ** now we are (perhaps) moving the page off of the freelist for
+  ** reuse and we need to know its original content so that content
+  ** can be stored in the rollback journal.  So do the read at this
+  ** time.
+  */
+  if( pPg->needRead ){
+    rc = readDbPage(pPager, pPg, pPg->pgno);
+    if( rc==SQLITE_OK ){
+      pPg->needRead = 0;
+    }else{
+      return rc;
+    }
+  }
+
   /* Mark the page as dirty.  If the page has already been written
   ** to the journal then we can return right away.
   */
@@ -3425,7 +3436,8 @@
           put32bits(pData2, pPg->pgno);
           rc = sqlite3OsWrite(pPager->jfd, pData2, szPg);
           IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
-                   pPager->journalOff, szPg))
+                   pPager->journalOff, szPg));
+          PAGER_INCR(sqlite3_pager_writej_count);
           pPager->journalOff += szPg;
           PAGERTRACE4("JOURNAL %d page %d needSync=%d\n",
                   PAGERID(pPager), pPg->pgno, pPg->needSync);
@@ -3608,7 +3620,7 @@
 
 /*
 ** A call to this routine tells the pager that it is not necessary to
-** write the information on page "pgno" back to the disk, even though
+** write the information on page pPg back to the disk, even though
 ** that page might be marked as dirty.
 **
 ** The overlying software layer calls this routine when all of the data
@@ -3630,13 +3642,11 @@
 ** page contains critical data, we still need to be sure it gets
 ** rolled back in spite of the sqlite3PagerDontRollback() call.
 */
-void sqlite3PagerDontWrite(Pager *pPager, Pgno pgno){
-  PgHdr *pPg;
+void sqlite3PagerDontWrite(DbPage *pDbPage){
+  PgHdr *pPg = pDbPage;
+  Pager *pPager = pPg->pPager;
 
   if( MEMDB ) return;
-
-  pPg = pager_lookup(pPager, pgno);
-  assert( pPg!=0 );  /* We never call _dont_write unless the page is in mem */
   pPg->alwaysRollback = 1;
   if( pPg->dirty && !pPager->stmtInUse ){
     assert( pPager->state>=PAGER_SHARED );
@@ -3650,8 +3660,8 @@
       ** corruption during the next transaction.
       */
     }else{
-      PAGERTRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
-      IOTRACE(("CLEAN %p %d\n", pPager, pgno))
+      PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager));
+      IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
       makeClean(pPg);
 #ifdef SQLITE_CHECK_PAGES
       pPg->pageHash = pager_pagehash(pPg);
@@ -3665,6 +3675,11 @@
 ** it is not necessary to restore the data on the given page.  This
 ** means that the pager does not have to record the given page in the
 ** rollback journal.
+**
+** If we have not yet actually read the content of this page (if
+** the PgHdr.needRead flag is set) then this routine acts as a promise
+** that we will never need to read the page content in the future.
+** so the needRead flag can be cleared at this point.
 */
 void sqlite3PagerDontRollback(DbPage *pPg){
   Pager *pPager = pPg->pPager;
@@ -3676,6 +3691,7 @@
     assert( pPager->aInJournal!=0 );
     pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
     pPg->inJournal = 1;
+    pPg->needRead = 0;
     if( pPager->stmtInUse ){
       pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
     }
@@ -3715,7 +3731,6 @@
     /* Increment the value just read and write it back to byte 24. */
     change_counter++;
     put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter);
-    pPager->iChangeCount = change_counter;
   
     /* Release the page reference. */
     sqlite3PagerUnref(pPgHdr);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/pager.h?r1=1.3.2.2.2.3&r2=1.3.2.2.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/pager.h
diff -u php-src/ext/pdo_sqlite/sqlite/src/pager.h:1.3.2.2.2.3 
php-src/ext/pdo_sqlite/sqlite/src/pager.h:1.3.2.2.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/pager.h:1.3.2.2.2.3       Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/pager.h   Wed Apr 18 22:53:46 2007
@@ -109,7 +109,7 @@
 int sqlite3PagerStmtCommit(Pager*);
 int sqlite3PagerStmtRollback(Pager*);
 void sqlite3PagerDontRollback(DbPage*);
-void sqlite3PagerDontWrite(Pager*, Pgno);
+void sqlite3PagerDontWrite(DbPage*);
 int sqlite3PagerRefcount(Pager*);
 int *sqlite3PagerStats(Pager*);
 void sqlite3PagerSetSafetyLevel(Pager*,int,int);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/parse.y?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/select.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/select.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/select.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/select.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/select.c:1.3.2.2.2.4      Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/select.c  Wed Apr 18 22:53:46 2007
@@ -551,6 +551,7 @@
       sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
       addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
+      p->affinity = 
sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff);
       if( pOrderBy ){
         /* At first glance you would think we could optimize out the
         ** ORDER BY in this case since the order of entries in the set
@@ -558,9 +559,7 @@
         ** case the order does matter */
         pushOntoSorter(pParse, pOrderBy, p);
       }else{
-        char affinity = (iParm>>16)&0xFF;
-        affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, affinity);
-        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);
+        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
         sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
       }
       sqlite3VdbeJumpHere(v, addr2);
@@ -721,7 +720,7 @@
       sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
       sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
-      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "c", P3_STATIC);
+      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
       sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
       break;
     }
@@ -1096,7 +1095,7 @@
     sqlite3Dequote(zName);
     if( sqlite3MallocFailed() ){
       sqliteFree(zName);
-      sqlite3DeleteTable(0, pTab);
+      sqlite3DeleteTable(pTab);
       return 0;
     }
 
@@ -1400,8 +1399,11 @@
   }
   pEList = pSelect->pEList;
   for(i=0; i<pOrderBy->nExpr; i++){
+    struct ExprList_item *pItem;
     Expr *pE = pOrderBy->a[i].pExpr;
     int iCol = -1;
+    char *zLabel;
+
     if( pOrderBy->a[i].done ) continue;
     if( sqlite3ExprIsInteger(pE, &iCol) ){
       if( iCol<=0 || iCol>pEList->nExpr ){
@@ -1414,20 +1416,23 @@
       if( !mustComplete ) continue;
       iCol--;
     }
-    for(j=0; iCol<0 && j<pEList->nExpr; j++){
-      if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
-        char *zName, *zLabel;
-        zName = pEList->a[j].zName;
-        zLabel = sqlite3NameFromToken(&pE->token);
-        assert( zLabel!=0 );
-        if( sqlite3StrICmp(zName, zLabel)==0 ){ 
+    if( iCol<0 && (zLabel = sqlite3NameFromToken(&pE->token))!=0 ){
+      for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
+        char *zName;
+        int isMatch;
+        if( pItem->zName ){
+          zName = sqlite3StrDup(pItem->zName);
+        }else{
+          zName = sqlite3NameFromToken(&pItem->pExpr->token);
+        }
+        isMatch = zName && sqlite3StrICmp(zName, zLabel)==0;
+        sqliteFree(zName);
+        if( isMatch ){
           iCol = j;
+          break;
         }
-        sqliteFree(zLabel);
-      }
-      if( iCol<0 && sqlite3ExprCompare(pE, pEList->a[j].pExpr) ){
-        iCol = j;
       }
+      sqliteFree(zLabel);
     }
     if( iCol>=0 ){
       pE->op = TK_COLUMN;
@@ -1435,8 +1440,7 @@
       pE->iTable = iTable;
       pE->iAgg = -1;
       pOrderBy->a[i].done = 1;
-    }
-    if( iCol<0 && mustComplete ){
+    }else if( mustComplete ){
       sqlite3ErrorMsg(pParse,
         "ORDER BY term number %d does not match any result column", i+1);
       nErr++;
@@ -2212,7 +2216,7 @@
     int nSubSrc = pSubSrc->nSrc;
     int jointype = pSubitem->jointype;
 
-    sqlite3DeleteTable(0, pSubitem->pTab);
+    sqlite3DeleteTable(pSubitem->pTab);
     sqliteFree(pSubitem->zDatabase);
     sqliteFree(pSubitem->zName);
     sqliteFree(pSubitem->zAlias);
@@ -2590,12 +2594,15 @@
   */
   sNC.pEList = p->pEList;
   if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
-      sqlite3ExprResolveNames(&sNC, p->pHaving) ||
-      processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ||
-      processOrderGroupBy(&sNC, pGroupBy, "GROUP")
-  ){
+     sqlite3ExprResolveNames(&sNC, p->pHaving) ){
     return SQLITE_ERROR;
   }
+  if( p->pPrior==0 ){
+    if( processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ||
+        processOrderGroupBy(&sNC, pGroupBy, "GROUP") ){
+      return SQLITE_ERROR;
+    }
+  }
 
   /* Make sure the GROUP BY clause does not contain aggregate functions.
   */
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h
diff -u php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h:1.3.2.2.2.4   Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/sqliteInt.h       Wed Apr 18 22:53:46 2007
@@ -381,6 +381,14 @@
 
 /*
 ** An instance of the following structure stores a database schema.
+**
+** If there are no virtual tables configured in this schema, the
+** Schema.db variable is set to NULL. After the first virtual table
+** has been added, it is set to point to the database connection 
+** used to create the connection. Once a virtual table has been
+** added to the Schema structure and the Schema.db variable populated, 
+** only that database connection may use the Schema to prepare 
+** statements.
 */
 struct Schema {
   int schema_cookie;   /* Database schema version number for this file */
@@ -393,6 +401,9 @@
   u8 enc;              /* Text encoding used by this database */
   u16 flags;           /* Flags associated with this schema */
   int cache_size;      /* Number of pages to use in the cache */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  sqlite3 *db;         /* "Owner" connection. See comment above */
+#endif
 };
 
 /*
@@ -1266,6 +1277,7 @@
   u8 isAgg;              /* True if this is an aggregate query */
   u8 usesEphm;           /* True if uses an OpenEphemeral opcode */
   u8 disallowOrderBy;    /* Do not allow an ORDER BY to be attached if TRUE */
+  char affinity;         /* MakeRecord with this affinity for SRT_Set */
   SrcList *pSrc;         /* The FROM clause */
   Expr *pWhere;          /* The WHERE clause */
   ExprList *pGroupBy;    /* The GROUP BY clause */
@@ -1631,7 +1643,7 @@
 #endif
 
 void sqlite3DropTable(Parse*, SrcList*, int, int);
-void sqlite3DeleteTable(sqlite3*, Table*);
+void sqlite3DeleteTable(Table*);
 void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
 void *sqlite3ArrayAllocate(void*,int,int,int*,int*,int*);
 IdList *sqlite3IdListAppend(IdList*, Token*);
@@ -1889,7 +1901,7 @@
    int sqlite3VtabCommit(sqlite3 *db);
 #endif
 void sqlite3VtabLock(sqlite3_vtab*);
-void sqlite3VtabUnlock(sqlite3_vtab*);
+void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*);
 void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
 void sqlite3VtabFinishParse(Parse*, Token*);
 void sqlite3VtabArgInit(Parse*);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/test1.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/test1.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/test1.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/test1.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/test1.c:1.3.2.2.2.4       Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/test1.c   Wed Apr 18 22:53:46 2007
@@ -198,6 +198,57 @@
 }
 
 /*
+** The I/O tracing callback.
+*/
+static FILE *iotrace_file = 0;
+static void io_trace_callback(const char *zFormat, ...){
+  va_list ap;
+  va_start(ap, zFormat);
+  vfprintf(iotrace_file, zFormat, ap);
+  va_end(ap);
+  fflush(iotrace_file);
+}
+
+/*
+** Usage:  io_trace FILENAME
+**
+** Turn I/O tracing on or off.  If FILENAME is not an empty string,
+** I/O tracing begins going into FILENAME. If FILENAME is an empty
+** string, I/O tracing is turned off.
+*/
+static int test_io_trace(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  char **argv            /* Text of each argument */
+){
+  if( argc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+          " FILENAME\"", 0);
+    return TCL_ERROR;
+  }
+  if( iotrace_file ){
+    if( iotrace_file!=stdout && iotrace_file!=stderr ){
+      fclose(iotrace_file);
+    }
+    iotrace_file = 0;
+    sqlite3_io_trace = 0;
+  }
+  if( argv[1][0] ){
+    if( strcmp(argv[1],"stdout")==0 ){
+      iotrace_file = stdout;
+    }else if( strcmp(argv[1],"stderr")==0 ){
+      iotrace_file = stderr;
+    }else{
+      iotrace_file = fopen(argv[1], "w");
+    }
+    sqlite3_io_trace = io_trace_callback;
+  }
+  return SQLITE_OK;
+}
+
+
+/*
 ** Usage:  sqlite3_exec_printf  DB  FORMAT  STRING
 **
 ** Invoke the sqlite3_exec_printf() interface using the open database
@@ -4216,6 +4267,7 @@
      { "sqlite3_stack_used",            (Tcl_CmdProc*)test_stack_used       },
      { "sqlite3_busy_timeout",          (Tcl_CmdProc*)test_busy_timeout     },
      { "printf",                        (Tcl_CmdProc*)test_printf           },
+     { "sqlite3_io_trace",              (Tcl_CmdProc*)test_io_trace         },
   };
   static struct {
      char *zName;
@@ -4338,6 +4390,10 @@
   extern int sqlite3_like_count;
   extern int sqlite3_tsd_count;
   extern int sqlite3_xferopt_count;
+  extern int sqlite3_pager_readdb_count;
+  extern int sqlite3_pager_writedb_count;
+  extern int sqlite3_pager_writej_count;
+  extern int sqlite3_pager_pgfree_count;
 #if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
   extern int threadsOverrideEachOthersLocks;
 #endif
@@ -4377,6 +4433,14 @@
       (char*)&sqlite3_tsd_count, TCL_LINK_INT);
   Tcl_LinkVar(interp, "sqlite3_xferopt_count",
       (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
+      (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
+      (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
+      (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
+  Tcl_LinkVar(interp, "sqlite3_pager_pgfree_count",
+      (char*)&sqlite3_pager_pgfree_count, TCL_LINK_INT);
 #ifndef SQLITE_OMIT_UTF16
   Tcl_LinkVar(interp, "unaligned_string_counter",
       (char*)&unaligned_string_counter, TCL_LINK_INT);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/tokenize.c?r1=1.3.2.2.2.2&r2=1.3.2.2.2.3&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/tokenize.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/tokenize.c:1.3.2.2.2.2 
php-src/ext/pdo_sqlite/sqlite/src/tokenize.c:1.3.2.2.2.3
--- php-src/ext/pdo_sqlite/sqlite/src/tokenize.c:1.3.2.2.2.2    Fri Feb  9 
03:17:47 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/tokenize.c        Wed Apr 18 22:53:46 2007
@@ -495,7 +495,7 @@
     ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
     ** will take responsibility for freeing the Table structure.
     */
-    sqlite3DeleteTable(pParse->db, pParse->pNewTable);
+    sqlite3DeleteTable(pParse->pNewTable);
   }
 
   sqlite3DeleteTrigger(pParse->pNewTrigger);
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/vdbe.c?r1=1.3.2.2.2.3&r2=1.3.2.2.2.4&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/vdbe.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/vdbe.c:1.3.2.2.2.3 
php-src/ext/pdo_sqlite/sqlite/src/vdbe.c:1.3.2.2.2.4
--- php-src/ext/pdo_sqlite/sqlite/src/vdbe.c:1.3.2.2.2.3        Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/vdbe.c    Wed Apr 18 22:53:46 2007
@@ -2521,7 +2521,23 @@
   }
   if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
     sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0);
-    sqlite3ResetInternalSchema(db, pOp->p1);
+    /* If the schema-cookie from the database file matches the cookie 
+    ** stored with the in-memory representation of the schema, do
+    ** not reload the schema from the database file.
+    **
+    ** If virtual-tables are in use, this is not just an optimisation.
+    ** Often, v-tables store their data in other SQLite tables, which
+    ** are queried from within xNext() and other v-table methods using
+    ** prepared queries. If such a query is out-of-date, we do not want to
+    ** discard the database schema, as the user code implementing the
+    ** v-table would have to be ready for the sqlite3_vtab structure itself
+    ** to be invalidated whenever sqlite3_step() is called from within 
+    ** a v-table method.
+    */
+    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
+      sqlite3ResetInternalSchema(db, pOp->p1);
+    }
+
     sqlite3ExpirePreparedStatements(db);
     rc = SQLITE_SCHEMA;
   }
@@ -4881,7 +4897,7 @@
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     sqlite3VtabLock(pVtab);
     rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
-    sqlite3VtabUnlock(pVtab);
+    sqlite3VtabUnlock(db, pVtab);
     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
     if( pOp->p1 && rc==SQLITE_OK ){
       assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c?r1=1.3.2.2.2.4&r2=1.3.2.2.2.5&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c:1.3.2.2.2.4 
php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c:1.3.2.2.2.5
--- php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c:1.3.2.2.2.4     Mon Apr  9 
16:35:11 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/vdbeaux.c Wed Apr 18 22:53:46 2007
@@ -145,7 +145,6 @@
   VdbeOp *pOp;
 
   i = p->nOp;
-  p->nOp++;
   assert( p->magic==VDBE_MAGIC_INIT );
   if( p->nOpAlloc<=i ){
     resizeOpArray(p, i+1);
@@ -153,6 +152,7 @@
       return 0;
     }
   }
+  p->nOp++;
   pOp = &p->aOp[i];
   pOp->opcode = op;
   pOp->p1 = p1;
@@ -557,9 +557,8 @@
 */
 void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
   va_list ap;
-  assert( p->nOp>0 );
-  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 
-          || sqlite3MallocFailed() );
+  assert( p->nOp>0 || p->aOp==0 );
+  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || sqlite3MallocFailed() );
   va_start(ap, zFormat);
   sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);
   va_end(ap);
@@ -571,8 +570,8 @@
 */
 VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
   assert( p->magic==VDBE_MAGIC_INIT );
-  assert( addr>=0 && addr<p->nOp );
-  return &p->aOp[addr];
+  assert( (addr>=0 && addr<p->nOp) || sqlite3MallocFailed() );
+  return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0);
 }
 
 #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
http://cvs.php.net/viewvc.cgi/php-src/ext/pdo_sqlite/sqlite/src/vtab.c?r1=1.1.2.2&r2=1.1.2.3&diff_format=u
Index: php-src/ext/pdo_sqlite/sqlite/src/vtab.c
diff -u php-src/ext/pdo_sqlite/sqlite/src/vtab.c:1.1.2.2 
php-src/ext/pdo_sqlite/sqlite/src/vtab.c:1.1.2.3
--- php-src/ext/pdo_sqlite/sqlite/src/vtab.c:1.1.2.2    Fri Feb  9 03:17:47 2007
+++ php-src/ext/pdo_sqlite/sqlite/src/vtab.c    Wed Apr 18 22:53:46 2007
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.1.2.2 2007/02/09 03:17:47 iliaa Exp $
+** $Id: vtab.c,v 1.1.2.3 2007/04/18 22:53:46 iliaa Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -56,10 +56,18 @@
 ** Unlock a virtual table.  When the last lock is removed,
 ** disconnect the virtual table.
 */
-void sqlite3VtabUnlock(sqlite3_vtab *pVtab){
+void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
   pVtab->nRef--;
+  assert(db);
+  assert(!sqlite3SafetyCheck(db));
   if( pVtab->nRef==0 ){
-    pVtab->pModule->xDisconnect(pVtab);
+    if( db->magic==SQLITE_MAGIC_BUSY ){
+      sqlite3SafetyOff(db);
+      pVtab->pModule->xDisconnect(pVtab);
+      sqlite3SafetyOn(db);
+    } else {
+      pVtab->pModule->xDisconnect(pVtab);
+    }
   }
 }
 
@@ -72,7 +80,7 @@
   sqlite3_vtab *pVtab = p->pVtab;
   if( pVtab ){
     assert( p->pMod && p->pMod->pModule );
-    sqlite3VtabUnlock(pVtab);
+    sqlite3VtabUnlock(p->pSchema->db, pVtab);
     p->pVtab = 0;
   }
   if( p->azModuleArg ){
@@ -124,6 +132,11 @@
   int iDb;              /* The database the table is being created in */
   Table *pTable;        /* The new virtual table */
 
+  if( sqlite3ThreadDataReadOnly()->useSharedData ){
+    sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
+    return;
+  }
+
   sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
   pTable = pParse->pNewTable;
   if( pTable==0 || pParse->nErr ) return;
@@ -248,6 +261,7 @@
       assert( pTab==pOld );  /* Malloc must have failed inside HashInsert() */
       return;
     }
+    pSchema->db = pParse->db;
     pParse->pNewTable = 0;
   }
 }
@@ -297,6 +311,10 @@
   char *zErr = 0;
   char *zModuleName = sqlite3MPrintf("%s", pTab->zName);
 
+  if( !zModuleName ){
+    return SQLITE_NOMEM;
+  }
+
   assert( !db->pVTab );
   assert( xConstruct );
 
@@ -457,6 +475,7 @@
     pTab->nCol = sParse.pNewTable->nCol;
     sParse.pNewTable->nCol = 0;
     sParse.pNewTable->aCol = 0;
+    db->pVTab = 0;
   } else {
     sqlite3Error(db, SQLITE_ERROR, zErr);
     sqliteFree(zErr);
@@ -465,12 +484,11 @@
   sParse.declareVtab = 0;
 
   sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
-  sqlite3DeleteTable(0, sParse.pNewTable);
+  sqlite3DeleteTable(sParse.pNewTable);
   sParse.pNewTable = 0;
-  db->pVTab = 0;
 
   assert( (rc&0xff)==rc );
-  return rc;
+  return sqlite3ApiExit(db, rc);
 }
 
 /*
@@ -518,7 +536,7 @@
     int (*x)(sqlite3_vtab *);
     x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
     if( x ) x(pVtab);
-    sqlite3VtabUnlock(pVtab);
+    sqlite3VtabUnlock(db, pVtab);
   }
   sqliteFree(db->aVTrans);
   db->nVTrans = 0;

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to