Bug 328213, r=vladimir Upgrade to sqlite 3.3.4.

This commit is contained in:
brettw%gmail.com 2006-02-22 20:47:51 +00:00
Родитель 28c1f4ad33
Коммит b06468ea47
41 изменённых файлов: 1537 добавлений и 2717 удалений

Просмотреть файл

@ -1,5 +1,5 @@
This is sqlite 3.3.3
This is sqlite 3.3.4
See http://www.sqlite.org/ for more info.
@ -13,11 +13,20 @@ we just bring in *.c *.h (including a full sqlite3.h).
To move to a new version:
Update opcodes.c, opcodes.h, parse.c, parse.h, all of which are
Update opcodes.c, opcodes.h, parse.c, parse.h, and sqlite3.h, all of which are
normally generated as part of the sqlite build. Pull these out of the
sqlite3 windows source .zip, or autoconfiscate and build a tarball and
copy them out. Yes, this sucks, but it's better than having to build
the parser and all that goop as part of our build.
If you do a configure, you may want to --disable-tcl because the tcl
part may not work on all systems.
You will also need to apply sqlite3-param-indexes.patch.
They you need to update sqlite3file.h, which pulls out random bits of the
internal files that we need to export. If any of these internal structures
change, they need to be changed in sqlite3file.h as well.
-- Vlad Vukicevic <vladimir@pobox.com> 02/2006

Просмотреть файл

@ -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.5 2006-02-08 21:10:09 vladimir%pobox.com Exp $
** $Id: alter.c,v 1.7 2006-05-22 17:48:14 brettw%gmail.com Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -541,6 +541,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zName = sqliteStrDup(pCol->zName);
pCol->zColl = 0;
pCol->zType = 0;
pCol->pDflt = 0;
}

Просмотреть файл

@ -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.315 2006/02/22 03:08:33 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@ -411,8 +411,8 @@ struct BtCursor {
** 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,9 +756,19 @@ static void unlockAllTables(Btree *p){
** 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
@ -810,16 +820,19 @@ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){
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 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
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]);
@ -1260,6 +1273,12 @@ static void freeSpace(MemPage *pPage, int start, int size){
assert( (start + size)<=pPage->pBt->usableSize );
if( size<4 ) size = 4;
#ifdef SQLITE_SECURE_DELETE
/* Overwrite deleted information with zeros when the SECURE_DELETE
** option is enabled at compile-time */
memset(&data[start], 0, size);
#endif
/* Add the space back into the linked list of freeblocks */
hdr = pPage->hdrOffset;
addr = hdr + 1;
@ -1790,9 +1809,9 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
** 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 +2363,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
#endif
assert( pBt->autoVacuum );
if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
if( PTRMAP_ISPAGE(pBt, sqlite3pager_pagecount(pPager)) ){
return SQLITE_CORRUPT_BKPT;
}
@ -2357,14 +2376,26 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
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--;
}
while( PTRMAP_ISPAGE(pBt, finSize) || finSize==PENDING_BYTE_PAGE(pBt) ){
finSize--;
if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
finSize--;
}
}
TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize));
@ -2376,7 +2407,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
*/
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 +2465,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
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 +3838,7 @@ static int allocatePage(
*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.
@ -3853,6 +3885,15 @@ static int freePage(MemPage *pPage){
n = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], n+1);
#ifdef SQLITE_SECURE_DELETE
/* If the SQLITE_SECURE_DELETE compile-time option is enabled, then
** always fully overwrite deleted information with zeros.
*/
rc = sqlite3pager_write(pPage->aData);
if( rc ) return rc;
memset(pPage->aData, 0, pPage->pBt->pageSize);
#endif
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, write an entry in the pointer-map
** to indicate that the page is free.
@ -3893,7 +3934,9 @@ static int freePage(MemPage *pPage){
if( rc ) return rc;
put4byte(&pTrunk->aData[4], k+1);
put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE
sqlite3pager_dont_write(pBt->pPager, pPage->pgno);
#endif
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
}
releasePage(pTrunk);
@ -5440,7 +5483,7 @@ int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
/* 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 +5756,7 @@ int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
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 +6433,11 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
** 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 +6565,21 @@ int sqlite3BtreeIsInStmt(Btree *p){
** 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;
}
/*

Просмотреть файл

@ -1,148 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite B-Tree file
** 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 $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 10
/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
*/
#ifndef SQLITE_DEFAULT_AUTOVACUUM
#define SQLITE_DEFAULT_AUTOVACUUM 0
#endif
/*
** Forward declarations of structure
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtShared BtShared;
int sqlite3BtreeOpen(
const char *zFilename, /* Name of database file to open */
sqlite3 *db, /* Associated database connection */
Btree **, /* Return open Btree* here */
int flags /* Flags */
);
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
**
** NOTE: These values must match the corresponding PAGER_ values in
** pager.h.
*/
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*);
int sqlite3BtreeBeginStmt(Btree*);
int sqlite3BtreeCommitStmt(Btree*);
int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *);
int sqlite3BtreeLockTable(Btree *, int, u8);
const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetDirname(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);
/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
** of the following flags:
*/
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
int(*)(void*,int,const void*,int,const void*), /* Key comparison function */
void*, /* First argument to compare function */
BtCursor **ppCursor /* Returned cursor */
);
void sqlite3BtreeSetCompare(
BtCursor *,
int(*)(void*,int,const void*,int,const void*),
void*
);
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes);
int sqlite3BtreeDelete(BtCursor*);
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
struct Pager *sqlite3BtreePager(Btree*);
#ifdef SQLITE_TEST
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
#endif
#ifdef SQLITE_DEBUG
int sqlite3BtreePageDump(Btree*, int, int recursive);
#else
#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK
#endif
#endif /* _BTREE_H_ */

Просмотреть файл

@ -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.388 2006/02/18 16:36:45 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -135,8 +135,8 @@ void sqlite3FinishCoding(Parse *pParse){
if( !pParse->pVdbe ){
if( pParse->rc==SQLITE_OK && pParse->nErr ){
pParse->rc = SQLITE_ERROR;
return;
}
return;
}
/* Begin by generating some termination code at the end of the
@ -185,7 +185,7 @@ void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 ){
if( v && pParse->nErr==0 && !sqlite3MallocFailed() ){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
@ -1662,12 +1662,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** 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 @@ void sqlite3CreateIndex(
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 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
pItem->zName = sqlite3NameFromToken(pTable);
pItem->zDatabase = sqlite3NameFromToken(pDatabase);
pItem->iCursor = -1;
pItem->isPopulated = 0;
pList->nSrc++;
return pList;
}
@ -2959,7 +2958,7 @@ void sqlite3RollbackTransaction(Parse *pParse){
** Make sure the TEMP database is open and available for use. Return
** the number of errors. Leave any error messages in the pParse structure.
*/
static int sqlite3OpenTempDatabase(Parse *pParse){
int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc = sqlite3BtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);

Просмотреть файл

@ -1,998 +0,0 @@
/*
** 2003 October 31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement date and time
** functions for SQLite.
**
** There is only one exported symbol in this file - the function
** 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 $
**
** NOTES:
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system.
**
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
**
** This implemention requires years to be expressed as a 4-digit number
** which means that only dates between 0000-01-01 and 9999-12-31 can
** be represented, even though julian day numbers allow a much wider
** range of dates.
**
** The Gregorian calendar system is used for all dates and times,
** even those that predate the Gregorian calendar. Historians usually
** use the Julian calendar for dates prior to 1582-10-15 and for some
** dates afterwards, depending on locale. Beware of this difference.
**
** The conversion algorithms are implemented based on descriptions
** in the following text:
**
** Jean Meeus
** Astronomical Algorithms, 2nd Edition, 1998
** ISBM 0-943396-61-1
** Willmann-Bell, Inc
** Richmond, Virginia (USA)
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#ifndef SQLITE_OMIT_DATETIME_FUNCS
/*
** A structure for holding a single date and time.
*/
typedef struct DateTime DateTime;
struct DateTime {
double rJD; /* The julian day number */
int Y, M, D; /* Year, month, and day */
int h, m; /* Hour and minutes */
int tz; /* Timezone offset in minutes */
double s; /* Seconds */
char validYMD; /* True if Y,M,D are valid */
char validHMS; /* True if h,m,s are valid */
char validJD; /* True if rJD is valid */
char validTZ; /* True if tz is valid */
};
/*
** Convert zDate into one or more integers. Additional arguments
** come in groups of 5 as follows:
**
** N number of digits in the integer
** min minimum allowed value of the integer
** max maximum allowed value of the integer
** nextC first character after the integer
** pVal where to write the integers value.
**
** Conversions continue until one with nextC==0 is encountered.
** The function returns the number of successful conversions.
*/
static int getDigits(const char *zDate, ...){
va_list ap;
int val;
int N;
int min;
int max;
int nextC;
int *pVal;
int cnt = 0;
va_start(ap, zDate);
do{
N = va_arg(ap, int);
min = va_arg(ap, int);
max = va_arg(ap, int);
nextC = va_arg(ap, int);
pVal = va_arg(ap, int*);
val = 0;
while( N-- ){
if( !isdigit(*(u8*)zDate) ){
goto end_getDigits;
}
val = val*10 + *zDate - '0';
zDate++;
}
if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
goto end_getDigits;
}
*pVal = val;
zDate++;
cnt++;
}while( nextC );
va_end(ap);
end_getDigits:
return cnt;
}
/*
** Read text from z[] and convert into a floating point number. Return
** the number of digits converted.
*/
#define getValue sqlite3AtoF
/*
** Parse a timezone extension on the end of a date-time.
** The extension is of the form:
**
** (+/-)HH:MM
**
** If the parse is successful, write the number of minutes
** of change in *pnMin and return 0. If a parser error occurs,
** return 0.
**
** A missing specifier is not considered an error.
*/
static int parseTimezone(const char *zDate, DateTime *p){
int sgn = 0;
int nHr, nMn;
while( isspace(*(u8*)zDate) ){ zDate++; }
p->tz = 0;
if( *zDate=='-' ){
sgn = -1;
}else if( *zDate=='+' ){
sgn = +1;
}else{
return *zDate!=0;
}
zDate++;
if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
return 1;
}
zDate += 5;
p->tz = sgn*(nMn + nHr*60);
while( isspace(*(u8*)zDate) ){ zDate++; }
return *zDate!=0;
}
/*
** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
** The HH, MM, and SS must each be exactly 2 digits. The
** fractional seconds FFFF can be one or more digits.
**
** Return 1 if there is a parsing error and 0 on success.
*/
static int parseHhMmSs(const char *zDate, DateTime *p){
int h, m, s;
double ms = 0.0;
if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
return 1;
}
zDate += 5;
if( *zDate==':' ){
zDate++;
if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
return 1;
}
zDate += 2;
if( *zDate=='.' && isdigit((u8)zDate[1]) ){
double rScale = 1.0;
zDate++;
while( isdigit(*(u8*)zDate) ){
ms = ms*10.0 + *zDate - '0';
rScale *= 10.0;
zDate++;
}
ms /= rScale;
}
}else{
s = 0;
}
p->validJD = 0;
p->validHMS = 1;
p->h = h;
p->m = m;
p->s = s + ms;
if( parseTimezone(zDate, p) ) return 1;
p->validTZ = p->tz!=0;
return 0;
}
/*
** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
** that the YYYY-MM-DD is according to the Gregorian calendar.
**
** Reference: Meeus page 61
*/
static void computeJD(DateTime *p){
int Y, M, D, A, B, X1, X2;
if( p->validJD ) return;
if( p->validYMD ){
Y = p->Y;
M = p->M;
D = p->D;
}else{
Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
M = 1;
D = 1;
}
if( M<=2 ){
Y--;
M += 12;
}
A = Y/100;
B = 2 - A + (A/4);
X1 = 365.25*(Y+4716);
X2 = 30.6001*(M+1);
p->rJD = X1 + X2 + D + B - 1524.5;
p->validJD = 1;
p->validYMD = 0;
if( p->validHMS ){
p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
if( p->validTZ ){
p->rJD -= p->tz*60/86400.0;
p->validHMS = 0;
p->validTZ = 0;
}
}
}
/*
** Parse dates of the form
**
** YYYY-MM-DD HH:MM:SS.FFF
** YYYY-MM-DD HH:MM:SS
** YYYY-MM-DD HH:MM
** YYYY-MM-DD
**
** Write the result into the DateTime structure and return 0
** on success and 1 if the input string is not a well-formed
** date.
*/
static int parseYyyyMmDd(const char *zDate, DateTime *p){
int Y, M, D, neg;
if( zDate[0]=='-' ){
zDate++;
neg = 1;
}else{
neg = 0;
}
if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
return 1;
}
zDate += 10;
while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; }
if( parseHhMmSs(zDate, p)==0 ){
/* We got the time */
}else if( *zDate==0 ){
p->validHMS = 0;
}else{
return 1;
}
p->validJD = 0;
p->validYMD = 1;
p->Y = neg ? -Y : Y;
p->M = M;
p->D = D;
if( p->validTZ ){
computeJD(p);
}
return 0;
}
/*
** Attempt to parse the given string into a Julian Day Number. Return
** the number of errors.
**
** The following are acceptable forms for the input string:
**
** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
** DDDD.DD
** now
**
** In the first form, the +/-HH:MM is always optional. The fractional
** seconds extension (the ".FFF") is optional. The seconds portion
** (":SS.FFF") is option. The year and date can be omitted as long
** as there is a time string. The time string can be omitted as long
** as there is a year and date.
*/
static int parseDateOrTime(const char *zDate, DateTime *p){
memset(p, 0, sizeof(*p));
if( parseYyyyMmDd(zDate,p)==0 ){
return 0;
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0){
double r;
sqlite3OsCurrentTime(&r);
p->rJD = r;
p->validJD = 1;
return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
getValue(zDate, &p->rJD);
p->validJD = 1;
return 0;
}
return 1;
}
/*
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
int Z, A, B, C, D, E, X1;
if( p->validYMD ) return;
if( !p->validJD ){
p->Y = 2000;
p->M = 1;
p->D = 1;
}else{
Z = p->rJD + 0.5;
A = (Z - 1867216.25)/36524.25;
A = Z + 1 + A - (A/4);
B = A + 1524;
C = (B - 122.1)/365.25;
D = 365.25*C;
E = (B-D)/30.6001;
X1 = 30.6001*E;
p->D = B - D - X1;
p->M = E<14 ? E-1 : E-13;
p->Y = p->M>2 ? C - 4716 : C - 4715;
}
p->validYMD = 1;
}
/*
** Compute the Hour, Minute, and Seconds from the julian day number.
*/
static void computeHMS(DateTime *p){
int Z, s;
if( p->validHMS ) return;
Z = p->rJD + 0.5;
s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
p->s = 0.001*s;
s = p->s;
p->s -= s;
p->h = s/3600;
s -= p->h*3600;
p->m = s/60;
p->s += s - p->m*60;
p->validHMS = 1;
}
/*
** Compute both YMD and HMS
*/
static void computeYMD_HMS(DateTime *p){
computeYMD(p);
computeHMS(p);
}
/*
** Clear the YMD and HMS and the TZ
*/
static void clearYMD_HMS_TZ(DateTime *p){
p->validYMD = 0;
p->validHMS = 0;
p->validTZ = 0;
}
/*
** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
** for the time value p where p is in UTC.
*/
static double localtimeOffset(DateTime *p){
DateTime x, y;
time_t t;
struct tm *pTm;
x = *p;
computeYMD_HMS(&x);
if( x.Y<1971 || x.Y>=2038 ){
x.Y = 2000;
x.M = 1;
x.D = 1;
x.h = 0;
x.m = 0;
x.s = 0.0;
} else {
int s = x.s + 0.5;
x.s = s;
}
x.tz = 0;
x.validJD = 0;
computeJD(&x);
t = (x.rJD-2440587.5)*86400.0 + 0.5;
sqlite3OsEnterMutex();
pTm = localtime(&t);
y.Y = pTm->tm_year + 1900;
y.M = pTm->tm_mon + 1;
y.D = pTm->tm_mday;
y.h = pTm->tm_hour;
y.m = pTm->tm_min;
y.s = pTm->tm_sec;
sqlite3OsLeaveMutex();
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
y.validTZ = 0;
computeJD(&y);
return y.rJD - x.rJD;
}
/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
**
** NNN days
** NNN hours
** NNN minutes
** NNN.NNNN seconds
** NNN months
** NNN years
** start of month
** start of year
** start of week
** start of day
** weekday N
** unixepoch
** localtime
** utc
**
** Return 0 on success and 1 if there is any kind of error.
*/
static int parseModifier(const char *zMod, DateTime *p){
int rc = 1;
int n;
double r;
char *z, zBuf[30];
z = zBuf;
for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
z[n] = tolower(zMod[n]);
}
z[n] = 0;
switch( z[0] ){
case 'l': {
/* localtime
**
** Assuming the current time value is UTC (a.k.a. GMT), shift it to
** show local time.
*/
if( strcmp(z, "localtime")==0 ){
computeJD(p);
p->rJD += localtimeOffset(p);
clearYMD_HMS_TZ(p);
rc = 0;
}
break;
}
case 'u': {
/*
** unixepoch
**
** Treat the current value of p->rJD as the number of
** seconds since 1970. Convert to a real julian day number.
*/
if( strcmp(z, "unixepoch")==0 && p->validJD ){
p->rJD = p->rJD/86400.0 + 2440587.5;
clearYMD_HMS_TZ(p);
rc = 0;
}else if( strcmp(z, "utc")==0 ){
double c1;
computeJD(p);
c1 = localtimeOffset(p);
p->rJD -= c1;
clearYMD_HMS_TZ(p);
p->rJD += c1 - localtimeOffset(p);
rc = 0;
}
break;
}
case 'w': {
/*
** weekday N
**
** Move the date to the same time on the next occurrence of
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
*/
if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
&& (n=r)==r && n>=0 && r<7 ){
int Z;
computeYMD_HMS(p);
p->validTZ = 0;
p->validJD = 0;
computeJD(p);
Z = p->rJD + 1.5;
Z %= 7;
if( Z>n ) Z -= 7;
p->rJD += n - Z;
clearYMD_HMS_TZ(p);
rc = 0;
}
break;
}
case 's': {
/*
** start of TTTTT
**
** Move the date backwards to the beginning of the current day,
** or month or year.
*/
if( strncmp(z, "start of ", 9)!=0 ) break;
z += 9;
computeYMD(p);
p->validHMS = 1;
p->h = p->m = 0;
p->s = 0.0;
p->validTZ = 0;
p->validJD = 0;
if( strcmp(z,"month")==0 ){
p->D = 1;
rc = 0;
}else if( strcmp(z,"year")==0 ){
computeYMD(p);
p->M = 1;
p->D = 1;
rc = 0;
}else if( strcmp(z,"day")==0 ){
rc = 0;
}
break;
}
case '+':
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
n = getValue(z, &r);
if( n<=0 ) break;
if( z[n]==':' ){
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
** specified number of hours, minutes, seconds, and fractional seconds
** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
** omitted.
*/
const char *z2 = z;
DateTime tx;
int day;
if( !isdigit(*(u8*)z2) ) z2++;
memset(&tx, 0, sizeof(tx));
if( parseHhMmSs(z2, &tx) ) break;
computeJD(&tx);
tx.rJD -= 0.5;
day = (int)tx.rJD;
tx.rJD -= day;
if( z[0]=='-' ) tx.rJD = -tx.rJD;
computeJD(p);
clearYMD_HMS_TZ(p);
p->rJD += tx.rJD;
rc = 0;
break;
}
z += n;
while( isspace(*(u8*)z) ) z++;
n = strlen(z);
if( n>10 || n<3 ) break;
if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
computeJD(p);
rc = 0;
if( n==3 && strcmp(z,"day")==0 ){
p->rJD += r;
}else if( n==4 && strcmp(z,"hour")==0 ){
p->rJD += r/24.0;
}else if( n==6 && strcmp(z,"minute")==0 ){
p->rJD += r/(24.0*60.0);
}else if( n==6 && strcmp(z,"second")==0 ){
p->rJD += r/(24.0*60.0*60.0);
}else if( n==5 && strcmp(z,"month")==0 ){
int x, y;
computeYMD_HMS(p);
p->M += r;
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
p->Y += x;
p->M -= x*12;
p->validJD = 0;
computeJD(p);
y = r;
if( y!=r ){
p->rJD += (r - y)*30.0;
}
}else if( n==4 && strcmp(z,"year")==0 ){
computeYMD_HMS(p);
p->Y += r;
p->validJD = 0;
computeJD(p);
}else{
rc = 1;
}
clearYMD_HMS_TZ(p);
break;
}
default: {
break;
}
}
return rc;
}
/*
** Process time function arguments. argv[0] is a date-time stamp.
** argv[1] and following are modifiers. Parse them all and write
** the resulting time into the DateTime structure p. Return 0
** on success and 1 if there are any errors.
*/
static int isDate(int argc, sqlite3_value **argv, DateTime *p){
int i;
if( argc==0 ) return 1;
if( SQLITE_NULL==sqlite3_value_type(argv[0]) ||
parseDateOrTime((char*)sqlite3_value_text(argv[0]), p) ) return 1;
for(i=1; i<argc; i++){
if( SQLITE_NULL==sqlite3_value_type(argv[i]) ||
parseModifier((char*)sqlite3_value_text(argv[i]), p) ) return 1;
}
return 0;
}
/*
** The following routines implement the various date and time functions
** of SQLite.
*/
/*
** julianday( TIMESTRING, MOD, MOD, ...)
**
** Return the julian day number of the date specified in the arguments
*/
static void juliandayFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
computeJD(&x);
sqlite3_result_double(context, x.rJD);
}
}
/*
** datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeYMD_HMS(&x);
sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
(int)(x.s));
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
/*
** time( TIMESTRING, MOD, MOD, ...)
**
** Return HH:MM:SS
*/
static void timeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeHMS(&x);
sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
/*
** date( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD
*/
static void dateFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeYMD(&x);
sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
/*
** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
**
** Return a string described by FORMAT. Conversions as follows:
**
** %d day of month
** %f ** fractional seconds SS.SSS
** %H hour 00-24
** %j day of year 000-366
** %J ** Julian day number
** %m month 01-12
** %M minute 00-59
** %s seconds since 1970-01-01
** %S seconds 00-59
** %w day of week 0-6 sunday==0
** %W week of year 00-53
** %Y year 0000-9999
** %% %
*/
static void strftimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
int n, i, j;
char *z;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return;
for(i=0, n=1; zFmt[i]; i++, n++){
if( zFmt[i]=='%' ){
switch( zFmt[i+1] ){
case 'd':
case 'H':
case 'm':
case 'M':
case 'S':
case 'W':
n++;
/* fall thru */
case 'w':
case '%':
break;
case 'f':
n += 8;
break;
case 'j':
n += 3;
break;
case 'Y':
n += 8;
break;
case 's':
case 'J':
n += 50;
break;
default:
return; /* ERROR. return a NULL */
}
i++;
}
}
if( n<sizeof(zBuf) ){
z = zBuf;
}else{
z = sqliteMalloc( n );
if( z==0 ) return;
}
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
if( zFmt[i]!='%' ){
z[j++] = zFmt[i];
}else{
i++;
switch( zFmt[i] ){
case 'd': sprintf(&z[j],"%02d",x.D); j+=2; break;
case 'f': {
int s = x.s;
int ms = (x.s - s)*1000.0;
sprintf(&z[j],"%02d.%03d",s,ms);
j += strlen(&z[j]);
break;
}
case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
case 'W': /* Fall thru */
case 'j': {
int nDay; /* Number of days since 1st day of year */
DateTime y = x;
y.validJD = 0;
y.M = 1;
y.D = 1;
computeJD(&y);
nDay = x.rJD - y.rJD;
if( zFmt[i]=='W' ){
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
wd = ((int)(x.rJD+0.5)) % 7;
sprintf(&z[j],"%02d",(nDay+7-wd)/7);
j += 2;
}else{
sprintf(&z[j],"%03d",nDay+1);
j += 3;
}
break;
}
case 'J': sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
case 'm': sprintf(&z[j],"%02d",x.M); j+=2; break;
case 'M': sprintf(&z[j],"%02d",x.m); j+=2; break;
case 's': {
sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
j += strlen(&z[j]);
break;
}
case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
case '%': z[j++] = '%'; break;
}
}
}
z[j] = 0;
sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
if( z!=zBuf ){
sqliteFree(z);
}
}
/*
** current_time()
**
** This function returns the same value as time('now').
*/
static void ctimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
timeFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
/*
** current_date()
**
** This function returns the same value as date('now').
*/
static void cdateFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dateFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
/*
** current_timestamp()
**
** This function returns the same value as datetime('now').
*/
static void ctimestampFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
datetimeFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
#ifdef SQLITE_OMIT_DATETIME_FUNCS
/*
** If the library is compiled to omit the full-scale date and time
** handling (to get a smaller binary), the following minimal version
** of the functions current_time(), current_date() and current_timestamp()
** are included instead. This is to support column declarations that
** include "DEFAULT CURRENT_TIME" etc.
**
** This function uses the C-library functions time(), gmtime()
** and strftime(). The format string to pass to strftime() is supplied
** as the user-data for the function.
*/
static void currentTimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
time_t t;
char *zFormat = (char *)sqlite3_user_data(context);
char zBuf[20];
time(&t);
#ifdef SQLITE_TEST
{
extern int sqlite3_current_time; /* See os_XXX.c */
if( sqlite3_current_time ){
t = sqlite3_current_time;
}
}
#endif
sqlite3OsEnterMutex();
strftime(zBuf, 20, zFormat, gmtime(&t));
sqlite3OsLeaveMutex();
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
#endif
/*
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
** external linkage.
*/
void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_DATETIME_FUNCS
static const struct {
char *zName;
int nArg;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFuncs[] = {
{ "julianday", -1, juliandayFunc },
{ "date", -1, dateFunc },
{ "time", -1, timeFunc },
{ "datetime", -1, datetimeFunc },
{ "strftime", -1, strftimeFunc },
{ "current_time", 0, ctimeFunc },
{ "current_timestamp", 0, ctimestampFunc },
{ "current_date", 0, cdateFunc },
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
#else
static const struct {
char *zName;
char *zFormat;
} aFuncs[] = {
{ "current_time", "%H:%M:%S" },
{ "current_date", "%Y-%m-%d" },
{ "current_timestamp", "%Y-%m-%d %H:%M:%S" }
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8,
aFuncs[i].zFormat, currentTimeFunc, 0, 0);
}
#endif
}

Просмотреть файл

@ -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 @@ void sqlite3DeleteFrom(
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:

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains C code routines that are not a part of the official
** SQLite API. These routines are unsupported.
**
** $Id: experimental.c,v 1.2 2006-02-08 21:10:10 vladimir%pobox.com Exp $
** $Id: experimental.c,v 1.4 2006-05-22 17:48:14 brettw%gmail.com Exp $
*/
#include "sqliteInt.h"
#include "os.h"

Просмотреть файл

@ -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 <ctype.h>
@ -495,6 +495,7 @@ SrcList *sqlite3SrcListDup(SrcList *p){
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++;

Просмотреть файл

@ -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.122 2006/02/11 17:34:00 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -817,9 +817,11 @@ static void test_error(
*/
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 */
double rSum; /* Floating point sum */
i64 iSum; /* Integer sum */
i64 cnt; /* Number of elements summed */
u8 overflow; /* True if integer overflow seen */
u8 approx; /* True if non-integer value was input to the sum */
};
/*
@ -830,18 +832,38 @@ struct SumCtx {
** 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 ){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 ){
i64 iNewSum = p->iSum + v;
int s1 = p->iSum >> (sizeof(i64)*8-1);
int s2 = v >> (sizeof(i64)*8-1);
int s3 = iNewSum >> (sizeof(i64)*8-1);
p->overflow = (s1&s2&~s3) | (~s1&~s2&s3);
p->iSum = iNewSum;
}
}else{
p->rSum += sqlite3_value_double(argv[0]);
p->approx = 1;
}
}
}
@ -849,10 +871,12 @@ static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
if( p->seenFloat ){
sqlite3_result_double(context, p->sum);
if( p->overflow ){
sqlite3_result_error(context,"integer overflow",-1);
}else if( p->approx ){
sqlite3_result_double(context, p->rSum);
}else{
sqlite3_result_int64(context, (i64)p->sum);
sqlite3_result_int64(context, p->iSum);
}
}
}
@ -860,33 +884,22 @@ static void avgFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
sqlite3_result_double(context, p->sum/(double)p->cnt);
sqlite3_result_double(context, p->rSum/(double)p->cnt);
}
}
static void totalFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_double(context, p ? p->sum : 0.0);
sqlite3_result_double(context, p ? p->rSum : 0.0);
}
/*
** 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 +915,7 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
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);
}
/*

Просмотреть файл

@ -1,392 +0,0 @@
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
** $Id: hash.c,v 1.17 2005/10/03 15:11:09 drh Exp $
*/
#include "sqliteInt.h"
#include <assert.h>
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
** determines what kind of key the hash table will use. "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer. CopyKey only makes
** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
** for other key classes.
*/
void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
assert( pNew!=0 );
assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
pNew->keyClass = keyClass;
#if 0
if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
#endif
pNew->copyKey = copyKey;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
pNew->ht = 0;
}
/* Remove all entries from a hash table. Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void sqlite3HashClear(Hash *pH){
HashElem *elem; /* For looping over all elements of the table */
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
if( pH->ht ) sqliteFree(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
}
sqliteFree(elem);
elem = next_elem;
}
pH->count = 0;
}
#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is SQLITE_HASH_INT
*/
static int intHash(const void *pKey, int nKey){
return nKey ^ (nKey<<8) ^ (nKey>>8);
}
static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
return n2 - n1;
}
#endif
#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
*/
static int ptrHash(const void *pKey, int nKey){
uptr x = Addr(pKey);
return x ^ (x<<8) ^ (x>>8);
}
static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( pKey1==pKey2 ) return 0;
if( pKey1<pKey2 ) return -1;
return 1;
}
#endif
/*
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
const char *z = (const char *)pKey;
int h = 0;
if( nKey<=0 ) nKey = strlen(z);
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
nKey--;
}
return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
/*
** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
*/
static int binHash(const void *pKey, int nKey){
int h = 0;
const char *z = (const char *)pKey;
while( nKey-- > 0 ){
h = (h<<3) ^ h ^ *(z++);
}
return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
return memcmp(pKey1,pKey2,n1);
}
/*
** Return a pointer to the appropriate hash function given the key class.
**
** The C syntax in this function definition may be unfamilar to some
** programmers, so we provide the following additional explanation:
**
** The name of the function is "hashFunction". The function takes a
** single parameter "keyClass". The return value of hashFunction()
** is a pointer to another function. Specifically, the return value
** of hashFunction() is a pointer to a function that takes two parameters
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intHash;
case SQLITE_HASH_POINTER: return &ptrHash;
case SQLITE_HASH_STRING: return &strHash;
case SQLITE_HASH_BINARY: return &binHash;;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strHash;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binHash;
}
#endif
}
/*
** Return a pointer to the appropriate hash function given the key class.
**
** For help in interpreted the obscure C code in the function definition,
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intCompare;
case SQLITE_HASH_POINTER: return &ptrCompare;
case SQLITE_HASH_STRING: return &strCompare;
case SQLITE_HASH_BINARY: return &binCompare;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strCompare;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binCompare;
}
#endif
}
/* Link an element into the hash table
*/
static void insertElement(
Hash *pH, /* The complete hash table */
struct _ht *pEntry, /* The entry into which pNew is inserted */
HashElem *pNew /* The element to be inserted */
){
HashElem *pHead; /* First element already in pEntry */
pHead = pEntry->chain;
if( pHead ){
pNew->next = pHead;
pNew->prev = pHead->prev;
if( pHead->prev ){ pHead->prev->next = pNew; }
else { pH->first = pNew; }
pHead->prev = pNew;
}else{
pNew->next = pH->first;
if( pH->first ){ pH->first->prev = pNew; }
pNew->prev = 0;
pH->first = pNew;
}
pEntry->count++;
pEntry->chain = pNew;
}
/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
*/
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
int (*xHash)(const void*,int); /* The hash function */
assert( (new_size & (new_size-1))==0 );
new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
if( new_ht==0 ) return;
if( pH->ht ) sqliteFree(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
xHash = hashFunction(pH->keyClass);
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
next_elem = elem->next;
insertElement(pH, &new_ht[h], elem);
}
}
/* This function (for internal use only) locates an element in an
** hash table that matches the given key. The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static HashElem *findElementGivenHash(
const Hash *pH, /* The pH to be searched */
const void *pKey, /* The key we are searching for */
int nKey,
int h /* The hash for this key. */
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
int (*xCompare)(const void*,int,const void*,int); /* comparison function */
if( pH->ht ){
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
xCompare = compareFunction(pH->keyClass);
while( count-- && elem ){
if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
}
}
return 0;
}
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
Hash *pH, /* The pH containing "elem" */
HashElem* elem, /* The element to be removed from the pH */
int h /* Hash value for the element */
){
struct _ht *pEntry;
if( elem->prev ){
elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
if( elem->next ){
elem->next->prev = elem->prev;
}
pEntry = &pH->ht[h];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
pEntry->count--;
if( pEntry->count<=0 ){
pEntry->chain = 0;
}
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
}
sqliteFree( elem );
pH->count--;
if( pH->count<=0 ){
assert( pH->first==0 );
assert( pH->count==0 );
sqlite3HashClear(pH);
}
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
int (*xHash)(const void*,int); /* The hash function */
if( pH==0 || pH->ht==0 ) return 0;
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
h = (*xHash)(pKey,nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
return elem ? elem->data : 0;
}
/* Insert an element into the hash table pH. The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created. A copy of the key is made if the copyKey
** flag is set. NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance. If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
int hraw; /* Raw hash value of the key */
int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
HashElem *new_elem; /* New element added to the pH */
int (*xHash)(const void*,int); /* The hash function */
assert( pH!=0 );
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
hraw = (*xHash)(pKey, nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
elem = findElementGivenHash(pH,pKey,nKey,h);
if( elem ){
void *old_data = elem->data;
if( data==0 ){
removeElementGivenHash(pH,elem,h);
}else{
elem->data = data;
}
return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
new_elem->pKey = sqliteMallocRaw( nKey );
if( new_elem->pKey==0 ){
sqliteFree(new_elem);
return data;
}
memcpy((void*)new_elem->pKey, pKey, nKey);
}else{
new_elem->pKey = (void*)pKey;
}
new_elem->nKey = nKey;
pH->count++;
if( pH->htsize==0 ){
rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
sqliteFree(new_elem);
return data;
}
}
if( pH->count > pH->htsize ){
rehash(pH,pH->htsize*2);
}
assert( pH->htsize>0 );
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
insertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}

Просмотреть файл

@ -1,109 +0,0 @@
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
** $Id: hash.h,v 1.8 2004/08/20 14:08:51 drh Exp $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_
/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;
/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly. Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct Hash {
char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
int htsize; /* Number of buckets in the hash table */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
HashElem *chain; /* Pointer to first entry with this hash */
} *ht;
};
/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
void *pKey; int nKey; /* Key associated with this element */
};
/*
** There are 4 different modes of operation for a hash table:
**
** SQLITE_HASH_INT nKey is used as the key and pKey is ignored.
**
** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored.
**
** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long
** (including the null-terminator, if any). Case
** is ignored in comparisons.
**
** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long.
** memcmp() is used to compare keys.
**
** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
** if the copyKey parameter to HashInit is 1.
*/
/* #define SQLITE_HASH_INT 1 // NOT USED */
/* #define SQLITE_HASH_POINTER 2 // NOT USED */
#define SQLITE_HASH_STRING 3
#define SQLITE_HASH_BINARY 4
/*
** Access routines. To delete, insert a NULL pointer.
*/
void sqlite3HashInit(Hash*, int keytype, int copyKey);
void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
void sqlite3HashClear(Hash*);
/*
** Macros for looping over all elements of a hash table. The idiom is
** like this:
**
** Hash h;
** HashElem *p;
** ...
** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
** SomeStructure *pData = sqliteHashData(p);
** // do something with pData
** }
*/
#define sqliteHashFirst(H) ((H)->first)
#define sqliteHashNext(E) ((E)->next)
#define sqliteHashData(E) ((E)->data)
#define sqliteHashKey(E) ((E)->pKey)
#define sqliteHashKeysize(E) ((E)->nKey)
/*
** Number of entries in a hash table
*/
#define sqliteHashCount(H) ((H)->count)
#endif /* _SQLITE_HASH_H_ */

Просмотреть файл

@ -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 @@ void sqlite3Insert(
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:

Просмотреть файл

@ -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.335 2006/02/16 18:16:37 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -29,7 +29,6 @@ const int sqlite3one = 1;
/*
** 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 @@ int sqlite3_errcode(sqlite3 *db){
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,
@ -740,6 +743,7 @@ static int createCollation(
int(*xCompare)(void*,int,const void*,int,const void*)
){
CollSeq *pColl;
int enc2;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
@ -749,15 +753,13 @@ static int createCollation(
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
*/
if( enc==SQLITE_UTF16 ){
enc = SQLITE_UTF16NATIVE;
enc2 = enc & ~SQLITE_UTF16_ALIGNED;
if( enc2==SQLITE_UTF16 ){
enc2 = SQLITE_UTF16NATIVE;
}
if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){
sqlite3Error(db, SQLITE_ERROR,
"Param 3 to sqlite3_create_collation() must be one of "
"SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE"
);
if( (enc2&~3)!=0 ){
sqlite3Error(db, SQLITE_ERROR, "unknown encoding");
return SQLITE_ERROR;
}
@ -765,7 +767,7 @@ static int createCollation(
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0);
if( pColl && pColl->xCmp ){
if( db->activeVdbeCnt ){
sqlite3Error(db, SQLITE_BUSY,
@ -775,11 +777,11 @@ static int createCollation(
sqlite3ExpirePreparedStatements(db);
}
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1);
if( pColl ){
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
pColl->enc = enc;
pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED);
}
sqlite3Error(db, SQLITE_OK, 0);
return SQLITE_OK;
@ -817,8 +819,9 @@ static int openDatabase(
** 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 +1116,116 @@ void sqlite3_thread_cleanup(void){
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; iCol<pTab->nCol; 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

Просмотреть файл

@ -1,147 +0,0 @@
/* Automatically generated. Do not edit */
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
/* 1 */ "MemLoad",
/* 2 */ "Column",
/* 3 */ "SetCookie",
/* 4 */ "IfMemPos",
/* 5 */ "Sequence",
/* 6 */ "MoveGt",
/* 7 */ "RowKey",
/* 8 */ "OpenWrite",
/* 9 */ "If",
/* 10 */ "Pop",
/* 11 */ "CollSeq",
/* 12 */ "OpenRead",
/* 13 */ "Expire",
/* 14 */ "AutoCommit",
/* 15 */ "IntegrityCk",
/* 16 */ "Not",
/* 17 */ "Sort",
/* 18 */ "Function",
/* 19 */ "Noop",
/* 20 */ "Return",
/* 21 */ "NewRowid",
/* 22 */ "IfMemNeg",
/* 23 */ "Variable",
/* 24 */ "String",
/* 25 */ "RealAffinity",
/* 26 */ "ParseSchema",
/* 27 */ "Close",
/* 28 */ "CreateIndex",
/* 29 */ "IsUnique",
/* 30 */ "IdxIsNull",
/* 31 */ "NotFound",
/* 32 */ "Int64",
/* 33 */ "MustBeInt",
/* 34 */ "Halt",
/* 35 */ "Rowid",
/* 36 */ "IdxLT",
/* 37 */ "AddImm",
/* 38 */ "Statement",
/* 39 */ "RowData",
/* 40 */ "MemMax",
/* 41 */ "Push",
/* 42 */ "NotExists",
/* 43 */ "MemIncr",
/* 44 */ "Gosub",
/* 45 */ "Integer",
/* 46 */ "MemInt",
/* 47 */ "Prev",
/* 48 */ "CreateTable",
/* 49 */ "Last",
/* 50 */ "IdxRowid",
/* 51 */ "MakeIdxRec",
/* 52 */ "ResetCount",
/* 53 */ "FifoWrite",
/* 54 */ "Callback",
/* 55 */ "ContextPush",
/* 56 */ "DropTrigger",
/* 57 */ "DropIndex",
/* 58 */ "IdxGE",
/* 59 */ "Or",
/* 60 */ "And",
/* 61 */ "IdxDelete",
/* 62 */ "Vacuum",
/* 63 */ "MoveLe",
/* 64 */ "IsNull",
/* 65 */ "NotNull",
/* 66 */ "Ne",
/* 67 */ "Eq",
/* 68 */ "Gt",
/* 69 */ "Le",
/* 70 */ "Lt",
/* 71 */ "Ge",
/* 72 */ "IfNot",
/* 73 */ "BitAnd",
/* 74 */ "BitOr",
/* 75 */ "ShiftLeft",
/* 76 */ "ShiftRight",
/* 77 */ "Add",
/* 78 */ "Subtract",
/* 79 */ "Multiply",
/* 80 */ "Divide",
/* 81 */ "Remainder",
/* 82 */ "Concat",
/* 83 */ "Negative",
/* 84 */ "DropTable",
/* 85 */ "BitNot",
/* 86 */ "String8",
/* 87 */ "MakeRecord",
/* 88 */ "Delete",
/* 89 */ "AggFinal",
/* 90 */ "Dup",
/* 91 */ "Goto",
/* 92 */ "TableLock",
/* 93 */ "FifoRead",
/* 94 */ "Clear",
/* 95 */ "IdxGT",
/* 96 */ "MoveLt",
/* 97 */ "VerifyCookie",
/* 98 */ "AggStep",
/* 99 */ "Pull",
/* 100 */ "SetNumColumns",
/* 101 */ "AbsValue",
/* 102 */ "Transaction",
/* 103 */ "ContextPop",
/* 104 */ "Next",
/* 105 */ "IdxInsert",
/* 106 */ "Distinct",
/* 107 */ "Insert",
/* 108 */ "Destroy",
/* 109 */ "ReadCookie",
/* 110 */ "ForceInt",
/* 111 */ "LoadAnalysis",
/* 112 */ "OpenVirtual",
/* 113 */ "Explain",
/* 114 */ "IfMemZero",
/* 115 */ "OpenPseudo",
/* 116 */ "Null",
/* 117 */ "Blob",
/* 118 */ "MemStore",
/* 119 */ "Rewind",
/* 120 */ "MoveGe",
/* 121 */ "MemMove",
/* 122 */ "MemNull",
/* 123 */ "Found",
/* 124 */ "Real",
/* 125 */ "HexBlob",
/* 126 */ "NullRow",
/* 127 */ "NotUsed_127",
/* 128 */ "NotUsed_128",
/* 129 */ "NotUsed_129",
/* 130 */ "NotUsed_130",
/* 131 */ "NotUsed_131",
/* 132 */ "NotUsed_132",
/* 133 */ "NotUsed_133",
/* 134 */ "NotUsed_134",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "ToText",
/* 138 */ "ToBlob",
/* 139 */ "ToNumeric",
/* 140 */ "ToInt",
/* 141 */ "ToReal",
};
#endif

Просмотреть файл

@ -1,159 +0,0 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
#define OP_HexBlob 125 /* same as TK_BLOB */
#define OP_Column 2
#define OP_SetCookie 3
#define OP_IfMemPos 4
#define OP_Real 124 /* same as TK_FLOAT */
#define OP_Sequence 5
#define OP_MoveGt 6
#define OP_Ge 71 /* same as TK_GE */
#define OP_RowKey 7
#define OP_Eq 67 /* same as TK_EQ */
#define OP_OpenWrite 8
#define OP_NotNull 65 /* same as TK_NOTNULL */
#define OP_If 9
#define OP_ToInt 140 /* same as TK_TO_INT */
#define OP_String8 86 /* same as TK_STRING */
#define OP_Pop 10
#define OP_CollSeq 11
#define OP_OpenRead 12
#define OP_Expire 13
#define OP_AutoCommit 14
#define OP_Gt 68 /* same as TK_GT */
#define OP_IntegrityCk 15
#define OP_Sort 17
#define OP_Function 18
#define OP_And 60 /* same as TK_AND */
#define OP_Subtract 78 /* same as TK_MINUS */
#define OP_Noop 19
#define OP_Return 20
#define OP_Remainder 81 /* same as TK_REM */
#define OP_NewRowid 21
#define OP_Multiply 79 /* same as TK_STAR */
#define OP_IfMemNeg 22
#define OP_Variable 23
#define OP_String 24
#define OP_RealAffinity 25
#define OP_ParseSchema 26
#define OP_Close 27
#define OP_CreateIndex 28
#define OP_IsUnique 29
#define OP_IdxIsNull 30
#define OP_NotFound 31
#define OP_Int64 32
#define OP_MustBeInt 33
#define OP_Halt 34
#define OP_Rowid 35
#define OP_IdxLT 36
#define OP_AddImm 37
#define OP_Statement 38
#define OP_RowData 39
#define OP_MemMax 40
#define OP_Push 41
#define OP_Or 59 /* same as TK_OR */
#define OP_NotExists 42
#define OP_MemIncr 43
#define OP_Gosub 44
#define OP_Divide 80 /* same as TK_SLASH */
#define OP_Integer 45
#define OP_ToNumeric 139 /* same as TK_TO_NUMERIC*/
#define OP_MemInt 46
#define OP_Prev 47
#define OP_Concat 82 /* same as TK_CONCAT */
#define OP_BitAnd 73 /* same as TK_BITAND */
#define OP_CreateTable 48
#define OP_Last 49
#define OP_IsNull 64 /* same as TK_ISNULL */
#define OP_IdxRowid 50
#define OP_MakeIdxRec 51
#define OP_ShiftRight 76 /* same as TK_RSHIFT */
#define OP_ResetCount 52
#define OP_FifoWrite 53
#define OP_Callback 54
#define OP_ContextPush 55
#define OP_DropTrigger 56
#define OP_DropIndex 57
#define OP_IdxGE 58
#define OP_IdxDelete 61
#define OP_Vacuum 62
#define OP_MoveLe 63
#define OP_IfNot 72
#define OP_DropTable 84
#define OP_MakeRecord 87
#define OP_ToBlob 138 /* same as TK_TO_BLOB */
#define OP_Delete 88
#define OP_AggFinal 89
#define OP_ShiftLeft 75 /* same as TK_LSHIFT */
#define OP_Dup 90
#define OP_Goto 91
#define OP_TableLock 92
#define OP_FifoRead 93
#define OP_Clear 94
#define OP_IdxGT 95
#define OP_MoveLt 96
#define OP_Le 69 /* same as TK_LE */
#define OP_VerifyCookie 97
#define OP_AggStep 98
#define OP_Pull 99
#define OP_ToText 137 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
#define OP_ToReal 141 /* same as TK_TO_REAL */
#define OP_SetNumColumns 100
#define OP_AbsValue 101
#define OP_Transaction 102
#define OP_Negative 83 /* same as TK_UMINUS */
#define OP_Ne 66 /* same as TK_NE */
#define OP_ContextPop 103
#define OP_BitOr 74 /* same as TK_BITOR */
#define OP_Next 104
#define OP_IdxInsert 105
#define OP_Distinct 106
#define OP_Lt 70 /* same as TK_LT */
#define OP_Insert 107
#define OP_Destroy 108
#define OP_ReadCookie 109
#define OP_ForceInt 110
#define OP_LoadAnalysis 111
#define OP_OpenVirtual 112
#define OP_Explain 113
#define OP_IfMemZero 114
#define OP_OpenPseudo 115
#define OP_Null 116
#define OP_Blob 117
#define OP_Add 77 /* same as TK_PLUS */
#define OP_MemStore 118
#define OP_Rewind 119
#define OP_MoveGe 120
#define OP_BitNot 85 /* same as TK_BITNOT */
#define OP_MemMove 121
#define OP_MemNull 122
#define OP_Found 123
#define OP_NullRow 126
/* The following opcode values are never used */
#define OP_NotUsed_127 127
#define OP_NotUsed_128 128
#define OP_NotUsed_129 129
#define OP_NotUsed_130 130
#define OP_NotUsed_131 131
#define OP_NotUsed_132 132
#define OP_NotUsed_133 133
#define OP_NotUsed_134 134
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
/* Opcodes that are guaranteed to never push a value onto the stack
** contain a 1 their corresponding position of the following mask
** set. See the opcodeNoPush() function in vdbeaux.c */
#define NOPUSH_MASK_0 0x7f58
#define NOPUSH_MASK_1 0xee5b
#define NOPUSH_MASK_2 0x9f76
#define NOPUSH_MASK_3 0xfff2
#define NOPUSH_MASK_4 0xffff
#define NOPUSH_MASK_5 0xdb3b
#define NOPUSH_MASK_6 0xcfdf
#define NOPUSH_MASK_7 0x49cd
#define NOPUSH_MASK_8 0x3e00
#define NOPUSH_MASK_9 0x0000

Просмотреть файл

@ -1,188 +0,0 @@
/*
** 2004 May 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains macros and a little bit of code that is common to
** all of the platform-specific files (os_*.c) and is #included into those
** files.
**
** This file should be #included by the os_*.c files only. It is not a
** general purpose header file.
*/
/*
** At least two bugs have slipped in because we changed the MEMORY_DEBUG
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch. The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
/*
* When testing, this global variable stores the location of the
* pending-byte in the database file.
*/
#ifdef SQLITE_TEST
unsigned int sqlite3_pending_byte = 0x40000000;
#endif
int sqlite3_os_trace = 0;
#ifdef SQLITE_DEBUG
static int last_page = 0;
#define SEEK(X) last_page=(X)
#define TRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
#define TRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
#define TRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D) \
if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define SEEK(X)
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D)
#endif
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE
__inline__ unsigned long long int hwtime(void){
unsigned long long int x;
__asm__("rdtsc\n\t"
"mov %%edx, %%ecx\n\t"
:"=A" (x));
return x;
}
static unsigned long long int g_start;
static unsigned int elapse;
#define TIMER_START g_start=hwtime()
#define TIMER_END elapse=hwtime()-g_start
#define TIMER_ELAPSED elapse
#else
#define TIMER_START
#define TIMER_END
#define TIMER_ELAPSED 0
#endif
/*
** If we compile with the SQLITE_TEST macro set, then the following block
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(A) \
if( sqlite3_io_error_pending ) \
if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; }
static void local_ioerr(){
sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */
}
#define SimulateDiskfullError \
if( sqlite3_diskfull_pending ){ \
if( sqlite3_diskfull_pending == 1 ){ \
local_ioerr(); \
sqlite3_diskfull = 1; \
return SQLITE_FULL; \
}else{ \
sqlite3_diskfull_pending--; \
} \
}
#else
#define SimulateIOError(A)
#define SimulateDiskfullError
#endif
/*
** When testing, keep a count of the number of open files.
*/
#ifdef SQLITE_TEST
int sqlite3_open_file_count = 0;
#define OpenCounter(X) sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif
/*
** sqlite3GenericMalloc
** sqlite3GenericRealloc
** sqlite3GenericOsFree
** sqlite3GenericAllocationSize
**
** Implementation of the os level dynamic memory allocation interface in terms
** of the standard malloc(), realloc() and free() found in many operating
** systems. No rocket science here.
**
** There are two versions of these four functions here. The version
** implemented here is only used if memory-management or memory-debugging is
** enabled. This version allocates an extra 8-bytes at the beginning of each
** block and stores the size of the allocation there.
**
** If neither memory-management or debugging is enabled, the second
** set of implementations is used instead.
*/
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG)
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n+8);
assert(n>0);
assert(sizeof(int)<=8);
if( p ){
*(int *)p = n;
p += 8;
}
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
char *p2 = ((char *)p - 8);
assert(n>0);
p2 = realloc(p2, n+8);
if( p2 ){
*(int *)p2 = n;
p2 += 8;
}
return (void *)p2;
}
void sqlite3GenericFree(void *p){
assert(p);
free((void *)((char *)p - 8));
}
int sqlite3GenericAllocationSize(void *p){
return p ? *(int *)((char *)p - 8) : 0;
}
#else
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n);
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
assert(n>0);
p = realloc(p, n);
return p;
}
void sqlite3GenericFree(void *p){
assert(p);
free(p);
}
/* Never actually used, but needed for the linker */
int sqlite3GenericAllocationSize(void *p){ return 0; }
#endif

Просмотреть файл

@ -340,9 +340,10 @@ struct openCnt {
** openKey structures) into lockInfo and openCnt structures. Access to
** these hash tables must be protected by a mutex.
*/
static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0,
sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0};
static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0,
sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0};
#ifdef SQLITE_UNIX_THREADS
/*
@ -353,14 +354,23 @@ static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
** 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
/*
@ -482,7 +492,7 @@ static void releaseLockInfo(struct lockInfo *pLock){
pLock->nRef--;
if( pLock->nRef==0 ){
sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
sqliteFree(pLock);
sqlite3ThreadSafeFree(pLock);
}
}
@ -495,7 +505,7 @@ static void releaseOpenCnt(struct openCnt *pOpen){
if( pOpen->nRef==0 ){
sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
free(pOpen->aPending);
sqliteFree(pOpen);
sqlite3ThreadSafeFree(pOpen);
}
}
@ -536,7 +546,7 @@ static int findLockInfo(
pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));
if( pLock==0 ){
struct lockInfo *pOld;
pLock = sqliteMallocRaw( sizeof(*pLock) );
pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) );
if( pLock==0 ){
rc = 1;
goto exit_findlockinfo;
@ -548,7 +558,7 @@ static int findLockInfo(
pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
if( pOld!=0 ){
assert( pOld==pLock );
sqliteFree(pLock);
sqlite3ThreadSafeFree(pLock);
rc = 1;
goto exit_findlockinfo;
}
@ -560,7 +570,7 @@ static int findLockInfo(
pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));
if( pOpen==0 ){
struct openCnt *pOld;
pOpen = sqliteMallocRaw( sizeof(*pOpen) );
pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
rc = 1;
@ -574,7 +584,7 @@ static int findLockInfo(
pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
if( pOld!=0 ){
assert( pOld==pOpen );
sqliteFree(pOpen);
sqlite3ThreadSafeFree(pOpen);
releaseLockInfo(pLock);
rc = 1;
goto exit_findlockinfo;
@ -972,6 +982,17 @@ int sqlite3_fullsync_count = 0;
# 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
@ -1003,7 +1024,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
rc = SQLITE_OK;
#else
#ifdef F_FULLFSYNC
#if HAVE_FULLFSYNC
if( fullSync ){
rc = fcntl(fd, F_FULLFSYNC, 0);
}else{
@ -1048,10 +1069,21 @@ static int unixSync(OsFile *id, int dataOnly){
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 */
@ -1495,7 +1527,7 @@ static int unixClose(OsFile **pId){
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqliteFree(id);
sqlite3ThreadSafeFree(id);
*pId = 0;
return SQLITE_OK;
}
@ -1520,6 +1552,33 @@ char *sqlite3UnixFullPathname(const char *zRelative){
(char*)0);
sqliteFree(zBuf);
}
#if 0
/*
** Remove "/./" path elements and convert "/A/./" path elements
** to just "/".
*/
if( zFull ){
int i, j;
for(i=j=0; zFull[i]; i++){
if( zFull[i]=='/' ){
if( zFull[i+1]=='/' ) continue;
if( zFull[i+1]=='.' && zFull[i+2]=='/' ){
i += 1;
continue;
}
if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){
while( j>0 && zFull[j-1]!='/' ){ j--; }
i += 3;
continue;
}
}
zFull[j++] = zFull[i];
}
zFull[j] = 0;
}
#endif
return zFull;
}
@ -1577,7 +1636,7 @@ static int allocateUnixFile(unixFile *pInit, OsFile **pId){
pInit->fullSync = 0;
pInit->locktype = 0;
SET_THREADID(pInit);
pNew = sqliteMalloc( sizeof(unixFile) );
pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) );
if( pNew==0 ){
close(pInit->h);
sqlite3OsEnterMutex();
@ -1656,13 +1715,42 @@ int sqlite3UnixSleep(int ms){
}
/*
** 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 +1765,34 @@ static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
*/
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 +1801,17 @@ void sqlite3UnixLeaveMutex(){
/*
** 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

Просмотреть файл

@ -1479,7 +1479,7 @@ int sqlite3_tsd_count = 0;
ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
static int key;
static int keyInit = 0;
static const ThreadData zeroData;
static const ThreadData zeroData = {0};
ThreadData *pTsd;
if( !keyInit ){

Просмотреть файл

@ -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 @@ struct Pager {
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 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){
** 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 @@ static int syncJournal(Pager *pPager){
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 @@ static int pager_open_journal(Pager *pPager){
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;

Просмотреть файл

@ -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 @@ int sqlite3pager_stmt_rollback(Pager*);
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*);

Просмотреть файл

@ -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.119 2006/02/17 12:25:16 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -128,7 +128,7 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
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 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "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 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
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;
}
@ -230,6 +227,13 @@ void sqlite3Pragma(
if( iDb<0 ) return;
pDb = &db->aDb[iDb];
/* If the temp database has been explicitly named as part of the
** pragma, make sure it is open.
*/
if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
return;
}
zLeft = sqlite3NameFromToken(pId);
if( !zLeft ) return;
if( minusFlag ){
@ -274,7 +278,7 @@ void sqlite3Pragma(
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 +396,8 @@ void sqlite3Pragma(
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 +441,6 @@ void sqlite3Pragma(
"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 +472,23 @@ void sqlite3Pragma(
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; i<pTab->nCol; i++){
for(i=0, pCol=pTab->aCol; i<pTab->nCol; 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 +503,9 @@ void sqlite3Pragma(
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; i<pIdx->nColumn; i++){
int cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
@ -523,9 +528,9 @@ void sqlite3Pragma(
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 +547,9 @@ void sqlite3Pragma(
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; i<db->nDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zName!=0 );
@ -560,8 +565,8 @@ void sqlite3Pragma(
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 +588,11 @@ void sqlite3Pragma(
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; j<pFK->nCol; j++){
@ -649,7 +654,7 @@ void sqlite3Pragma(
/* 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 +799,7 @@ void sqlite3Pragma(
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 +905,8 @@ void sqlite3Pragma(
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; i<db->nDb; i++){
Btree *pBt;
Pager *pPager;
@ -945,6 +950,17 @@ void sqlite3Pragma(
** 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.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
if( db->autoCommit ){
sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
(db->flags&SQLITE_FullFSync)!=0);
}
#endif
}
pragma_out:
sqliteFree(zLeft);

Просмотреть файл

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.3 2006-02-08 21:10:11 vladimir%pobox.com Exp $
** $Id: prepare.c,v 1.4 2006-02-22 20:47:51 brettw%gmail.com Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -556,16 +556,16 @@ int sqlite3_prepare(
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

Просмотреть файл

@ -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 @@ static void generateSortTail(
** 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 @@ static const char *columnType(NameContext *pNC, Expr *pExpr){
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;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
if( j<pTabList->nSrc ){
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 @@ static const char *columnType(NameContext *pNC, Expr *pExpr){
zType = "TEXT";
break;
}
assert( pTab );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
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 && iCol<pS->pEList->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 && iCol<pTab->nCol) );
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 @@ static void generateColumnTypes(
int i;
NameContext sNC;
sNC.pSrcList = pTabList;
sNC.pParse = pParse;
for(i=0; i<pEList->nExpr; 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 @@ static void generateColumnNames(
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 @@ static void generateColumnNames(
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 @@ static void generateColumnNames(
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 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
*/
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 @@ int sqlite3Select(
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 sqlite3Select(
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 @@ int sqlite3Select(
#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 @@ int sqlite3Select(
** 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;

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.131 2006/01/25 15:55:38 drh Exp $
** $Id: shell.c,v 1.133 2006/01/31 19:31:44 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
@ -247,7 +247,7 @@ struct callback_data {
#define MODE_Csv 7 /* Quote strings, numbers are plain */
#define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */
char *modeDescr[MODE_NUM_OF] = {
static const char *modeDescr[MODE_NUM_OF] = {
"line",
"column",
"list",
@ -1040,7 +1040,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if( zSql==0 ) return 0;
nByte = strlen(zSql);
rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0);
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
@ -1060,7 +1060,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
zSql[j++] = ')';
zSql[j] = 0;
rc = sqlite3_prepare(p->db, zSql, 0, &pStmt, 0);
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
@ -1618,7 +1618,7 @@ static void usage(int showDetail){
/*
** Initialize the state information in data
*/
void main_init(struct callback_data *data) {
static void main_init(struct callback_data *data) {
memset(data, 0, sizeof(*data));
data->mode = MODE_List;
strcpy(data->separator,"|");

Просмотреть файл

@ -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.163 2006/02/16 18:16:37 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@ -31,7 +31,7 @@ extern "C" {
#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<trailing string>", where
@ -48,7 +48,7 @@ extern "C" {
#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 @@ int sqlite3_exec(
** 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 @@ int sqlite3_exec(
#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
@ -724,6 +725,30 @@ int sqlite3_column_count(sqlite3_stmt *pStmt);
const char *sqlite3_column_name(sqlite3_stmt*,int);
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
@ -736,7 +761,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*,int);
**
** 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 @@ const char *sqlite3_column_decltype(sqlite3_stmt *, int i);
**
** 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 @@ sqlite_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
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 @@ int sqlite3_create_function16(
);
/*
** 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_text16(sqlite3_value*);
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
@ -1088,11 +1114,12 @@ void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
** These are the allowed values for the eTextRep argument to
** sqlite3_create_collation and sqlite3_create_function.
*/
#define SQLITE_UTF8 1
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16 4 /* Use native byte order */
#define SQLITE_ANY 5 /* sqlite3_create_function only */
#define SQLITE_UTF8 1
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16 4 /* Use native byte order */
#define SQLITE_ANY 5 /* sqlite3_create_function only */
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
/*
** These two functions are used to add new collation sequences to the
@ -1369,6 +1396,75 @@ void sqlite3_soft_heap_limit(int);
*/
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.

Просмотреть файл

@ -1,9 +1,58 @@
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla History System
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brett Wilson <brettw@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This file collects some internal sqlite data structures that are exported
* for use by the storage asynchronous IO system. Using all real versions of
* the internal sqlite header files became complicated because they depend
* on one another and they have a lot of extra stuff we don't care about.
*
* THESE DECLARATIONS MUST BE KEPT IN SYNC with the internal versions, so if
* you upgrade sqlite, be sure to update these.
*/
extern "C" {
struct ThreadData;
/*
/* FROM sqliteInt.h
** ----------------
** Some compilers do not support the "long long" datatype. So we have
** to do a typedef that for 64-bit integers that depends on what compiler
** is being used.
@ -16,13 +65,23 @@ struct ThreadData;
typedef unsigned long long int sqlite_uint64;
#endif
/* FROM sqliteInt.h
** ----------------
** Call this to check for out of memory errors when returning.
** See definition in util.c
*/
struct sqlite3;
int sqlite3ApiExit(sqlite3 *db, int);
/*
** Forward declarations
*/
typedef struct OsFile OsFile;
typedef struct IoMethod IoMethod;
/*
/* FROM os.h
** ---------
** An instance of the following structure contains pointers to all
** methods on an OsFile object.
*/
@ -43,7 +102,8 @@ struct IoMethod {
int (*xCheckReservedLock)(OsFile *id);
};
/*
/* FROM os.h
** ---------
** The OsFile object describes an open disk file in an OS-dependent way.
** The version of OsFile defined here is a generic version. Each OS
** implementation defines its own subclass of this structure that contains
@ -55,7 +115,8 @@ struct OsFile {
IoMethod const *pMethod;
};
/*
/* FROM os.h
** ---------
** When redefinable I/O is enabled, a single global instance of the
** following structure holds pointers to the routines that SQLite
** uses to talk with the underlying operating system. Modify this
@ -89,7 +150,9 @@ struct sqlite3OsVtbl {
int (*xAllocationSize)(void *);
};
/* Macro used to comment out routines that do not exists when there is
/* FROM os.h
** ---------
** Macro used to comment out routines that do not exists when there is
** no disk I/O
*/
#ifdef SQLITE_OMIT_DISKIO
@ -132,6 +195,10 @@ struct sqlite3OsVtbl {
#endif /* _SQLITE_OS_C_ */
/* This additional API routine is available with redefinable I/O */
/* FROM os.h
** ---------
** This additional API routine is available with redefinable I/O
*/
struct sqlite3OsVtbl *sqlite3_os_switch(void);
} // extern "C"

Просмотреть файл

@ -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.486 2006/02/17 15:01:36 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -251,12 +251,6 @@ struct BusyHandler {
#include "btree.h"
#include "pager.h"
/*
** This macro casts a pointer to an integer. Useful for doing
** pointer arithmetic.
*/
#define Addr(X) ((uptr)X)
#ifdef SQLITE_MEMDEBUG
/*
** The following global variables are used for testing and debugging
@ -267,7 +261,6 @@ extern int sqlite3_nFree; /* Number of sqliteFree() calls */
extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */
extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */
extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */
@ -276,8 +269,8 @@ extern const char *sqlite3_zFile; /* Filename to associate debug info with */
extern int sqlite3_iLine; /* Line number for debug info */
#define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__)
#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x))
#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x))
#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x,1))
#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x,1))
#define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y))
#define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x))
#define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y))
@ -285,8 +278,9 @@ extern int sqlite3_iLine; /* Line number for debug info */
#else
#define sqliteMalloc(x) sqlite3Malloc(x)
#define sqliteMallocRaw(x) sqlite3MallocRaw(x)
#define ENTER_MALLOC 0
#define sqliteMalloc(x) sqlite3Malloc(x,1)
#define sqliteMallocRaw(x) sqlite3MallocRaw(x,1)
#define sqliteRealloc(x,y) sqlite3Realloc(x,y)
#define sqliteStrDup(x) sqlite3StrDup(x)
#define sqliteStrNDup(x,y) sqlite3StrNDup(x,y)
@ -544,6 +538,7 @@ struct sqlite3 {
#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 +1064,7 @@ struct SrcList {
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 */
@ -1481,8 +1477,8 @@ int sqlite3Compare(const char *, const char *);
int sqlite3SortCompare(const char *, const char *);
void sqlite3RealToSortable(double r, char *);
void *sqlite3Malloc(int);
void *sqlite3MallocRaw(int);
void *sqlite3Malloc(int,int);
void *sqlite3MallocRaw(int,int);
void sqlite3Free(void*);
void *sqlite3Realloc(void*,int);
char *sqlite3StrDup(const char*);
@ -1748,6 +1744,7 @@ int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3MallocFailed(void);
void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3TableLock(Parse *, int, int, u8, const char *);
@ -1765,6 +1762,14 @@ void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
#define sqlite3MallocAllow()
#endif
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
void *sqlite3ThreadSafeMalloc(int);
void sqlite3ThreadSafeFree(void *);
#else
#define sqlite3ThreadSafeMalloc sqlite3MallocX
#define sqlite3ThreadSafeFree sqlite3FreeX
#endif
#ifdef SQLITE_SSE
#include "sseInt.h"
#endif

Просмотреть файл

@ -1,199 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the sqlite3_get_table() and sqlite3_free_table()
** interface routines. These are just wrappers around the main
** interface routine of sqlite3_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>
#ifndef SQLITE_OMIT_GET_TABLE
/*
** This structure is used to pass data from sqlite3_get_table() through
** to the callback function is uses to build the result.
*/
typedef struct TabResult {
char **azResult;
char *zErrMsg;
int nResult;
int nAlloc;
int nRow;
int nColumn;
int nData;
int rc;
} TabResult;
/*
** This routine is called once for each row in the result table. Its job
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.
*/
static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
TabResult *p = (TabResult*)pArg;
int need;
int i;
char *z;
/* Make sure there is enough space in p->azResult to hold everything
** we need to remember from this invocation of the callback.
*/
if( p->nRow==0 && argv!=0 ){
need = nCol*2;
}else{
need = nCol;
}
if( p->nData + need >= p->nAlloc ){
char **azNew;
p->nAlloc = p->nAlloc*2 + need + 1;
azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
}
/* If this is the first row, then generate an extra row containing
** the names of all columns.
*/
if( p->nRow==0 ){
p->nColumn = nCol;
for(i=0; i<nCol; i++){
if( colv[i]==0 ){
z = 0;
}else{
z = malloc( strlen(colv[i])+1 );
if( z==0 ) goto malloc_failed;
strcpy(z, colv[i]);
}
p->azResult[p->nData++] = z;
}
}else if( p->nColumn!=nCol ){
sqlite3SetString(&p->zErrMsg,
"sqlite3_get_table() called with two or more incompatible queries",
(char*)0);
p->rc = SQLITE_ERROR;
return 1;
}
/* Copy over the row data
*/
if( argv!=0 ){
for(i=0; i<nCol; i++){
if( argv[i]==0 ){
z = 0;
}else{
z = malloc( strlen(argv[i])+1 );
if( z==0 ) goto malloc_failed;
strcpy(z, argv[i]);
}
p->azResult[p->nData++] = z;
}
p->nRow++;
}
return 0;
malloc_failed:
p->rc = SQLITE_NOMEM;
return 1;
}
/*
** Query the database. But instead of invoking a callback for each row,
** malloc() for space to hold the result and return the entire results
** at the conclusion of the call.
**
** The result that is written to ***pazResult is held in memory obtained
** from malloc(). But the caller cannot free this memory directly.
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
int sqlite3_get_table(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
char ***pazResult, /* Write the result table here */
int *pnRow, /* Write the number of rows in the result here */
int *pnColumn, /* Write the number of columns of result here */
char **pzErrMsg /* Write error messages here */
){
int rc;
TabResult res;
if( pazResult==0 ){ return SQLITE_ERROR; }
*pazResult = 0;
if( pnColumn ) *pnColumn = 0;
if( pnRow ) *pnRow = 0;
res.zErrMsg = 0;
res.nResult = 0;
res.nRow = 0;
res.nColumn = 0;
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
res.azResult = malloc( sizeof(char*)*res.nAlloc );
if( res.azResult==0 ) return SQLITE_NOMEM;
res.azResult[0] = 0;
rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
if( res.azResult ){
res.azResult[0] = (char*)res.nData;
}
if( rc==SQLITE_ABORT ){
sqlite3_free_table(&res.azResult[1]);
if( res.zErrMsg ){
if( pzErrMsg ){
free(*pzErrMsg);
*pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
}
sqliteFree(res.zErrMsg);
}
db->errCode = res.rc;
return res.rc;
}
sqliteFree(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite3_free_table(&res.azResult[1]);
return rc;
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
return SQLITE_NOMEM;
}
res.nAlloc = res.nData+1;
res.azResult = azNew;
}
*pazResult = &res.azResult[1];
if( pnColumn ) *pnColumn = res.nColumn;
if( pnRow ) *pnRow = res.nRow;
return rc;
}
/*
** This routine frees the space the sqlite3_get_table() malloced.
*/
void sqlite3_free_table(
char **azResult /* Result returned from from sqlite3_get_table() */
){
if( azResult ){
int i, n;
azResult--;
if( azResult==0 ) return;
n = (int)azResult[0];
for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
free(azResult);
}
}
#endif /* SQLITE_OMIT_GET_TABLE */

Просмотреть файл

@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.150 2006/01/23 13:00:38 drh Exp $
** $Id: tclsqlite.c,v 1.151 2006/02/10 02:27:43 danielk1977 Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -1116,7 +1116,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( i+1!=nCol ){
char *zErr;
zErr = malloc(200 + strlen(zFile));
sprintf(zErr,"Error: %s line %d: expected %d columns of data but found %d",
sprintf(zErr,
"Error: %s line %d: expected %d columns of data but found %d",
zFile, lineno, nCol, i+1);
Tcl_AppendResult(interp, zErr, 0);
free(zErr);

Просмотреть файл

Просмотреть файл

@ -0,0 +1,485 @@
/*
** 2006 January 07
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains demonstration code. Nothing in this file gets compiled
** or linked into the SQLite library unless you use a non-standard option:
**
** -DSQLITE_SERVER=1
**
** The configure script will never generate a Makefile with the option
** above. You will need to manually modify the Makefile if you want to
** include any of the code from this file in your project. Or, at your
** option, you may copy and paste the code from this file and
** thereby avoiding a recompile of SQLite.
**
**
** This source file demonstrates how to use SQLite to create an SQL database
** server thread in a multiple-threaded program. One or more client threads
** send messages to the server thread and the server thread processes those
** messages in the order received and returns the results to the client.
**
** One might ask: "Why bother? Why not just let each thread connect
** to the database directly?" There are a several of reasons to
** prefer the client/server approach.
**
** (1) Some systems (ex: Redhat9) have broken threading implementations
** that prevent SQLite database connections from being used in
** a thread different from the one where they were created. With
** the client/server approach, all database connections are created
** and used within the server thread. Client calls to the database
** can be made from multiple threads (though not at the same time!)
**
** (2) Beginning with SQLite version 3.3.0, when two or more
** connections to the same database occur within the same thread,
** they can optionally share their database cache. This reduces
** I/O and memory requirements. Cache shared is controlled using
** the sqlite3_enable_shared_cache() API.
**
** (3) Database connections on a shared cache use table-level locking
** instead of file-level locking for improved concurrency.
**
** (4) Database connections on a shared cache can by optionally
** set to READ UNCOMMITTED isolation. (The default isolation for
** SQLite is SERIALIZABLE.) When this occurs, readers will
** never be blocked by a writer and writers will not be
** blocked by readers. There can still only be a single writer
** at a time, but multiple readers can simultaneously exist with
** that writer. This is a huge increase in concurrency.
**
** To summarize the rational for using a client/server approach: prior
** to SQLite version 3.3.0 it probably was not worth the trouble. But
** with SQLite version 3.3.0 and beyond you can get significant performance
** and concurrency improvements and memory usage reductions by going
** client/server.
**
** Note: The extra features of version 3.3.0 described by points (2)
** through (4) above are only available if you compile without the
** option -DSQLITE_OMIT_SHARED_CACHE.
**
** Here is how the client/server approach works: The database server
** thread is started on this procedure:
**
** void *sqlite3_server(void *NotUsed);
**
** The sqlite_server procedure runs as long as the g.serverHalt variable
** is false. A mutex is used to make sure no more than one server runs
** at a time. The server waits for messages to arrive on a message
** queue and processes the messages in order.
**
** Two convenience routines are provided for starting and stopping the
** server thread:
**
** void sqlite3_server_start(void);
** void sqlite3_server_stop(void);
**
** Both of the convenience routines return immediately. Neither will
** ever give an error. If a server is already started or already halted,
** then the routines are effectively no-ops.
**
** Clients use the following interfaces:
**
** sqlite3_client_open
** sqlite3_client_prepare
** sqlite3_client_step
** sqlite3_client_reset
** sqlite3_client_finalize
** sqlite3_client_close
**
** These interfaces work exactly like the standard core SQLite interfaces
** having the same names without the "_client_" infix. Many other SQLite
** interfaces can be used directly without having to send messages to the
** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined.
** The following interfaces fall into this second category:
**
** sqlite3_bind_*
** sqlite3_changes
** sqlite3_clear_bindings
** sqlite3_column_*
** sqlite3_complete
** sqlite3_create_collation
** sqlite3_create_function
** sqlite3_data_count
** sqlite3_db_handle
** sqlite3_errcode
** sqlite3_errmsg
** sqlite3_last_insert_rowid
** sqlite3_total_changes
** sqlite3_transfer_bindings
**
** A single SQLite connection (an sqlite3* object) or an SQLite statement
** (an sqlite3_stmt* object) should only be passed to a single interface
** function at a time. The connections and statements can be passed from
** any thread to any of the functions listed in the second group above as
** long as the same connection is not in use by two threads at once and
** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional
** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is
** below.
**
** The busy handler for all database connections should remain turned
** off. That means that any lock contention will cause the associated
** sqlite3_client_step() call to return immediately with an SQLITE_BUSY
** error code. If a busy handler is enabled and lock contention occurs,
** then the entire server thread will block. This will cause not only
** the requesting client to block but every other database client as
** well. It is possible to enhance the code below so that lock
** contention will cause the message to be placed back on the top of
** the queue to be tried again later. But such enhanced processing is
** not included here, in order to keep the example simple.
**
** This example code assumes the use of pthreads. Pthreads
** implementations are available for windows. (See, for example
** http://sourceware.org/pthreads-win32/announcement.html.) Or, you
** can translate the locking and thread synchronization code to use
** windows primitives easily enough. The details are left as an
** exercise to the reader.
**
**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT ****
**
** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then
** SQLite includes code that tracks how much memory is being used by
** each thread. These memory counts can become confused if memory
** is allocated by one thread and then freed by another. For that
** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations
** that might allocate or free memory should be performanced in the same
** thread that originally created the database connection. In that case,
** many of the operations that are listed above as safe to be performed
** in separate threads would need to be sent over to the server to be
** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then
** the following functions can be used safely from different threads
** without messing up the allocation counts:
**
** sqlite3_bind_parameter_name
** sqlite3_bind_parameter_index
** sqlite3_changes
** sqlite3_column_blob
** sqlite3_column_count
** sqlite3_complete
** sqlite3_data_count
** sqlite3_db_handle
** sqlite3_errcode
** sqlite3_errmsg
** sqlite3_last_insert_rowid
** sqlite3_total_changes
**
** The remaining functions are not thread-safe when memory management
** is enabled. So one would have to define some new interface routines
** along the following lines:
**
** sqlite3_client_bind_*
** sqlite3_client_clear_bindings
** sqlite3_client_column_*
** sqlite3_client_create_collation
** sqlite3_client_create_function
** sqlite3_client_transfer_bindings
**
** The example code in this file is intended for use with memory
** management turned off. So the implementation of these additional
** client interfaces is left as an exercise to the reader.
**
** It may seem surprising to the reader that the list of safe functions
** above does not include things like sqlite3_bind_int() or
** sqlite3_column_int(). But those routines might, in fact, allocate
** or deallocate memory. In the case of sqlite3_bind_int(), if the
** parameter was previously bound to a string that string might need
** to be deallocated before the new integer value is inserted. In
** the case of sqlite3_column_int(), the value of the column might be
** a UTF-16 string which will need to be converted to UTF-8 then into
** an integer.
*/
/*
** Only compile the code in this file on UNIX with a THREADSAFE build
** and only if the SQLITE_SERVER macro is defined.
*/
#ifdef SQLITE_SERVER
#if defined(OS_UNIX) && OS_UNIX && defined(THREADSAFE) && THREADSAFE
/*
** We require only pthreads and the public interface of SQLite.
*/
#include <pthread.h>
#include "sqlite3.h"
/*
** Messages are passed from client to server and back again as
** instances of the following structure.
*/
typedef struct SqlMessage SqlMessage;
struct SqlMessage {
int op; /* Opcode for the message */
sqlite3 *pDb; /* The SQLite connection */
sqlite3_stmt *pStmt; /* A specific statement */
int errCode; /* Error code returned */
const char *zIn; /* Input filename or SQL statement */
int nByte; /* Size of the zIn parameter for prepare() */
const char *zOut; /* Tail of the SQL statement */
SqlMessage *pNext; /* Next message in the queue */
SqlMessage *pPrev; /* Previous message in the queue */
pthread_mutex_t clientMutex; /* Hold this mutex to access the message */
pthread_cond_t clientWakeup; /* Signal to wake up the client */
};
/*
** Legal values for SqlMessage.op
*/
#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */
#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */
#define MSG_Step 3 /* sqlite3_step(pStmt) */
#define MSG_Reset 4 /* sqlite3_reset(pStmt) */
#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */
#define MSG_Close 6 /* sqlite3_close(pDb) */
#define MSG_Done 7 /* Server has finished with this message */
/*
** State information about the server is stored in a static variable
** named "g" as follows:
*/
static struct ServerState {
pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */
pthread_mutex_t serverMutex; /* Held by the server while it is running */
pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */
volatile int serverHalt; /* Server halts itself when true */
SqlMessage *pQueueHead; /* Head of the message queue */
SqlMessage *pQueueTail; /* Tail of the message queue */
} g = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_COND_INITIALIZER,
};
/*
** Send a message to the server. Block until we get a reply.
**
** The mutex and condition variable in the message are uninitialized
** when this routine is called. This routine takes care of
** initializing them and destroying them when it has finished.
*/
static void sendToServer(SqlMessage *pMsg){
/* Initialize the mutex and condition variable on the message
*/
pthread_mutex_init(&pMsg->clientMutex, 0);
pthread_cond_init(&pMsg->clientWakeup, 0);
/* Add the message to the head of the server's message queue.
*/
pthread_mutex_lock(&g.queueMutex);
pMsg->pNext = g.pQueueHead;
if( g.pQueueHead==0 ){
g.pQueueTail = pMsg;
}else{
g.pQueueHead->pPrev = pMsg;
}
pMsg->pPrev = 0;
g.pQueueHead = pMsg;
pthread_mutex_unlock(&g.queueMutex);
/* Signal the server that the new message has be queued, then
** block waiting for the server to process the message.
*/
pthread_mutex_lock(&pMsg->clientMutex);
pthread_cond_signal(&g.serverWakeup);
while( pMsg->op!=MSG_Done ){
pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex);
}
pthread_mutex_unlock(&pMsg->clientMutex);
/* Destroy the mutex and condition variable of the message.
*/
pthread_mutex_destroy(&pMsg->clientMutex);
pthread_cond_destroy(&pMsg->clientWakeup);
}
/*
** The following 6 routines are client-side implementations of the
** core SQLite interfaces:
**
** sqlite3_open
** sqlite3_prepare
** sqlite3_step
** sqlite3_reset
** sqlite3_finalize
** sqlite3_close
**
** Clients should use the following client-side routines instead of
** the core routines above.
**
** sqlite3_client_open
** sqlite3_client_prepare
** sqlite3_client_step
** sqlite3_client_reset
** sqlite3_client_finalize
** sqlite3_client_close
**
** Each of these routines creates a message for the desired operation,
** sends that message to the server, waits for the server to process
** then message and return a response.
*/
int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){
SqlMessage msg;
msg.op = MSG_Open;
msg.zIn = zDatabaseName;
sendToServer(&msg);
*ppDb = msg.pDb;
return msg.errCode;
}
int sqlite3_client_prepare(
sqlite3 *pDb,
const char *zSql,
int nByte,
sqlite3_stmt **ppStmt,
const char **pzTail
){
SqlMessage msg;
msg.op = MSG_Prepare;
msg.pDb = pDb;
msg.zIn = zSql;
msg.nByte = nByte;
sendToServer(&msg);
*ppStmt = msg.pStmt;
if( pzTail ) *pzTail = msg.zOut;
return msg.errCode;
}
int sqlite3_client_step(sqlite3_stmt *pStmt){
SqlMessage msg;
msg.op = MSG_Step;
msg.pStmt = pStmt;
sendToServer(&msg);
return msg.errCode;
}
int sqlite3_client_reset(sqlite3_stmt *pStmt){
SqlMessage msg;
msg.op = MSG_Reset;
msg.pStmt = pStmt;
sendToServer(&msg);
return msg.errCode;
}
int sqlite3_client_finalize(sqlite3_stmt *pStmt){
SqlMessage msg;
msg.op = MSG_Finalize;
msg.pStmt = pStmt;
sendToServer(&msg);
return msg.errCode;
}
int sqlite3_client_close(sqlite3 *pDb){
SqlMessage msg;
msg.op = MSG_Close;
msg.pDb = pDb;
sendToServer(&msg);
return msg.errCode;
}
/*
** This routine implements the server. To start the server, first
** make sure g.serverHalt is false, then create a new detached thread
** on this procedure. See the sqlite3_server_start() routine below
** for an example. This procedure loops until g.serverHalt becomes
** true.
*/
void *sqlite3_server(void *NotUsed){
sqlite3_enable_shared_cache(1);
if( pthread_mutex_trylock(&g.serverMutex) ){
sqlite3_enable_shared_cache(0);
return 0; /* Another server is already running */
}
while( !g.serverHalt ){
SqlMessage *pMsg;
/* Remove the last message from the message queue.
*/
pthread_mutex_lock(&g.queueMutex);
while( g.pQueueTail==0 && g.serverHalt==0 ){
pthread_cond_wait(&g.serverWakeup, &g.queueMutex);
}
pMsg = g.pQueueTail;
if( pMsg ){
if( pMsg->pPrev ){
pMsg->pPrev->pNext = 0;
}else{
g.pQueueHead = 0;
}
g.pQueueTail = pMsg->pPrev;
}
pthread_mutex_unlock(&g.queueMutex);
if( pMsg==0 ) break;
/* Process the message just removed
*/
pthread_mutex_lock(&pMsg->clientMutex);
switch( pMsg->op ){
case MSG_Open: {
pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb);
break;
}
case MSG_Prepare: {
pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte,
&pMsg->pStmt, &pMsg->zOut);
break;
}
case MSG_Step: {
pMsg->errCode = sqlite3_step(pMsg->pStmt);
break;
}
case MSG_Reset: {
pMsg->errCode = sqlite3_reset(pMsg->pStmt);
break;
}
case MSG_Finalize: {
pMsg->errCode = sqlite3_finalize(pMsg->pStmt);
break;
}
case MSG_Close: {
pMsg->errCode = sqlite3_close(pMsg->pDb);
break;
}
}
/* Signal the client that the message has been processed.
*/
pMsg->op = MSG_Done;
pthread_mutex_unlock(&pMsg->clientMutex);
pthread_cond_signal(&pMsg->clientWakeup);
}
pthread_mutex_unlock(&g.serverMutex);
sqlite3_thread_cleanup();
return 0;
}
/*
** Start a server thread if one is not already running. If there
** is aleady a server thread running, the new thread will quickly
** die and this routine is effectively a no-op.
*/
void sqlite3_server_start(void){
pthread_t x;
int rc;
g.serverHalt = 0;
rc = pthread_create(&x, 0, sqlite3_server, 0);
if( rc==0 ){
pthread_detach(x);
}
}
/*
** If a server thread is running, then stop it. If no server is
** running, this routine is effectively a no-op.
**
** This routine returns immediately without waiting for the server
** thread to stop. But be assured that the server will eventually stop.
*/
void sqlite3_server_stop(void){
g.serverHalt = 1;
pthread_cond_broadcast(&g.serverWakeup);
}
#endif /* defined(OS_UNIX) && OS_UNIX && defined(THREADSAFE) && THREADSAFE */
#endif /* defined(SQLITE_SERVER) */

Просмотреть файл

@ -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 @@ static int getToken(const unsigned char *z, int *tokenType){
#ifndef SQLITE_OMIT_TCL_VARIABLE
case '$':
#endif
case '@': /* For compatibility with MS SQL Server */
case ':': {
int n = 0;
*tokenType = TK_VARIABLE;

Просмотреть файл

@ -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 @@ void sqlite3Update(
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:

Просмотреть файл

@ -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.185 2006/02/14 10:48:39 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -443,6 +443,7 @@ int sqlite3OutstandingMallocs(Tcl_Interp *interp){
** This is the test layer's wrapper around sqlite3OsMalloc().
*/
static void * OSMALLOC(int n){
sqlite3OsEnterMutex();
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
sqlite3_nMaxAlloc =
MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
@ -455,8 +456,10 @@ static void * OSMALLOC(int n){
sqlite3_nMalloc++;
applyGuards(p);
linkAlloc(p);
sqlite3OsLeaveMutex();
return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
}
sqlite3OsLeaveMutex();
return 0;
}
@ -473,12 +476,14 @@ static int OSSIZEOF(void *p){
** pointer to the space allocated for the application to use.
*/
static void OSFREE(void *pFree){
sqlite3OsEnterMutex();
u32 *p = (u32 *)getOsPointer(pFree); /* p points to Os level allocation */
checkGuards(p);
unlinkAlloc(p);
memset(pFree, 0x55, OSSIZEOF(pFree));
sqlite3OsFree(p);
sqlite3_nFree++;
sqlite3OsLeaveMutex();
}
/*
@ -521,34 +526,56 @@ static void OSMALLOC_FAILED(){
**--------------------------------------------------------------------------*/
/*
** 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
/*
@ -556,19 +583,15 @@ static int handleSoftLimit(int n){
** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory
** by calling sqlite3_release_memory().
*/
void *sqlite3MallocRaw(int n){
void *sqlite3MallocRaw(int n, int doMemManage){
void *p = 0;
if( n>0 && !sqlite3MallocFailed() && !handleSoftLimit(n) ){
if( n>0 && !sqlite3MallocFailed() && (!doMemManage || 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 if( doMemManage ){
updateMemoryUsedCount(OSSIZEOF(p));
}
}
return p;
@ -585,20 +608,19 @@ void *sqlite3Realloc(void *p, int n){
}
if( !p ){
return sqlite3Malloc(n);
return sqlite3Malloc(n, 1);
}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 +632,8 @@ void *sqlite3Realloc(void *p, int n){
** 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);
}
}
@ -631,8 +653,8 @@ void *sqlite3MallocX(int n){
** These two are implemented as wrappers around sqlite3MallocRaw(),
** sqlite3Realloc() and sqlite3Free().
*/
void *sqlite3Malloc(int n){
void *p = sqlite3MallocRaw(n);
void *sqlite3Malloc(int n, int doMemManage){
void *p = sqlite3MallocRaw(n, doMemManage);
if( p ){
memset(p, 0, n);
}
@ -646,6 +668,33 @@ void sqlite3ReallocOrFree(void **pp, int n){
*pp = p;
}
/*
** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those
** rare scenarios where sqlite may allocate memory in one thread and free
** it in another. They are exactly the same as sqlite3Malloc() and
** sqlite3Free() except that:
**
** * The allocated memory is not included in any calculations with
** respect to the soft-heap-limit, and
**
** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(),
** not sqlite3Free(). Calling sqlite3Free() on memory obtained from
** ThreadSafeMalloc() will cause an error somewhere down the line.
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
void *sqlite3ThreadSafeMalloc(int n){
ENTER_MALLOC;
return sqlite3Malloc(n, 0);
}
void sqlite3ThreadSafeFree(void *p){
ENTER_MALLOC;
if( p ){
OSFREE(p);
}
}
#endif
/*
** Return the number of bytes allocated at location p. p must be either
** a NULL pointer (in which case 0 is returned) or a pointer returned by
@ -672,14 +721,14 @@ int sqlite3AllocSize(void *p){
char *sqlite3StrDup(const char *z){
char *zNew;
if( z==0 ) return 0;
zNew = sqlite3MallocRaw(strlen(z)+1);
zNew = sqlite3MallocRaw(strlen(z)+1, 1);
if( zNew ) strcpy(zNew, z);
return zNew;
}
char *sqlite3StrNDup(const char *z, int n){
char *zNew;
if( z==0 ) return 0;
zNew = sqlite3MallocRaw(n+1);
zNew = sqlite3MallocRaw(n+1, 1);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;

Просмотреть файл

@ -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"
@ -189,6 +189,31 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
return pCx;
}
/*
** 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:
**
@ -220,31 +245,28 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
}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 @@ case OP_Column: {
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 @@ case OP_Column: {
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 @@ case OP_Column: {
}
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 @@ case OP_IdxGE: { /* no-push */
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);

Просмотреть файл

@ -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 @@ typedef struct VdbeOpList VdbeOpList;
#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
@ -79,6 +80,17 @@ typedef struct VdbeOpList VdbeOpList;
*/
#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
@ -117,7 +129,7 @@ void sqlite3VdbeTrace(Vdbe*,FILE*);
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*);

Просмотреть файл

@ -74,6 +74,7 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){
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 @@ void sqlite3_set_auxdata(
** 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 @@ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
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 @@ static const void *columnName(
** 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 @@ const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
** 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 @@ const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
** 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,16 +585,16 @@ const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
** 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_ ***************************
@ -800,12 +817,12 @@ int sqlite3_bind_parameter_indexes(
}
*pIndexes = indexes;
return nVars;
}
}
void sqlite3_free_parameter_indexes(int *pIndexes)
{
{
sqliteFree( pIndexes );
}
}
/*
** Transfer all bindings from the first statement over to the second.

Просмотреть файл

@ -871,9 +871,9 @@ static void Cleanup(Vdbe *p){
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 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
** 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( idx<p->nResColumn );
assert( var<COLNAME_N );
if( sqlite3MallocFailed() ) return SQLITE_NOMEM;
assert( p->aColName!=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 @@ void sqlite3VdbeDelete(Vdbe *p){
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);

Просмотреть файл

@ -42,6 +42,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
return SQLITE_ERROR;
#else
/* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
** then the encoding of the value may not have changed.
*/
@ -118,6 +119,7 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
z[n+1] = 0;
pMem->z = (char*)z;
pMem->flags &= ~(MEM_Ephem|MEM_Static);
assert(0==(1&(int)pMem->z));
return SQLITE_OK;
}
@ -596,19 +598,25 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
if( pColl ){
if( pMem1->enc==pColl->enc ){
/* The strings are already in the correct encoding. Call the
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
u8 origEnc = pMem1->enc;
rc = pColl->xCmp(
pColl->pUser,
sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc),
sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc),
sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc),
sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc)
);
sqlite3ValueBytes((sqlite3_value*)pMem1, origEnc);
const void *v1, *v2;
int n1, n2;
/* Convert the strings into the encoding that the comparison
** function expects */
v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
n1 = v1==0 ? 0 : pMem1->n;
assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);
n2 = v2==0 ? 0 : pMem2->n;
assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
/* Do the comparison */
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
/* Convert the strings back into the database encoding */
sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
sqlite3ValueBytes((sqlite3_value*)pMem2, origEnc);
sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
return rc;
}
@ -752,10 +760,14 @@ void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){
** except the data returned is in the encoding specified by the second
** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
** SQLITE_UTF8.
**
** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
** If that is the case, then the result must be aligned on an even byte
** boundary.
*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
if( !pVal ) return 0;
assert( enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE || enc==SQLITE_UTF8);
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
if( pVal->flags&MEM_Null ){
return 0;
@ -763,12 +775,23 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
assert( (MEM_Blob>>3) == MEM_Str );
pVal->flags |= (pVal->flags & MEM_Blob)>>3;
if( pVal->flags&MEM_Str ){
sqlite3VdbeChangeEncoding(pVal, enc);
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){
assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
return 0;
}
}
}else if( !(pVal->flags&MEM_Blob) ){
sqlite3VdbeMemStringify(pVal, enc);
assert( 0==(1&(int)pVal->z) );
}
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || sqlite3MallocFailed() );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
return pVal->z;
}else{
return 0;
}
assert(pVal->enc==enc || sqlite3MallocFailed() );
return (const void *)(pVal->enc==enc ? (pVal->z) : 0);
}
/*

Просмотреть файл

@ -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 @@ WhereInfo *sqlite3WhereBegin(
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]; j<pTabList->nSrc; 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 @@ WhereInfo *sqlite3WhereBegin(
(i==0 && ppOrderBy) ? *ppOrderBy : 0,
&pIdx, &flags, &nEq);
if( cost<lowestCost ){
once = 1;
lowestCost = cost;
pBest = pIdx;
bestFlags = flags;
bestNEq = nEq;
bestJ = j;
}
if( (pTabItem->jointype & (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));