# # # patch "ChangeLog" # from [7044edcbf9586840754451d599adce80fd28085e] # to [7fbfacfd6eb7f8444712762f48501ae2b206ad6b] # # patch "sqlite/alter.c" # from [faf98b04050d674d06df21bcf23ded5bbff7b5b7] # to [451b34fc4eb2475ca76a2e86b21e1030a9428091] # # patch "sqlite/btree.c" # from [f45f57e6cbd3b3db947cdd699db64e5215d20b2a] # to [23bbfb4745e549ca224f6c933a6e9bc106d77f56] # # patch "sqlite/btree.h" # from [5663c4f43e8521546ccebc8fc95acb013b8f3184] # to [40055cfc09defd1146bc5b922399c035f969e56d] # # patch "sqlite/build.c" # from [feaa61e769d7887ffeaa060d746638c7b3e994ef] # to [b46cd7d0e2daca775d9de0cba8abae1b1625caf4] # # patch "sqlite/date.c" # from [c70a4f88e495ae2c523f6ef3848c26a021c96de8] # to [cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e] # # patch "sqlite/delete.c" # from [56ab34c3a384caa5d5ea06f5739944957e2e4213] # to [ca404d5fd5f678e32f2f46377ad802cd0219aa99] # # patch "sqlite/expr.c" # from [1149c3380bfce27703f5e9bec7dfb8e51baaf9d9] # to [9c957fabf95ef62288151eecd5c490a629470666] # # patch "sqlite/func.c" # from [96b26601c092b7b43a13e440e3f988b32a385f6a] # to [93d004b453a5d9aa754e673eef75d3c9527e0f54] # # patch "sqlite/insert.c" # from [7e931b7f06afbcefcbbaab175c02eff8268db33f] # to [67b3dc11831c58d8703eb502355ad3704ee18f66] # # patch "sqlite/main.c" # from [2693776249865dc69b97904205638e84a34a059c] # to [9a42464c44a6532003391486e802e65e88789cfc] # # patch "sqlite/os_common.h" # from [061fba8511a656b118551424f64e366ad0d4cb3b] # to [108cd719c96a2b714b64e02aeabbd40684274e6a] # # patch "sqlite/os_unix.c" # from [73c5e722a661ed98d8919f204911e4e34e51fa41] # to [378a89aaf15d83b901c1b73350e91ddecf743986] # # patch "sqlite/os_win.c" # from [566bf7b41b72556fd7dca390bceaa2769dc395e9] # to [c67a2c46d929cf54c8f80ec5e6079cf684a141a9] # # patch "sqlite/pager.c" # from [b5b380ea7a36f84e50c3adc1a414820a0eb3baa6] # to [c438aa5fc248e0523e80591eeae33a3993c47278] # # patch "sqlite/pager.h" # from [e0acb095b3ad0bca48f2ab00c87346665643f64f] # to [425a9e52d5404158de016799715cbc2c3d685178] # # patch "sqlite/parse.h" # from [20eb1ccb1fa5d4e4493dd0ca916ad74b515eefcf] # to [ae4ee794251454f9c8b4c97ef7fee85deecdcec5] # # patch "sqlite/pragma.c" # from [4496cc77dc35824e1c978c3d1413b8a5a4c777d3] # to [31d3e1b74cab2172807894e70c674d6a577501fd] # # patch "sqlite/prepare.c" # from [40ae23c8aeb641dc7b9bb271eb5e295b815154a7] # to [cf0fc8ebaf94409955ecb09ffeb0099c9ef44693] # # patch "sqlite/select.c" # from [daee9b20702ba51cf3807fc1b130edd8846e3e48] # to [7d069e875d0eec05129c7e8b9c99422d7c9c6321] # # patch "sqlite/sqlite3.h" # from [6b9ed927e0a9a3c6051a372929c97c2ac87ab314] # to [d0605a62334179d9c38bf587ac38b777d6daee2b] # # patch "sqlite/sqliteInt.h" # from [0121298397ac14eb468ab1ba9d488ac7ed7d88a1] # to [f61b60f243f1709c943c62cfb6d7a50209080e38] # # patch "sqlite/table.c" # from [486dcfce532685b53b5a2b5da8bba0ded6fb2316] # to [f64ec4fbfe333f8df925bc6ba494f55e05b0e75e] # # patch "sqlite/tokenize.c" # from [9ae9a59238eb97fbc61baea280563b91100518fb] # to [382b3bb0ca26eb9153b5d20b246ef512a114a24f] # # patch "sqlite/update.c" # from [14be4ba2f438919b4217085c02feff569e6cf1f2] # to [050a7e0ddaac03dec5271712eee62f1a9e699049] # # patch "sqlite/util.c" # from [82ee598519b8193184bdeab06b51a4ffa05ad60b] # to [405f46fef062b476826d2c171ec21def29563b75] # # patch "sqlite/vdbe.c" # from [fee677e05236e483d6c75d1d4229955fc1b89193] # to [0a7fd81609429bae2b3c326687b02a60a9c01c49] # # patch "sqlite/vdbe.h" # from [8729a4ee16ff9aeab2af9667df3cf300ff978e13] # to [80ba1c391ec28180dd07a630577f50b22c2062da] # # patch "sqlite/vdbeapi.c" # from [dcb2636f49b4807e34960d52a2fc257b3a751140] # to [7dc662e7c905ce666bb506dced932e0307115cbf] # # patch "sqlite/vdbeaux.c" # from [9bf50cdb6a6c40b8c06ca9a8d87cf90120a16797] # to [95f4ed0bc8ed45f16823d84504310495b5dc587d] # # patch "sqlite/where.c" # from [8409e00fa2cb5fce873b4c911165cfed097e9c49] # to [c7d71d5e55c9c4c1e948089280fb0dec7c7d1ef6] # ============================================================ --- ChangeLog 7044edcbf9586840754451d599adce80fd28085e +++ ChangeLog 7fbfacfd6eb7f8444712762f48501ae2b206ad6b @@ -1,3 +1,7 @@ +2006-02-17 Matthew Gregan + + * sqlite/*: Import SQLite 3.3.4. + 2006-02-16 Patrick Mauritz * netsync.cc (handle_new_connection): Netxx::Address.get_name() ============================================================ --- sqlite/alter.c faf98b04050d674d06df21bcf23ded5bbff7b5b7 +++ sqlite/alter.c 451b34fc4eb2475ca76a2e86b21e1030a9428091 @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.19 2006/01/31 14:28:45 drh Exp $ +** $Id: alter.c,v 1.20 2006/02/09 02:56:03 drh Exp $ */ #include "sqliteInt.h" #include @@ -541,6 +541,7 @@ for(i=0; inCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqliteStrDup(pCol->zName); + pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; } ============================================================ --- sqlite/btree.c f45f57e6cbd3b3db947cdd699db64e5215d20b2a +++ sqlite/btree.c 23bbfb4745e549ca224f6c933a6e9bc106d77f56 @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.311 2006/01/24 16:37:58 danielk1977 Exp $ +** $Id: btree.c,v 1.314 2006/02/11 01:25:51 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -411,8 +411,8 @@ ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in -** this state, restoreOrClearCursorPosition() can be called to attempt to seek -** the cursor to the saved position. +** this state, restoreOrClearCursorPosition() can be called to attempt to +** seek the cursor to the saved position. */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 @@ -756,10 +756,20 @@ ** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements ** this test. */ -#define PTRMAP_PAGENO(pgsz, pgno) (((pgno-2)/(pgsz/5+1))*(pgsz/5+1)+2) -#define PTRMAP_PTROFFSET(pgsz, pgno) (((pgno-2)%(pgsz/5+1)-1)*5) -#define PTRMAP_ISPAGE(pgsz, pgno) (PTRMAP_PAGENO(pgsz,pgno)==pgno) +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage = (pBt->usableSize/5)+1; + int iPtrMap = (pgno-2)/nPagesPerMapPage; + int ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} + /* ** The pointer map is a lookup table that identifies the parent page for ** each child page in the database file. The parent page is the page that @@ -810,16 +820,19 @@ int offset; /* Offset in pointer map page */ int rc; + /* The master-journal page number must never be used as a pointer map page */ + assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); + assert( pBt->autoVacuum ); if( key==0 ){ return SQLITE_CORRUPT_BKPT; } - iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); + iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=SQLITE_OK ){ return rc; } - offset = PTRMAP_PTROFFSET(pBt->usableSize, key); + offset = PTRMAP_PTROFFSET(pBt, key); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); @@ -847,13 +860,13 @@ int offset; /* Offset of entry in pointer map */ int rc; - iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key); + iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=0 ){ return rc; } - offset = PTRMAP_PTROFFSET(pBt->usableSize, key); + offset = PTRMAP_PTROFFSET(pBt, key); if( pEType ) *pEType = pPtrmap[offset]; if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); @@ -1790,9 +1803,9 @@ ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -int sqlite3BtreeSetSafetyLevel(Btree *p, int level){ +int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; - sqlite3pager_set_safety_level(pBt->pPager, level); + sqlite3pager_set_safety_level(pBt->pPager, level, fullSync); return SQLITE_OK; } #endif @@ -2344,7 +2357,7 @@ #endif assert( pBt->autoVacuum ); - if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){ + if( PTRMAP_ISPAGE(pBt, sqlite3pager_pagecount(pPager)) ){ return SQLITE_CORRUPT_BKPT; } @@ -2357,15 +2370,27 @@ return SQLITE_OK; } + /* This block figures out how many pages there are in the database + ** now (variable origSize), and how many there will be after the + ** truncation (variable finSize). + ** + ** The final size is the original size, less the number of free pages + ** in the database, less any pointer-map pages that will no longer + ** be required, less 1 if the pending-byte page was part of the database + ** but is not after the truncation. + **/ origSize = sqlite3pager_pagecount(pPager); - nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5); + if( origSize==PENDING_BYTE_PAGE(pBt) ){ + origSize--; + } + nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pBt, origSize)+pgsz/5)/(pgsz/5); finSize = origSize - nFreeList - nPtrMap; - if( origSize>=PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){ + if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){ finSize--; - if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){ - finSize--; - } } + while( PTRMAP_ISPAGE(pBt, finSize) || finSize==PENDING_BYTE_PAGE(pBt) ){ + finSize--; + } TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize)); /* Variable 'finSize' will be the size of the file in pages after @@ -2376,7 +2401,7 @@ */ for( iDbPage=finSize+1; iDbPage<=origSize; iDbPage++ ){ /* If iDbPage is a pointer map page, or the pending-byte page, skip it. */ - if( PTRMAP_ISPAGE(pgsz, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ + if( PTRMAP_ISPAGE(pBt, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){ continue; } @@ -2434,6 +2459,7 @@ put4byte(&pBt->pPage1->aData[36], 0); if( rc!=SQLITE_OK ) goto autovacuum_out; *nTrunc = finSize; + assert( finSize!=PENDING_BYTE_PAGE(pBt) ); autovacuum_out: assert( nRef==*sqlite3pager_stats(pPager) ); @@ -3806,7 +3832,7 @@ *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1; #ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt->usableSize, *pPgno) ){ + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. @@ -5440,7 +5466,7 @@ /* The new root-page may not be allocated on a pointer-map page, or the ** PENDING_BYTE page. */ - if( pgnoRoot==PTRMAP_PAGENO(pBt->usableSize, pgnoRoot) || + if( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ pgnoRoot++; } @@ -5713,7 +5739,7 @@ if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ maxRootPgno--; } - if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){ + if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ maxRootPgno--; } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); @@ -6390,11 +6416,11 @@ ** references to pointer-map pages. */ if( sCheck.anRef[i]==0 && - (PTRMAP_PAGENO(pBt->usableSize, i)!=i || !pBt->autoVacuum) ){ + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } if( sCheck.anRef[i]!=0 && - (PTRMAP_PAGENO(pBt->usableSize, i)==i && pBt->autoVacuum) ){ + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } #endif @@ -6522,19 +6548,21 @@ ** the write-transaction for this database file is to delete the journal. */ int sqlite3BtreeSync(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; if( p->inTrans==TRANS_WRITE ){ BtShared *pBt = p->pBt; -#ifndef SQLITE_OMIT_AUTOVACUUM Pgno nTrunc = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ - int rc = autoVacuumCommit(pBt, &nTrunc); - if( rc!=SQLITE_OK ) return rc; + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + return rc; + } } - return sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); #endif - return sqlite3pager_sync(pBt->pPager, zMaster, 0); + rc = sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); } - return SQLITE_OK; + return rc; } /* ============================================================ --- sqlite/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184 +++ sqlite/btree.h 40055cfc09defd1146bc5b922399c035f969e56d @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.69 2006/01/07 13:21:04 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.70 2006/02/11 01:25:51 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -59,7 +59,7 @@ int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*); int sqlite3BtreeSetCacheSize(Btree*,int); -int sqlite3BtreeSetSafetyLevel(Btree*,int); +int sqlite3BtreeSetSafetyLevel(Btree*,int,int); int sqlite3BtreeSyncDisabled(Btree*); int sqlite3BtreeSetPageSize(Btree*,int,int); int sqlite3BtreeGetPageSize(Btree*); ============================================================ --- sqlite/build.c feaa61e769d7887ffeaa060d746638c7b3e994ef +++ sqlite/build.c b46cd7d0e2daca775d9de0cba8abae1b1625caf4 @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.383 2006/01/24 12:09:19 danielk1977 Exp $ +** $Id: build.c,v 1.386 2006/02/10 18:08:09 drh Exp $ */ #include "sqliteInt.h" #include @@ -1662,12 +1662,10 @@ ** Actually, this error is caught previously and so the following test ** should always fail. But we will leave it in place just to be safe. */ -#if 0 if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } -#endif assert( pTable->nCol>=0 ); /* If we get this far, it means we need to compute the table names. @@ -2364,10 +2362,10 @@ nExtra /* Collation sequence names */ ); if( sqlite3MallocFailed() ) goto exit_create_index; - pIndex->aiColumn = (int *)(&pIndex[1]); + pIndex->azColl = (char**)(&pIndex[1]); + pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); - pIndex->azColl = (char **)(&pIndex->aiRowEst[nCol+1]); - pIndex->aSortOrder = (u8 *)(&pIndex->azColl[nCol]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]); pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); zExtra = (char *)(&pIndex->zName[nName+1]); strcpy(pIndex->zName, zName); @@ -2849,6 +2847,7 @@ pItem->zName = sqlite3NameFromToken(pTable); pItem->zDatabase = sqlite3NameFromToken(pDatabase); pItem->iCursor = -1; + pItem->isPopulated = 0; pList->nSrc++; return pList; } ============================================================ --- sqlite/date.c c70a4f88e495ae2c523f6ef3848c26a021c96de8 +++ sqlite/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.53 2006/01/24 12:09:19 danielk1977 Exp $ +** $Id: date.c,v 1.54 2006/01/31 20:49:13 drh Exp $ ** ** NOTES: ** @@ -117,8 +117,8 @@ zDate++; cnt++; }while( nextC ); +end_getDigits: va_end(ap); -end_getDigits: return cnt; } ============================================================ --- sqlite/delete.c 56ab34c3a384caa5d5ea06f5739944957e2e4213 +++ sqlite/delete.c ca404d5fd5f678e32f2f46377ad802cd0219aa99 @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.120 2006/01/24 12:09:19 danielk1977 Exp $ +** $Id: delete.c,v 1.121 2006/02/10 02:27:43 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -343,7 +343,7 @@ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC); } delete_from_cleanup: ============================================================ --- sqlite/expr.c 1149c3380bfce27703f5e9bec7dfb8e51baaf9d9 +++ sqlite/expr.c 9c957fabf95ef62288151eecd5c490a629470666 @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.253 2006/01/30 14:36:59 drh Exp $ +** $Id: expr.c,v 1.254 2006/02/10 07:07:15 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -495,6 +495,7 @@ pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; + pNewItem->isPopulated = pOldItem->isPopulated; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; ============================================================ --- sqlite/func.c 96b26601c092b7b43a13e440e3f988b32a385f6a +++ sqlite/func.c 93d004b453a5d9aa754e673eef75d3c9527e0f54 @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.117 2006/01/17 13:21:40 danielk1977 Exp $ +** $Id: func.c,v 1.121 2006/02/09 22:13:42 drh Exp $ */ #include "sqliteInt.h" #include @@ -817,9 +817,9 @@ */ typedef struct SumCtx SumCtx; struct SumCtx { - double sum; /* Sum of terms */ - int cnt; /* Number of elements summed */ - u8 seenFloat; /* True if there has been any floating point value */ + LONGDOUBLE_TYPE sum; /* Sum of terms */ + i64 cnt; /* Number of elements summed */ + u8 approx; /* True if sum is approximate */ }; /* @@ -830,18 +830,33 @@ ** 0.0 in that case. In addition, TOTAL always returns a float where ** SUM might return an integer if it never encounters a floating point ** value. +** +** I am told that SUM() should raise an exception if it encounters +** a integer overflow. But after pondering this, I decided that +** behavior leads to brittle programs. So instead, I have coded +** SUM() to revert to using floating point if it encounters an +** integer overflow. The answer may not be exact, but it will be +** close. If the SUM() function returns an integer, the value is +** exact. If SUM() returns a floating point value, it means the +** value might be approximated. */ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ SumCtx *p; int type; assert( argc==1 ); p = sqlite3_aggregate_context(context, sizeof(*p)); - type = sqlite3_value_type(argv[0]); + type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ - p->sum += sqlite3_value_double(argv[0]); p->cnt++; - if( type==SQLITE_FLOAT ){ - p->seenFloat = 1; + if( type==SQLITE_INTEGER ){ + p->sum += sqlite3_value_int64(argv[0]); + if( !p->approx ){ + i64 iVal; + p->approx = p->sum!=(LONGDOUBLE_TYPE)(iVal = (i64)p->sum); + } + }else{ + p->sum += sqlite3_value_double(argv[0]); + p->approx = 1; } } } @@ -849,7 +864,7 @@ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ - if( p->seenFloat ){ + if( p->approx ){ sqlite3_result_double(context, p->sum); }else{ sqlite3_result_int64(context, (i64)p->sum); @@ -870,23 +885,12 @@ } /* -** An instance of the following structure holds the context of a -** variance or standard deviation computation. -*/ -typedef struct StdDevCtx StdDevCtx; -struct StdDevCtx { - double sum; /* Sum of terms */ - double sum2; /* Sum of the squares of terms */ - int cnt; /* Number of terms counted */ -}; - -/* ** The following structure keeps track of state information for the ** count() aggregate function. */ typedef struct CountCtx CountCtx; struct CountCtx { - int n; + i64 n; }; /* @@ -902,7 +906,7 @@ static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, 0); - sqlite3_result_int(context, p ? p->n : 0); + sqlite3_result_int64(context, p ? p->n : 0); } /* ============================================================ --- sqlite/insert.c 7e931b7f06afbcefcbbaab175c02eff8268db33f +++ sqlite/insert.c 67b3dc11831c58d8703eb502355ad3704ee18f66 @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.160 2006/01/24 12:09:19 danielk1977 Exp $ +** $Id: insert.c,v 1.161 2006/02/10 02:27:43 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -703,7 +703,7 @@ sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC); } insert_cleanup: ============================================================ --- sqlite/main.c 2693776249865dc69b97904205638e84a34a059c +++ sqlite/main.c 9a42464c44a6532003391486e802e65e88789cfc @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.331 2006/01/24 16:37:58 danielk1977 Exp $ +** $Id: main.c,v 1.334 2006/02/09 13:43:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -29,7 +29,6 @@ /* ** The version of the library */ -const char rcsid3[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite3_version[] = SQLITE_VERSION; const char *sqlite3_libversion(void){ return sqlite3_version; } int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } @@ -732,6 +731,10 @@ return db->errCode; } +/* +** Create a new collating function for database "db". The name is zName +** and the encoding is enc. +*/ static int createCollation( sqlite3* db, const char *zName, @@ -817,8 +820,9 @@ ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. */ - if( createCollation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) || - createCollation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) || + if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc) || + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc) || + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc) || (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 ){ assert( sqlite3MallocFailed() ); @@ -1113,3 +1117,117 @@ sqlite3OsThreadSpecificData(-1); } } + +/* +** Return meta information about a specific column of a database table. +** See comment in sqlite3.h (sqlite.h.in) for details. +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if colums is auto-increment */ +){ + int rc; + char *zErrMsg = 0; + Table *pTab = 0; + Column *pCol = 0; + int iCol; + + char const *zDataType = 0; + char const *zCollSeq = 0; + int notnull = 0; + int primarykey = 0; + int autoinc = 0; + + /* Ensure the database schema has been loaded */ + if( sqlite3SafetyOn(db) ){ + return SQLITE_MISUSE; + } + rc = sqlite3Init(db, &zErrMsg); + if( SQLITE_OK!=rc ){ + goto error_out; + } + + /* Locate the table in question */ + pTab = sqlite3FindTable(db, zTableName, zDbName); + if( !pTab || pTab->pSelect ){ + pTab = 0; + goto error_out; + } + + /* Find the column for which info is requested */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } + }else{ + for(iCol=0; iColnCol; iCol++){ + pCol = &pTab->aCol[iCol]; + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ + break; + } + } + if( iCol==pTab->nCol ){ + pTab = 0; + goto error_out; + } + } + + /* The following block stores the meta information that will be returned + ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey + ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. + ** + ** 2. The table is not a view and the column name identified an + ** explicitly declared column. Copy meta information from *pCol. + */ + if( pCol ){ + zDataType = pCol->zType; + zCollSeq = pCol->zColl; + notnull = (pCol->notNull?1:0); + primarykey = (pCol->isPrimKey?1:0); + autoinc = ((pTab->iPKey==iCol && pTab->autoInc)?1:0); + }else{ + zDataType = "INTEGER"; + primarykey = 1; + } + if( !zCollSeq ){ + zCollSeq = "BINARY"; + } + +error_out: + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + /* Whether the function call succeeded or failed, set the output parameters + ** to whatever their local counterparts contain. If an error did occur, + ** this has the effect of zeroing all output parameters. + */ + if( pzDataType ) *pzDataType = zDataType; + if( pzCollSeq ) *pzCollSeq = zCollSeq; + if( pNotNull ) *pNotNull = notnull; + if( pPrimaryKey ) *pPrimaryKey = primarykey; + if( pAutoinc ) *pAutoinc = autoinc; + + if( SQLITE_OK==rc && !pTab ){ + sqlite3SetString(&zErrMsg, "no such table column: ", zTableName, ".", + zColumnName, 0); + rc = SQLITE_ERROR; + } + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqliteFree(zErrMsg); + return sqlite3ApiExit(db, rc); +} +#endif + ============================================================ --- sqlite/os_common.h 061fba8511a656b118551424f64e366ad0d4cb3b +++ sqlite/os_common.h 108cd719c96a2b714b64e02aeabbd40684274e6a @@ -155,7 +155,7 @@ void *sqlite3GenericRealloc(void *p, int n){ char *p2 = ((char *)p - 8); assert(n>0); - p2 = realloc(p2, n+8); + p2 = (char*)realloc(p2, n+8); if( p2 ){ *(int *)p2 = n; p2 += 8; ============================================================ --- sqlite/os_unix.c 73c5e722a661ed98d8919f204911e4e34e51fa41 +++ sqlite/os_unix.c 378a89aaf15d83b901c1b73350e91ddecf743986 @@ -353,14 +353,23 @@ ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. ** +** On some systems, we know at compile-time if threads can override each +** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro +** will be set appropriately. On other systems, we have to check at +** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is +** undefined. +** ** This variable normally has file scope only. But during testing, we make ** it a global so that the test code can change its value in order to verify ** that the right stuff happens in either case. */ +#ifndef SQLITE_THREAD_OVERRIDE_LOCK +# define SQLITE_THREAD_OVERRIDE_LOCK -1 +#endif #ifdef SQLITE_TEST -int threadsOverrideEachOthersLocks = -1; +int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; #else -static int threadsOverrideEachOthersLocks = -1; +static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; #endif /* @@ -972,7 +981,18 @@ # define fdatasync fsync #endif +/* +** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not +** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently +** only available on Mac OS X. But that could change. +*/ +#ifdef F_FULLFSYNC +# define HAVE_FULLFSYNC 1 +#else +# define HAVE_FULLFSYNC 0 +#endif + /* ** The fsync() system call does not work as advertised on many ** unix systems. The following procedure is an attempt to make @@ -1003,7 +1023,7 @@ rc = SQLITE_OK; #else -#ifdef F_FULLFSYNC +#if HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); }else{ @@ -1048,10 +1068,21 @@ return SQLITE_IOERR; } if( pFile->dirfd>=0 ){ - TRACE2("DIRSYNC %-3d\n", pFile->dirfd); + TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + HAVE_FULLFSYNC, pFile->fullSync); #ifndef SQLITE_DISABLE_DIRSYNC - if( full_fsync(pFile->dirfd, pFile->fullSync, 0) ){ - return SQLITE_IOERR; + /* The directory sync is only attempted if full_fsync is + ** turned off or unavailable. If a full_fsync occurred above, + ** then the directory sync is superfluous. + */ + if( (!HAVE_FULLFSYNC || !pFile->fullSync) && full_fsync(pFile->dirfd,0,0) ){ + /* + ** We have received multiple reports of fsync() returning + ** errors when applied to directories on certain file systems. + ** A failed directory sync is not a big deal. So it seems + ** better to ignore the error. Ticket #1657 + */ + /* return SQLITE_IOERR; */ } #endif close(pFile->dirfd); /* Only need to sync once, so close the directory */ @@ -1656,13 +1687,42 @@ } /* -** Static variables used for thread synchronization +** Static variables used for thread synchronization. +** +** inMutex the nesting depth of the recursive mutex. The thread +** holding mutexMain can read this variable at any time. +** But is must hold mutexAux to change this variable. Other +** threads must hold mutexAux to read the variable and can +** never write. +** +** mutexOwner The thread id of the thread holding mutexMain. Same +** access rules as for inMutex. +** +** mutexOwnerValid True if the value in mutexOwner is valid. The same +** access rules apply as for inMutex. +** +** mutexMain The main mutex. Hold this mutex in order to get exclusive +** access to SQLite data structures. +** +** mutexAux An auxiliary mutex needed to access variables defined above. +** +** Mutexes are always acquired in this order: mutexMain mutexAux. It +** is not necessary to acquire mutexMain in order to get mutexAux - just +** do not attempt to acquire them in the reverse order: mutexAux mutexMain. +** Either get the mutexes with mutexMain first or get mutexAux only. +** +** When running on a platform where the three variables inMutex, mutexOwner, +** and mutexOwnerValid can be set atomically, the mutexAux is not required. +** On many systems, all three are 32-bit integers and writing to a 32-bit +** integer is atomic. I think. But there are no guarantees. So it seems +** safer to protect them using mutexAux. */ static int inMutex = 0; #ifdef SQLITE_UNIX_THREADS -static pthread_t mutexOwner; -static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; +static pthread_t mutexOwner; /* Thread holding mutexMain */ +static int mutexOwnerValid = 0; /* True if mutexOwner is valid */ +static pthread_mutex_t mutexMain = PTHREAD_MUTEX_INITIALIZER; /* The mutex */ +static pthread_mutex_t mutexAux = PTHREAD_MUTEX_INITIALIZER; /* Aux mutex */ #endif /* @@ -1677,25 +1737,34 @@ */ void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutex1); - if( inMutex==0 ){ - pthread_mutex_lock(&mutex2); + pthread_mutex_lock(&mutexAux); + if( !mutexOwnerValid || !pthread_equal(mutexOwner, pthread_self()) ){ + pthread_mutex_unlock(&mutexAux); + pthread_mutex_lock(&mutexMain); + assert( inMutex==0 ); + assert( !mutexOwnerValid ); + pthread_mutex_lock(&mutexAux); mutexOwner = pthread_self(); + mutexOwnerValid = 1; } - pthread_mutex_unlock(&mutex1); -#endif inMutex++; + pthread_mutex_unlock(&mutexAux); +#else + inMutex++; +#endif } void sqlite3UnixLeaveMutex(){ assert( inMutex>0 ); #ifdef SQLITE_UNIX_THREADS - assert( pthread_equal(mutexOwner, pthread_self()) ); - pthread_mutex_lock(&mutex1); + pthread_mutex_lock(&mutexAux); inMutex--; + assert( pthread_equal(mutexOwner, pthread_self()) ); if( inMutex==0 ){ - pthread_mutex_unlock(&mutex2); + assert( mutexOwnerValid ); + mutexOwnerValid = 0; + pthread_mutex_unlock(&mutexMain); } - pthread_mutex_unlock(&mutex1); + pthread_mutex_unlock(&mutexAux); #else inMutex--; #endif @@ -1704,14 +1773,17 @@ /* ** Return TRUE if the mutex is currently held. ** -** If the thisThreadOnly parameter is true, return true only if the +** If the thisThrd parameter is true, return true only if the ** calling thread holds the mutex. If the parameter is false, return ** true if any thread holds the mutex. */ -int sqlite3UnixInMutex(int thisThreadOnly){ +int sqlite3UnixInMutex(int thisThrd){ #ifdef SQLITE_UNIX_THREADS - return inMutex>0 && - (thisThreadOnly==0 || pthread_equal(mutexOwner, pthread_self())); + int rc; + pthread_mutex_lock(&mutexAux); + rc = inMutex>0 && (thisThrd==0 || pthread_equal(mutexOwner,pthread_self())); + pthread_mutex_unlock(&mutexAux); + return rc; #else return inMutex>0; #endif ============================================================ --- sqlite/os_win.c 566bf7b41b72556fd7dca390bceaa2769dc395e9 +++ sqlite/os_win.c c67a2c46d929cf54c8f80ec5e6079cf684a141a9 @@ -1479,7 +1479,7 @@ ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ static int key; static int keyInit = 0; - static const ThreadData zeroData; + static const ThreadData zeroData = {0}; ThreadData *pTsd; if( !keyInit ){ ============================================================ --- sqlite/pager.c b5b380ea7a36f84e50c3adc1a414820a0eb3baa6 +++ sqlite/pager.c c438aa5fc248e0523e80591eeae33a3993c47278 @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.257 2006/01/30 22:48:44 drh Exp $ +** @(#) $Id: pager.c,v 1.258 2006/02/11 01:25:51 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -244,6 +244,7 @@ u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 full_fsync; /* Use F_FULLFSYNC when available */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ u8 errCode; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ @@ -1509,9 +1510,10 @@ ** and FULL=3. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -void sqlite3pager_set_safety_level(Pager *pPager, int level){ +void sqlite3pager_set_safety_level(Pager *pPager, int level, int full_fsync){ pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; + pPager->full_fsync = full_fsync; if( pPager->noSync ) pPager->needSync = 0; } #endif @@ -2204,7 +2206,7 @@ if( rc ) return rc; } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3OsSync(pPager->jfd, pPager->fullSync); + rc = sqlite3OsSync(pPager->jfd, pPager->full_fsync); if( rc!=0 ) return rc; pPager->journalStarted = 1; } @@ -2832,8 +2834,8 @@ if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } - sqlite3OsSetFullSync(pPager->jfd, pPager->fullSync); - sqlite3OsSetFullSync(pPager->fd, pPager->fullSync); + sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync); + sqlite3OsSetFullSync(pPager->fd, pPager->full_fsync); sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; ============================================================ --- sqlite/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f +++ sqlite/pager.h 425a9e52d5404158de016799715cbc2c3d685178 @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.48 2005/12/19 14:18:11 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.49 2006/02/11 01:25:51 drh Exp $ */ #ifndef _PAGER_H_ @@ -99,7 +99,7 @@ void sqlite3pager_dont_rollback(void*); void sqlite3pager_dont_write(Pager*, Pgno); int *sqlite3pager_stats(Pager*); -void sqlite3pager_set_safety_level(Pager*,int); +void sqlite3pager_set_safety_level(Pager*,int,int); const char *sqlite3pager_filename(Pager*); const char *sqlite3pager_dirname(Pager*); const char *sqlite3pager_journalname(Pager*); ============================================================ --- sqlite/parse.h 20eb1ccb1fa5d4e4493dd0ca916ad74b515eefcf +++ sqlite/parse.h ae4ee794251454f9c8b4c97ef7fee85deecdcec5 @@ -149,3 +149,18 @@ #define TK_AGG_FUNCTION 149 #define TK_AGG_COLUMN 150 #define TK_CONST_FUNC 151 +#define TK_TO_TEXT 152 +#define TK_TO_BLOB 153 +#define TK_TO_NUMERIC 154 +#define TK_TO_INT 155 +#define TK_TO_REAL 156 +#define TK_END_OF_FILE 157 +#define TK_ILLEGAL 158 +#define TK_SPACE 159 +#define TK_UNCLOSED_STRING 160 +#define TK_COMMENT 161 +#define TK_FUNCTION 162 +#define TK_COLUMN 163 +#define TK_AGG_FUNCTION 164 +#define TK_AGG_COLUMN 165 +#define TK_CONST_FUNC 166 ============================================================ --- sqlite/pragma.c 4496cc77dc35824e1c978c3d1413b8a5a4c777d3 +++ sqlite/pragma.c 31d3e1b74cab2172807894e70c674d6a577501fd @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.114 2006/01/12 01:56:44 drh Exp $ +** $Id: pragma.c,v 1.118 2006/02/11 01:25:51 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -128,7 +128,7 @@ sqlite3VdbeAddOp(v, OP_Integer, value, 0); if( pParse->explain==0 ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC); } sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } @@ -152,6 +152,7 @@ { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, { "legacy_file_format", SQLITE_LegacyFileFmt }, + { "fullfsync", SQLITE_FullFSync }, #ifndef SQLITE_OMIT_CHECK { "ignore_check_constraints", SQLITE_IgnoreChecks }, #endif @@ -180,10 +181,6 @@ db->flags &= ~p->mask; } } - /* If one of these pragmas is executed, any prepared statements - ** need to be recompiled. - */ - sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } return 1; } @@ -274,7 +271,7 @@ if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES); @@ -392,7 +389,8 @@ if( !zRight ){ if( sqlite3_temp_directory ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "temp_store_directory", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", P3_STATIC); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); } @@ -436,7 +434,6 @@ "Safety level may not be changed inside a transaction"); }else{ pDb->safety_level = getSafetyLevel(zRight)+1; - sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); } } }else @@ -468,22 +465,23 @@ pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ int i; + Column *pCol; sqlite3VdbeSetNumCols(v, 6); - sqlite3VdbeSetColName(v, 0, "cid", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "type", P3_STATIC); - sqlite3VdbeSetColName(v, 3, "notnull", P3_STATIC); - sqlite3VdbeSetColName(v, 4, "dflt_value", P3_STATIC); - sqlite3VdbeSetColName(v, 5, "pk", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P3_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); - for(i=0; inCol; i++){ + for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zName, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, - pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0); - sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0); - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); - sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0); + pCol->zType ? pCol->zType : "numeric", 0); + sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0); + sqlite3ExprCode(pParse, pCol->pDflt); + sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0); sqlite3VdbeAddOp(v, OP_Callback, 6, 0); } } @@ -498,9 +496,9 @@ int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seqno", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "cid", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P3_STATIC); for(i=0; inColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp(v, OP_Integer, i, 0); @@ -523,9 +521,9 @@ if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "unique", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P3_STATIC); while(pIdx){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0); @@ -542,9 +540,9 @@ int i; if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "file", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P3_STATIC); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); @@ -560,8 +558,8 @@ int i = 0; HashElem *p; sqlite3VdbeSetNumCols(v, 2); - sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeAddOp(v, OP_Integer, i++, 0); @@ -583,11 +581,11 @@ if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 5); - sqlite3VdbeSetColName(v, 0, "id", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); - sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); - sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); - sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P3_STATIC); while(pFK){ int j; for(j=0; jnCol; j++){ @@ -649,7 +647,7 @@ /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC); sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */ /* Do an integrity check on each database file */ @@ -794,7 +792,7 @@ if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( pEnc->enc==ENC(pParse->db) ){ @@ -900,8 +898,8 @@ int i; Vdbe *v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 2); - sqlite3VdbeSetColName(v, 0, "database", P3_STATIC); - sqlite3VdbeSetColName(v, 1, "status", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P3_STATIC); for(i=0; inDb; i++){ Btree *pBt; Pager *pPager; @@ -945,6 +943,15 @@ ** are only valid for a single execution. */ sqlite3VdbeAddOp(v, OP_Expire, 1, 0); + + /* + ** Reset the safety level, in case the fullfsync flag or synchronous + ** setting changed. + */ + if( db->autoCommit ){ + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, + (db->flags&SQLITE_FullFSync)!=0); + } } pragma_out: sqliteFree(zLeft); ============================================================ --- sqlite/prepare.c 40ae23c8aeb641dc7b9bb271eb5e295b815154a7 +++ sqlite/prepare.c cf0fc8ebaf94409955ecb09ffeb0099c9ef44693 @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.30 2006/01/30 22:35:44 drh Exp $ +** $Id: prepare.c,v 1.31 2006/02/10 02:27:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -556,16 +556,16 @@ if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ if( sParse.explain==2 ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 3); - sqlite3VdbeSetColName(sParse.pVdbe, 0, "order", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, "from", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, "detail", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P3_STATIC); }else{ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); - sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC); } } #endif ============================================================ --- sqlite/select.c daee9b20702ba51cf3807fc1b130edd8846e3e48 +++ sqlite/select.c 7d069e875d0eec05129c7e8b9c99422d7c9c6321 @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.301 2006/01/24 12:09:19 danielk1977 Exp $ +** $Id: select.c,v 1.304 2006/02/10 07:07:16 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -762,14 +762,31 @@ ** Return a pointer to a string containing the 'declaration type' of the ** expression pExpr. The string may be treated as static by the caller. ** -** If the declaration type is the exact datatype definition extracted from -** the original CREATE TABLE statement if the expression is a column. +** The declaration type is the exact datatype definition extracted from the +** original CREATE TABLE statement if the expression is a column. The +** declaration type for a ROWID field is INTEGER. Exactly when an expression +** is considered a column can be complex in the presence of subqueries. The +** result-set expression in all of the following SELECT statements is +** considered a column by this function. +** +** SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl); +** SELECT abc FROM (SELECT col AS abc FROM tbl); ** -** The declaration type for an expression is either TEXT, NUMERIC or ANY. -** The declaration type for a ROWID field is INTEGER. +** The declaration type for any expression other than a column is NULL. */ -static const char *columnType(NameContext *pNC, Expr *pExpr){ - char const *zType; +static const char *columnType( + NameContext *pNC, + Expr *pExpr, + const char **pzOriginDb, + const char **pzOriginTab, + const char **pzOriginCol +){ + char const *zType = 0; + char const *zOriginDb = 0; + char const *zOriginTab = 0; + char const *zOriginCol = 0; int j; if( pExpr==0 || pNC->pSrcList==0 ) return 0; @@ -781,17 +798,24 @@ switch( pExpr->op ){ case TK_COLUMN: { - Table *pTab = 0; - int iCol = pExpr->iColumn; + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real + ** database table or a subquery. + */ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( jnSrc ){ pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; }else{ pNC = pNC->pNext; } } + if( pTab==0 ){ /* FIX ME: ** This can occurs if you have something like "SELECT new.x;" inside @@ -806,30 +830,72 @@ zType = "TEXT"; break; } + assert( pTab ); - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - }else{ - zType = pTab->aCol[iCol].zType; +#ifndef SQLITE_OMIT_SUBQUERY + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin + ** data for the result-set column of the sub-select. + */ + if( iCol>=0 && iColpEList->nExpr ){ + /* If iCol is less than zero, then the expression requests the + ** rowid of the sub-select or view. This expression is legal (see + ** test case misc2.2.2) - it always evaluates to NULL. + */ + NameContext sNC; + Expr *p = pS->pEList->a[iCol].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = 0; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + } + }else +#endif + if( pTab->pSchema ){ + /* A real table */ + assert( !pS ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOriginCol = "rowid"; + }else{ + zType = pTab->aCol[iCol].zType; + zOriginCol = pTab->aCol[iCol].zName; + } + zOriginTab = pTab->zName; + if( pNC->pParse ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOriginDb = pNC->pParse->db->aDb[iDb].zName; + } } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: { + /* The expression is a sub-select. Return the declaration type and + ** origin info for the single column in the result set of the SELECT + ** statement. + */ NameContext sNC; Select *pS = pExpr->pSelect; - sNC.pSrcList = pExpr->pSelect->pSrc; + Expr *p = pS->pEList->a[0].pExpr; + sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; - zType = columnType(&sNC, pS->pEList->a[0].pExpr); + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); break; } #endif - default: - zType = 0; } + if( pzOriginDb ){ + assert( pzOriginTab && pzOriginCol ); + *pzOriginDb = zOriginDb; + *pzOriginTab = zOriginTab; + *pzOriginCol = zOriginCol; + } return zType; } @@ -846,14 +912,22 @@ int i; NameContext sNC; sNC.pSrcList = pTabList; + sNC.pParse = pParse; for(i=0; inExpr; i++){ Expr *p = pEList->a[i].pExpr; - const char *zType = columnType(&sNC, p); - if( zType==0 ) continue; - /* The vdbe must make it's own copy of the column-type, in case the - ** schema is reset before this virtual machine is deleted. + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; + const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make it's own copy of the column-type and other + ** column specific strings, in case the schema is reset before this + ** virtual machine is deleted. */ - sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType)); + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT); } } @@ -891,7 +965,7 @@ if( p==0 ) continue; if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; - sqlite3VdbeSetColName(v, i, zName, strlen(zName)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); continue; } if( p->op==TK_COLUMN && pTabList ){ @@ -909,7 +983,7 @@ zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; @@ -917,18 +991,18 @@ zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ) zTab = pTab->zName; sqlite3SetString(&zName, zTab, ".", zCol, (char*)0); - sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC); }else{ - sqlite3VdbeSetColName(v, i, zCol, strlen(zCol)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); } }else if( p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; assert( p->op!=TK_COLUMN || pTabList==0 ); sprintf(zName, "column%d", i+1); - sqlite3VdbeSetColName(v, i, zName, 0); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0); } } generateColumnTypes(pParse, pTabList, pEList); @@ -1036,7 +1110,7 @@ */ memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; - zType = sqliteStrDup(columnType(&sNC, p)); + zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); pColl = sqlite3ExprCollSeq(pParse, p); @@ -2783,13 +2857,6 @@ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; - /* Identify column names if we will be using them in a callback. This - ** step is skipped if the output is going to some other destination. - */ - if( eDest==SRT_Callback ){ - generateColumnNames(pParse, pTabList, pEList); - } - /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) @@ -2798,7 +2865,7 @@ int needRestoreContext; struct SrcList_item *pItem = &pTabList->a[i]; - if( pItem->pSelect==0 ) continue; + if( pItem->pSelect==0 || pItem->isPopulated ) continue; if( pItem->zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; @@ -3192,15 +3259,14 @@ #ifndef SQLITE_OMIT_SUBQUERY /* If this was a subquery, we have now converted the subquery into a - ** temporary table. So delete the subquery structure from the parent - ** to prevent this subquery from being evaluated again and to force the - ** the use of the temporary table. + ** temporary table. So set the SrcList_item.isPopulated flag to prevent + ** this subquery from being evaluated again and to force the use of + ** the temporary table. */ if( pParent ){ assert( pParent->pSrc->nSrc>parentTab ); assert( pParent->pSrc->a[parentTab].pSelect==p ); - sqlite3SelectDelete(p); - pParent->pSrc->a[parentTab].pSelect = 0; + pParent->pSrc->a[parentTab].isPopulated = 1; } #endif @@ -3217,6 +3283,14 @@ ** successful coding of the SELECT. */ select_end: + + /* Identify column names if we will be using them in a callback. This + ** step is skipped if the output is going to some other destination. + */ + if( rc==SQLITE_OK && eDest==SRT_Callback ){ + generateColumnNames(pParse, pTabList, pEList); + } + sqliteFree(sAggInfo.aCol); sqliteFree(sAggInfo.aFunc); return rc; ============================================================ --- sqlite/sqlite3.h 6b9ed927e0a9a3c6051a372929c97c2ac87ab314 +++ sqlite/sqlite3.h d0605a62334179d9c38bf587ac38b777d6daee2b @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.156 2006/01/12 02:50:10 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.162 2006/02/10 03:06:10 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -31,7 +31,7 @@ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif -#define SQLITE_VERSION "3.3.3" +#define SQLITE_VERSION "3.3.4" /* ** The format of the version string is "X.Y.Z", where @@ -48,7 +48,7 @@ #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif -#define SQLITE_VERSION_NUMBER 3003003 +#define SQLITE_VERSION_NUMBER 3003004 /* ** The version string is also compiled into the library so that a program @@ -164,6 +164,7 @@ ** Return values for sqlite3_exec() and sqlite3_step() */ #define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ @@ -192,7 +193,7 @@ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-return-codes */ +/* end-of-error-codes */ /* ** Each entry in an SQLite table has a unique integer key. (The key is @@ -725,6 +726,30 @@ const void *sqlite3_column_name16(sqlite3_stmt*,int); /* +** The first parameter to the following calls is a compiled SQL statement. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is not a column value, +** then all of the functions return NULL. Otherwise, the return the +** name of the attached database, table and column that the expression +** extracts a value from. +** +** As with all other SQLite APIs, those postfixed with "16" return UTF-16 +** encoded strings, the other functions return UTF-8. The memory containing +** the returned strings is valid until the statement handle is finalized(). +** +** These APIs are only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt*,int); +const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +const char *sqlite3_column_table_name(sqlite3_stmt*,int); +const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* ** The first parameter is a compiled SQL statement. If this statement ** is a SELECT statement, the Nth column of the returned result set ** of the SELECT is a table column then the declared type of the table @@ -736,7 +761,7 @@ ** ** And the following statement compiled: ** -** SELECT c1 + 1, 0 FROM t1; +** SELECT c1 + 1, c1 FROM t1; ** ** Then this routine would return the string "VARIANT" for the second ** result column (i==1), and a NULL pointer for the first result column @@ -756,7 +781,7 @@ ** ** And the following statement compiled: ** -** SELECT c1 + 1, 0 FROM t1; +** SELECT c1 + 1, c1 FROM t1; ** ** Then this routine would return the string "INTEGER" for the second ** result column (i==1), and a NULL pointer for the first result column @@ -897,6 +922,7 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); int sqlite3_column_type(sqlite3_stmt*, int iCol); +int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol); /* ** The sqlite3_finalize() function is called to delete a compiled @@ -980,9 +1006,8 @@ ); /* -** The next routine returns the number of calls to xStep for a particular -** aggregate function instance. The current call to xStep counts so this -** routine always returns at least 1. +** This function is deprecated. Do not use it. It continues to exist +** so as not to break legacy code. But new code should avoid using it. */ int sqlite3_aggregate_count(sqlite3_context*); @@ -1005,6 +1030,7 @@ const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); /* ** Aggregate functions use the following routine to allocate @@ -1370,6 +1396,75 @@ void sqlite3_thread_cleanup(void); /* +** Return meta information about a specific column of a specific database +** table accessible using the connection handle passed as the first function +** argument. +** +** The column is identified by the second, third and fourth parameters to +** this function. The second parameter is either the name of the database +** (i.e. "main", "temp" or an attached database) containing the specified +** table or NULL. If it is NULL, then all attached databases are searched +** for the table using the same algorithm as the database engine uses to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Meta information is returned by writing to the memory locations passed as +** the 5th and subsequent parameters to this function. Any of these +** arguments may be NULL, in which case the corresponding element of meta +** information is ommitted. +** +** Parameter Output Type Description +** ----------------------------------- +** +** 5th const char* Data type +** 6th const char* Name of the default collation sequence +** 7th int True if the column has a NOT NULL constraint +** 8th int True if the column is part of the PRIMARY KEY +** 9th int True if the column is AUTOINCREMENT +** +** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any sqlite API function. +** +** If the specified table is actually a view, then an error is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" and an +** INTEGER PRIMARY KEY column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. If there is no +** explicitly declared IPK column, then the output parameters are set as +** follows: +** +** data type: "INTEGER" +** collation sequence: "BINARY" +** not null: 0 +** primary key: 1 +** auto increment: 0 +** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an SQLITE error code is returned and an error message +** left in the database handle (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if colums is auto-increment */ +); + +/* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ ============================================================ --- sqlite/sqliteInt.h 0121298397ac14eb468ab1ba9d488ac7ed7d88a1 +++ sqlite/sqliteInt.h f61b60f243f1709c943c62cfb6d7a50209080e38 @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.479 2006/01/24 16:37:58 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.481 2006/02/11 01:25:51 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -544,6 +544,7 @@ #define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ /* ** Possible values for the sqlite.magic field. @@ -1069,6 +1070,7 @@ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ 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 table and the next */ i16 iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ ============================================================ --- sqlite/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 +++ sqlite/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e @@ -145,6 +145,7 @@ res.azResult[0] = 0; rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); if( res.azResult ){ + assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); res.azResult[0] = (char*)res.nData; } if( rc==SQLITE_ABORT ){ ============================================================ --- sqlite/tokenize.c 9ae9a59238eb97fbc61baea280563b91100518fb +++ sqlite/tokenize.c 382b3bb0ca26eb9153b5d20b246ef512a114a24f @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.116 2006/01/20 17:56:33 drh Exp $ +** $Id: tokenize.c,v 1.117 2006/02/09 22:24:41 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -261,6 +261,7 @@ #ifndef SQLITE_OMIT_TCL_VARIABLE case '$': #endif + case '@': /* For compatibility with MS SQL Server */ case ':': { int n = 0; *tokenType = TK_VARIABLE; ============================================================ --- sqlite/update.c 14be4ba2f438919b4217085c02feff569e6cf1f2 +++ sqlite/update.c 050a7e0ddaac03dec5271712eee62f1a9e699049 @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.121 2006/01/18 16:51:36 danielk1977 Exp $ +** $Id: update.c,v 1.122 2006/02/10 02:27:43 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -494,7 +494,7 @@ if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){ sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC); } update_cleanup: ============================================================ --- sqlite/util.c 82ee598519b8193184bdeab06b51a4ffa05ad60b +++ sqlite/util.c 405f46fef062b476826d2c171ec21def29563b75 @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.182 2006/01/23 15:39:59 drh Exp $ +** $Id: util.c,v 1.184 2006/02/06 21:22:31 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -521,34 +521,56 @@ **--------------------------------------------------------------------------*/ /* -** The handleSoftLimit() function is called before each call to -** sqlite3OsMalloc() or xRealloc(). The parameter 'n' is the number of -** extra bytes about to be allocated (for Realloc() this means the size of the -** new allocation less the size of the old allocation). If the extra allocation -** means that the total memory allocated to SQLite in this thread would exceed -** the limit set by sqlite3_soft_heap_limit(), then sqlite3_release_memory() is -** called to try to avoid this. No indication of whether or not this is -** successful is returned to the caller. +** This routine is called when we are about to allocate n additional bytes +** of memory. If the new allocation will put is over the soft allocation +** limit, then invoke sqlite3_release_memory() to try to release some +** memory before continuing with the allocation. ** +** This routine also makes sure that the thread-specific-data (TSD) has +** be allocated. If it has not and can not be allocated, then return +** false. The updateMemoryUsedCount() routine below will deallocate +** the TSD if it ought to be. +** ** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is ** a no-op +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static int enforceSoftLimit(int n){ + ThreadData *pTsd = sqlite3ThreadData(); + if( pTsd==0 ){ + return 0; + } + assert( pTsd->nAlloc>=0 ); + if( n>0 && pTsd->nSoftHeapLimit>0 ){ + while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ); + } + return 1; +} +#else +# define enforceSoftLimit(X) 1 +#endif + +/* +** Update the count of total outstanding memory that is held in +** thread-specific-data (TSD). If after this update the TSD is +** no longer being used, then deallocate it. +** +** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is +** a no-op */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -static int handleSoftLimit(int n){ +static void updateMemoryUsedCount(int n){ ThreadData *pTsd = sqlite3ThreadData(); if( pTsd ){ pTsd->nAlloc += n; assert( pTsd->nAlloc>=0 ); - if( n>0 && pTsd->nSoftHeapLimit>0 ){ - while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ); - }else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ + if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ sqlite3ReleaseThreadData(); } } - return (pTsd ? 0 : 1); } #else -#define handleSoftLimit(x) 0 +#define updateMemoryUsedCount(x) /* no-op */ #endif /* @@ -558,17 +580,13 @@ */ void *sqlite3MallocRaw(int n){ void *p = 0; - if( n>0 && !sqlite3MallocFailed() && !handleSoftLimit(n) ){ + if( n>0 && !sqlite3MallocFailed() && enforceSoftLimit(n) ){ while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ); if( !p ){ - /* If the allocation failed, call handleSoftLimit() again, this time - ** with the additive inverse of the argument passed to - ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is - ** still correct after a malloc() failure. - */ - (void)handleSoftLimit(n * -1); sqlite3FailedMalloc(); OSMALLOC_FAILED(); + }else{ + updateMemoryUsedCount(OSSIZEOF(p)); } } return p; @@ -588,17 +606,16 @@ return sqlite3Malloc(n); }else{ void *np = 0; - if( !handleSoftLimit(n - OSSIZEOF(p)) ){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int origSize = OSSIZEOF(p); +#endif + if( enforceSoftLimit(n - origSize) ){ while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ); if( !np ){ - /* If the allocation failed, call handleSoftLimit() again, this time - ** with the additive inverse of the argument passed to - ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is - ** still correct after a malloc() failure. - */ - (void)handleSoftLimit(OSSIZEOF(p) - n); sqlite3FailedMalloc(); OSMALLOC_FAILED(); + }else{ + updateMemoryUsedCount(OSSIZEOF(np) - origSize); } } return np; @@ -610,8 +627,8 @@ ** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc(). */ void sqlite3FreeX(void *p){ - (void)handleSoftLimit(0 - OSSIZEOF(p)); if( p ){ + updateMemoryUsedCount(0 - OSSIZEOF(p)); OSFREE(p); } } ============================================================ --- sqlite/vdbe.c fee677e05236e483d6c75d1d4229955fc1b89193 +++ sqlite/vdbe.c 0a7fd81609429bae2b3c326687b02a60a9c01c49 @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.540 2006/01/30 15:34:23 drh Exp $ +** $Id: vdbe.c,v 1.543 2006/02/10 14:02:07 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -190,6 +190,31 @@ } /* +** Try to convert a value into a numeric representation if we can +** do so without loss of information. In other words, if the string +** looks like a number, convert it into a number. If it does not +** look like a number, leave it alone. +*/ +static void applyNumericAffinity(Mem *pRec){ + if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ + int realnum; + sqlite3VdbeMemNulTerminate(pRec); + if( (pRec->flags&MEM_Str) + && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){ + i64 value; + sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); + if( !realnum && sqlite3atoi64(pRec->z, &value) ){ + sqlite3VdbeMemRelease(pRec); + pRec->i = value; + pRec->flags = MEM_Int; + }else{ + sqlite3VdbeMemRealify(pRec); + } + } + } +} + +/* ** Processing is determine by the affinity parameter: ** ** SQLITE_AFF_INTEGER: @@ -220,32 +245,29 @@ }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){ - /* pRec does not have a valid integer or real representation. - ** Attempt a conversion if pRec has a string representation and - ** it looks like a number. - */ - int realnum; - sqlite3VdbeMemNulTerminate(pRec); - if( (pRec->flags&MEM_Str) - && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){ - i64 value; - sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); - if( !realnum && sqlite3atoi64(pRec->z, &value) ){ - sqlite3VdbeMemRelease(pRec); - pRec->i = value; - pRec->flags = MEM_Int; - }else{ - sqlite3VdbeMemNumerify(pRec); - } - } - }else if( pRec->flags & MEM_Real ){ + applyNumericAffinity(pRec); + if( pRec->flags & MEM_Real ){ sqlite3VdbeIntegerAffinity(pRec); } } } /* +** Try to convert the type of a function argument or a result column +** into a numeric representation. Use either INTEGER or REAL whichever +** is appropriate. But only do the conversion if it is possible without +** loss of information and return the revised type of the argument. +** +** This is an EXPERIMENTAL api and is subject to change or removal. +*/ +int sqlite3_value_numeric_type(sqlite3_value *pVal){ + Mem *pMem = (Mem*)pVal; + applyNumericAffinity(pMem); + storeTypeInfo(pMem, 0); + return pMem->type; +} + +/* ** Exported version of applyAffinity(). This one works on sqlite3_value*, ** not the internal Mem* type. */ @@ -1965,6 +1987,7 @@ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ u32 offset; /* Offset into the data */ + int szHdrSz; /* Size of the header size field at start of record */ int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; @@ -1997,7 +2020,8 @@ pC->aRow = 0; } } - zIdx = (u8 *)GetVarint((u8*)zData, offset); + assert( zRec!=0 || avail>=payloadSize || avail>=9 ); + szHdrSz = GetVarint((u8*)zData, offset); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete @@ -2012,8 +2036,8 @@ } zData = sMem.z; } - zEndHdr = (u8 *)zData + offset; - zIdx = (u8 *)zData + (int)zIdx; + zEndHdr = (u8 *)&zData[offset]; + zIdx = (u8 *)&zData[szHdrSz]; /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th @@ -3815,7 +3839,7 @@ assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pC = p->apCsr[i])->pCursor!=0 ){ - int res, rc; + int res; assert( pTos->flags & MEM_Blob ); /* Created using OP_Make*Key */ Stringify(pTos, encoding); ============================================================ --- sqlite/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 +++ sqlite/vdbe.h 80ba1c391ec28180dd07a630577f50b22c2062da @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.99 2005/09/20 17:42:23 drh Exp $ +** $Id: vdbe.h,v 1.101 2006/02/10 03:06:10 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -69,6 +69,7 @@ #define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */ #define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */ #define P3_MEM (-8) /* P3 is a pointer to a Mem* structure */ +#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */ /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the @@ -80,6 +81,17 @@ #define P3_KEYINFO_HANDOFF (-9) /* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ + +/* ** The following macro converts a relative address in the p2 field ** of a VdbeOp structure into a negative number so that ** sqlite3VdbeAddOpList() knows that the address is relative. Calling @@ -117,7 +129,7 @@ int sqlite3VdbeReset(Vdbe*); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); -int sqlite3VdbeSetColName(Vdbe*, int, const char *, int); +int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int); void sqlite3VdbeCountChanges(Vdbe*); sqlite3 *sqlite3VdbeDb(Vdbe*); ============================================================ --- sqlite/vdbeapi.c dcb2636f49b4807e34960d52a2fc257b3a751140 +++ sqlite/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf @@ -74,6 +74,7 @@ int sqlite3_value_type(sqlite3_value* pVal){ return pVal->type; } +/* sqlite3_value_numeric_type() defined in vdbe.c */ /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify @@ -335,9 +336,10 @@ ** Return the number of times the Step function of a aggregate has been ** called. ** -** This routine is defined here in vdbe.c because it depends on knowing -** the internals of the sqlite3_context structure which is only defined in -** this source file. +** This function is deprecated. Do not use it for new code. It is +** provide only to avoid breaking legacy code. New aggregate function +** implementations should keep their own counts within their aggregate +** context. */ int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pFunc && p->pFunc->xStep ); @@ -468,6 +470,13 @@ return sqlite3_value_type( columnMem(pStmt,i) ); } +/* The following function is experimental and subject to change or +** removal */ +/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){ +** return sqlite3_value_numeric_type( columnMem(pStmt,i) ); +**} +*/ + /* ** Convert the N-th element of pStmt->pColName[] into a string using ** xFunc() then return that string. If N is out of range, return 0. @@ -512,11 +521,13 @@ ** statement pStmt. */ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); } #endif @@ -525,26 +536,30 @@ ** of the result set of SQL statement pStmt. */ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } #endif /* SQLITE_OMIT_UTF16 */ -#if !defined(SQLITE_OMIT_ORIGIN_NAMES) && 0 +#ifdef SQLITE_ENABLE_COLUMN_METADATA /* ** Return the name of the database from which a result column derives. ** NULL is returned if the result column is an expression or constant or ** anything else which is not an unabiguous reference to a database column. */ const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 2); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 2); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -554,11 +569,13 @@ ** anything else which is not an unabiguous reference to a database column. */ const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 3); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 3); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -568,18 +585,18 @@ ** anything else which is not an unabiguous reference to a database column. */ const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 4); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ - return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 4); + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); } #endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_OMIT_ORIGIN_NAMES */ +#endif /* SQLITE_ENABLE_COLUMN_METADATA */ - - /******************************* sqlite3_bind_ *************************** ** ** Routines used to attach values to wildcards in a compiled SQL statement. ============================================================ --- sqlite/vdbeaux.c 9bf50cdb6a6c40b8c06ca9a8d87cf90120a16797 +++ sqlite/vdbeaux.c 95f4ed0bc8ed45f16823d84504310495b5dc587d @@ -871,9 +871,9 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ Mem *pColName; int n; - releaseMemArray(p->aColName, p->nResColumn*2); + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqliteFree(p->aColName); - n = nResColumn*2; + n = nResColumn*COLNAME_N; p->nResColumn = nResColumn; p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n ); if( p->aColName==0 ) return; @@ -893,13 +893,14 @@ ** the string is freed using sqliteFree() when the vdbe is finished with ** it. Otherwise, N bytes of zName are copied. */ -int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ +int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){ int rc; Mem *pColName; - assert( idx<(2*p->nResColumn) ); + assert( idxnResColumn ); + assert( varaColName!=0 ); - pColName = &(p->aColName[idx]); + pColName = &(p->aColName[idx+var*p->nResColumn]); if( N==P3_DYNAMIC || N==P3_STATIC ){ rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); }else{ @@ -1481,7 +1482,7 @@ releaseMemArray(p->aVar, p->nVar); sqliteFree(p->aLabel); sqliteFree(p->aStack); - releaseMemArray(p->aColName, p->nResColumn*2); + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqliteFree(p->aColName); p->magic = VDBE_MAGIC_DEAD; sqliteFree(p); ============================================================ --- sqlite/where.c 8409e00fa2cb5fce873b4c911165cfed097e9c49 +++ sqlite/where.c c7d71d5e55c9c4c1e948089280fb0dec7c7d1ef6 @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.203 2006/01/24 12:09:20 danielk1977 Exp $ +** $Id: where.c,v 1.204 2006/02/01 02:45:02 drh Exp $ */ #include "sqliteInt.h" @@ -1500,9 +1500,16 @@ double lowestCost; /* Cost of the pBest */ int bestJ = 0; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ + int once = 0; /* True when first table is seen */ lowestCost = SQLITE_BIG_DBL; for(j=iFrom, pTabItem=&pTabList->a[j]; jnSrc; j++, pTabItem++){ + if( once && + ((pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0 + || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0)) + ){ + break; + } m = getMask(&maskSet, pTabItem->iCursor); if( (m & notReady)==0 ){ if( j==iFrom ) iFrom++; @@ -1512,17 +1519,13 @@ (i==0 && ppOrderBy) ? *ppOrderBy : 0, &pIdx, &flags, &nEq); if( costjointype & (JT_LEFT|JT_CROSS))!=0 - || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0) - ){ - break; - } } TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ, pLevel-pWInfo->a));