c:\harbour\contrib\hbsqlit2
attach.c |
Type | Function | Source | Line |
VOID | sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey)
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
Db *aNew;
int rc, i;
char *zFile, *zName;
sqlite *db;
Vdbe *v;
v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
if( db->file_format<4 ){
sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
"older format master database", 0);
pParse->rc = SQLITE_ERROR;
return;
}
if( db->nDb>=MAX_ATTACHED+2 ){
sqliteErrorMsg(pParse, "too many attached databases - max %d",
MAX_ATTACHED);
pParse->rc = SQLITE_ERROR;
return;
}
zFile = 0;
sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
if( zFile==0 ) return;
sqliteDequote(zFile);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
sqliteFree(zFile);
return;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
zName = 0;
sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
if( zName==0 ) return;
sqliteDequote(zName);
for(i=0; inDb; i++){
if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
sqliteErrorMsg(pParse, "database %z is already in use", zName);
pParse->rc = SQLITE_ERROR;
sqliteFree(zFile);
return;
}
}
if( db->aDb==db->aDbStatic ){
aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
if( aNew==0 ) return;
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
}else{
aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
if( aNew==0 ) return;
}
db->aDb = aNew;
aNew = &db->aDb[db->nDb++];
memset(aNew, 0, sizeof(*aNew));
sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
aNew->zName = zName;
rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
if( rc ){
sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
}
#if SQLITE_HAS_CODEC
{
extern int sqliteCodecAttach(sqlite*, int, void*, int);
char *zKey = 0;
int nKey;
if( pKey && pKey->z && pKey->n ){
sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
sqliteDequote(zKey);
nKey = strlen(zKey);
}else{
zKey = 0;
nKey = 0;
}
sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
}
#endif
sqliteFree(zFile);
db->flags &= ~SQLITE_Initialized;
if( pParse->nErr ) return;
if( rc==SQLITE_OK ){
rc = sqliteInit(pParse->db, &pParse->zErrMsg);
}
if( rc ){
int i = db->nDb - 1;
assert( i>=2 );
if( db->aDb[i].pBt ){
sqliteBtreeClose(db->aDb[i].pBt);
db->aDb[i].pBt = 0;
}
sqliteResetInternalSchema(db, 0);
pParse->nErr++;
pParse->rc = SQLITE_ERROR;
}
}
| attach.c | 18 |
VOID | sqliteDetach(Parse *pParse, Token *pDbname)
void sqliteDetach(Parse *pParse, Token *pDbname){
int i;
sqlite *db;
Vdbe *v;
Db *pDb;
v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
for(i=0; inDb; i++){
pDb = &db->aDb[i];
if( pDb->pBt==0 || pDb->zName==0 ) continue;
if( strlen(pDb->zName)!=pDbname->n ) continue;
if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
}
if( i>=db->nDb ){
sqliteErrorMsg(pParse, "no such database: %T", pDbname);
return;
}
if( i<2 ){
sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
return;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
return;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
sqliteBtreeClose(pDb->pBt);
pDb->pBt = 0;
sqliteFree(pDb->zName);
sqliteResetInternalSchema(db, i);
if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
db->nDb--;
if( inDb ){
db->aDb[i] = db->aDb[db->nDb];
memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
sqliteResetInternalSchema(db, i);
}
}
| attach.c | 129 |
INT | sqliteFixInit( DbFixer *pFix, Parse *pParse, int iDb, const char *zType, const Token *pName )
int sqliteFixInit(
DbFixer *pFix, /* The fixer to be initialized */
Parse *pParse, /* Error messages will be written here */
int iDb, /* This is the database that must must be used */
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
sqlite *db;
if( iDb<0 || iDb==1 ) return 0;
db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zName;
pFix->zType = zType;
pFix->pName = pName;
return 1;
}
| attach.c | 178 |
INT | sqliteFixSrcList( DbFixer *pFix, SrcList *pList )
int sqliteFixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
int i;
const char *zDb;
if( pList==0 ) return 0;
zDb = pFix->zDb;
for(i=0; inSrc; i++){
if( pList->a[i].zDatabase==0 ){
pList->a[i].zDatabase = sqliteStrDup(zDb);
}else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
sqliteErrorMsg(pFix->pParse,
"%s %z cannot reference objects in database %s",
pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
pList->a[i].zDatabase);
return 1;
}
if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
}
return 0;
}
| attach.c | 204 |
INT | sqliteFixSelect( DbFixer *pFix, Select *pSelect )
int sqliteFixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
while( pSelect ){
if( sqliteFixExprList(pFix, pSelect->pEList) ){
return 1;
}
if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
return 1;
}
if( sqliteFixExpr(pFix, pSelect->pWhere) ){
return 1;
}
if( sqliteFixExpr(pFix, pSelect->pHaving) ){
return 1;
}
pSelect = pSelect->pPrior;
}
return 0;
}
| attach.c | 242 |
INT | sqliteFixExpr( DbFixer *pFix, Expr *pExpr )
int sqliteFixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( sqliteFixSelect(pFix, pExpr->pSelect) ){
return 1;
}
if( sqliteFixExprList(pFix, pExpr->pList) ){
return 1;
}
if( sqliteFixExpr(pFix, pExpr->pRight) ){
return 1;
}
pExpr = pExpr->pLeft;
}
return 0;
}
| attach.c | 263 |
INT | sqliteFixExprList( DbFixer *pFix, ExprList *pList )
int sqliteFixExprList(
DbFixer *pFix, /* Context of the fixation */
ExprList *pList /* The expression to be fixed to one database */
){
int i;
if( pList==0 ) return 0;
for(i=0; inExpr; i++){
if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
return 1;
}
}
return 0;
}
| attach.c | 281 |
INT | sqliteFixTriggerStep( DbFixer *pFix, TriggerStep *pStep )
int sqliteFixTriggerStep(
DbFixer *pFix, /* Context of the fixation */
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
if( sqliteFixSelect(pFix, pStep->pSelect) ){
return 1;
}
if( sqliteFixExpr(pFix, pStep->pWhere) ){
return 1;
}
if( sqliteFixExprList(pFix, pStep->pExprList) ){
return 1;
}
pStep = pStep->pNext;
}
return 0;
}
| attach.c | 294 |
auth.c |
Type | Function | Source | Line |
INT SQLITE_SET_AUTHORIZER( SQLITE *DB, INT (*XAUTH | (void*,int,const char*,const char*,const char*,const char*), void *pArg )
int sqlite_set_authorizer(
sqlite *db,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
db->xAuth = xAuth;
db->pAuthArg = pArg;
return SQLITE_OK;
}
| auth.c | 27 |
STATIC VOID | sqliteAuthBadReturnCode(Parse *pParse, int rc)
static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
sqliteErrorMsg(pParse, "illegal return value (%d) from the "
"authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
"or SQLITE_DENY", rc);
pParse->rc = SQLITE_MISUSE;
}
| auth.c | 83 |
VOID | sqliteAuthRead( Parse *pParse, Expr *pExpr, SrcList *pTabList )
void sqliteAuthRead(
Parse *pParse, /* The parser context */
Expr *pExpr, /* The expression to check authorization on */
SrcList *pTabList /* All table that pExpr might refer to */
){
sqlite *db = pParse->db;
int rc;
Table *pTab; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
const char *zDBase; /* Name of database being accessed */
TriggerStack *pStack; /* The stack of current triggers */
if( db->xAuth==0 ) return;
assert( pExpr->op==TK_COLUMN );
for(iSrc=0; iSrcnSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
}
if( iSrc>=0 && iSrcnSrc ){
pTab = pTabList->a[iSrc].pTab;
}else if( (pStack = pParse->trigStack)!=0 ){
/* This must be an attempt to read the NEW or OLD pseudo-tables
** of a trigger.
*/
assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
pTab = pStack->pTab;
}else{
return;
}
if( pTab==0 ) return;
if( pExpr->iColumn>=0 ){
assert( pExpr->iColumnnCol );
zCol = pTab->aCol[pExpr->iColumn].zName;
}else if( pTab->iPKey>=0 ){
assert( pTab->iPKeynCol );
zCol = pTab->aCol[pTab->iPKey].zName;
}else{
zCol = "ROWID";
}
assert( pExpr->iDbnDb );
zDBase = db->aDb[pExpr->iDb].zName;
rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase,
pParse->zAuthContext);
if( rc==SQLITE_IGNORE ){
pExpr->op = TK_NULL;
}else if( rc==SQLITE_DENY ){
if( db->nDb>2 || pExpr->iDb!=0 ){
sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited",
zDBase, pTab->zName, zCol);
}else{
sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol);
}
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK ){
sqliteAuthBadReturnCode(pParse, rc);
}
}
| auth.c | 94 |
INT | sqliteAuthCheck( Parse *pParse, int code, const char *zArg1, const char *zArg2, const char *zArg3 )
int sqliteAuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3
){
sqlite *db = pParse->db;
int rc;
if( db->init.busy || db->xAuth==0 ){
return SQLITE_OK;
}
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
if( rc==SQLITE_DENY ){
sqliteErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
sqliteAuthBadReturnCode(pParse, rc);
}
return rc;
}
| auth.c | 161 |
VOID | sqliteAuthContextPush( Parse *pParse, AuthContext *pContext, const char *zContext )
void sqliteAuthContextPush(
Parse *pParse,
AuthContext *pContext,
const char *zContext
){
pContext->pParse = pParse;
if( pParse ){
pContext->zAuthContext = pParse->zAuthContext;
pParse->zAuthContext = zContext;
}
}
| auth.c | 191 |
VOID | sqliteAuthContextPop(AuthContext *pContext)
void sqliteAuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;
}
}
| auth.c | 208 |
btree.c |
Type | Function | Source | Line |
U16 | swab16(u16 x)
u16 swab16(u16 x){
return ((x & 0xff)<<8) | ((x>>8)&0xff);
}
| btree.c | 387 |
U32 | swab32(u32 x)
u32 swab32(u32 x){
return ((x & 0xff)<<24) | ((x & 0xff00)<<8) |
((x>>8) & 0xff00) | ((x>>24)&0xff);
}
| btree.c | 393 |
STATIC INT | cellSize(Btree *pBt, Cell *pCell)
static int cellSize(Btree *pBt, Cell *pCell){
int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
if( n>MX_LOCAL_PAYLOAD ){
n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
}else{
n = ROUNDUP(n);
}
n += sizeof(CellHdr);
return n;
}
| btree.c | 398 |
STATIC VOID | defragmentPage(Btree *pBt, MemPage *pPage)
static void defragmentPage(Btree *pBt, MemPage *pPage){
int pc, i, n;
FreeBlk *pFBlk;
char newPage[SQLITE_USABLE_SIZE];
assert( sqlitepager_iswriteable(pPage) );
assert( pPage->isInit );
pc = sizeof(PageHdr);
pPage->u.hdr.firstCell = SWAB16(pBt, pc);
memcpy(newPage, pPage->u.aDisk, pc);
for(i=0; inCell; i++){
Cell *pCell = pPage->apCell[i];
/* This routine should never be called on an overfull page. The
** following asserts verify that constraint. */
assert( Addr(pCell) > Addr(pPage) );
assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE );
n = cellSize(pBt, pCell);
pCell->h.iNext = SWAB16(pBt, pc + n);
memcpy(&newPage[pc], pCell, n);
pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
pc += n;
}
assert( pPage->nFree==SQLITE_USABLE_SIZE-pc );
memcpy(pPage->u.aDisk, newPage, pc);
if( pPage->nCell>0 ){
pPage->apCell[pPage->nCell-1]->h.iNext = 0;
}
pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc);
pFBlk->iNext = 0;
pPage->u.hdr.firstFree = SWAB16(pBt, pc);
memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk));
}
| btree.c | 416 |
STATIC INT | allocateSpace(Btree *pBt, MemPage *pPage, int nByte)
static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){
FreeBlk *p;
u16 *pIdx;
int start;
int iSize;
#ifndef NDEBUG
int cnt = 0;
#endif
assert( sqlitepager_iswriteable(pPage) );
assert( nByte==ROUNDUP(nByte) );
assert( pPage->isInit );
if( pPage->nFreeisOverfull ) return 0;
pIdx = &pPage->u.hdr.firstFree;
p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
while( (iSize = SWAB16(pBt, p->iSize))iNext==0 ){
defragmentPage(pBt, pPage);
pIdx = &pPage->u.hdr.firstFree;
}else{
pIdx = &p->iNext;
}
p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
}
if( iSize==nByte ){
start = SWAB16(pBt, *pIdx);
*pIdx = p->iNext;
}else{
FreeBlk *pNew;
start = SWAB16(pBt, *pIdx);
pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
pNew->iNext = p->iNext;
pNew->iSize = SWAB16(pBt, iSize - nByte);
*pIdx = SWAB16(pBt, start + nByte);
}
pPage->nFree -= nByte;
return start;
}
| btree.c | 457 |
STATIC VOID | freeSpace(Btree *pBt, MemPage *pPage, int start, int size)
static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){
int end = start + size;
u16 *pIdx, idx;
FreeBlk *pFBlk;
FreeBlk *pNew;
FreeBlk *pNext;
int iSize;
assert( sqlitepager_iswriteable(pPage) );
assert( size == ROUNDUP(size) );
assert( start == ROUNDUP(start) );
assert( pPage->isInit );
pIdx = &pPage->u.hdr.firstFree;
idx = SWAB16(pBt, *pIdx);
while( idx!=0 && idxu.aDisk[idx];
iSize = SWAB16(pBt, pFBlk->iSize);
if( idx + iSize == start ){
pFBlk->iSize = SWAB16(pBt, iSize + size);
if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){
pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size];
if( pBt->needSwab ){
pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size);
}else{
pFBlk->iSize += pNext->iSize;
}
pFBlk->iNext = pNext->iNext;
}
pPage->nFree += size;
return;
}
pIdx = &pFBlk->iNext;
idx = SWAB16(pBt, *pIdx);
}
pNew = (FreeBlk*)&pPage->u.aDisk[start];
if( idx != end ){
pNew->iSize = SWAB16(pBt, size);
pNew->iNext = SWAB16(pBt, idx);
}else{
pNext = (FreeBlk*)&pPage->u.aDisk[idx];
pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize));
pNew->iNext = pNext->iNext;
}
*pIdx = SWAB16(pBt, start);
pPage->nFree += size;
}
| btree.c | 510 |
STATIC INT | initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent)
static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
int idx; /* An index into pPage->u.aDisk[] */
Cell *pCell; /* A pointer to a Cell in pPage->u.aDisk[] */
FreeBlk *pFBlk; /* A pointer to a free block in pPage->u.aDisk[] */
int sz; /* The size of a Cell in bytes */
int freeSpace; /* Amount of free space on the page */
if( pPage->pParent ){
assert( pPage->pParent==pParent );
return SQLITE_OK;
}
if( pParent ){
pPage->pParent = pParent;
sqlitepager_ref(pParent);
}
if( pPage->isInit ) return SQLITE_OK;
pPage->isInit = 1;
pPage->nCell = 0;
freeSpace = USABLE_SPACE;
idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx!=0 ){
if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
if( idxu.aDisk[idx];
sz = cellSize(pBt, pCell);
if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error;
freeSpace -= sz;
pPage->apCell[pPage->nCell++] = pCell;
idx = SWAB16(pBt, pCell->h.iNext);
}
pPage->nFree = 0;
idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx!=0 ){
int iNext;
if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error;
if( idxu.aDisk[idx];
pPage->nFree += SWAB16(pBt, pFBlk->iSize);
iNext = SWAB16(pBt, pFBlk->iNext);
if( iNext>0 && iNext <= idx ) goto page_format_error;
idx = iNext;
}
if( pPage->nCell==0 && pPage->nFree==0 ){
/* As a special case, an uninitialized root page appears to be
** an empty database */
return SQLITE_OK;
}
if( pPage->nFree!=freeSpace ) goto page_format_error;
return SQLITE_OK;
page_format_error:
return SQLITE_CORRUPT;
}
| btree.c | 566 |
STATIC VOID | zeroPage(Btree *pBt, MemPage *pPage)
static void zeroPage(Btree *pBt, MemPage *pPage){
PageHdr *pHdr;
FreeBlk *pFBlk;
assert( sqlitepager_iswriteable(pPage) );
memset(pPage, 0, SQLITE_USABLE_SIZE);
pHdr = &pPage->u.hdr;
pHdr->firstCell = 0;
pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr));
pFBlk = (FreeBlk*)&pHdr[1];
pFBlk->iNext = 0;
pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr);
pFBlk->iSize = SWAB16(pBt, pPage->nFree);
pPage->nCell = 0;
pPage->isOverfull = 0;
}
| btree.c | 635 |
STATIC VOID | pageDestructor(void *pData)
static void pageDestructor(void *pData){
MemPage *pPage = (MemPage*)pData;
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
pPage->pParent = 0;
sqlitepager_unref(pParent);
}
}
| btree.c | 655 |
INT | sqliteBtreeOpen( const char *zFilename, int omitJournal, int nCache, Btree **ppBtree )
int sqliteBtreeOpen(
const char *zFilename, /* Name of the file containing the BTree database */
int omitJournal, /* if TRUE then do not journal this file */
int nCache, /* How many pages in the page cache */
Btree **ppBtree /* Pointer to new Btree object written here */
){
Btree *pBt;
int rc;
/*
** The following asserts make sure that structures used by the btree are
** the right size. This is to guard against size changes that result
** when compiling on a different architecture.
*/
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
assert( sizeof(PageHdr)==8 );
assert( sizeof(CellHdr)==12 );
assert( sizeof(FreeBlk)==4 );
assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE );
assert( sizeof(FreelistInfo)==OVERFLOW_SIZE );
assert( sizeof(ptr)==sizeof(char*) );
assert( sizeof(uptr)==sizeof(ptr) );
pBt = sqliteMalloc( sizeof(*pBt) );
if( pBt==0 ){
*ppBtree = 0;
return SQLITE_NOMEM;
}
if( nCache<10 ) nCache = 10;
rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
!omitJournal);
if( rc!=SQLITE_OK ){
if( pBt->pPager ) sqlitepager_close(pBt->pPager);
sqliteFree(pBt);
*ppBtree = 0;
return rc;
}
sqlitepager_set_destructor(pBt->pPager, pageDestructor);
pBt->pCursor = 0;
pBt->page1 = 0;
pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
pBt->pOps = &sqliteBtreeOps;
*ppBtree = pBt;
return SQLITE_OK;
}
| btree.c | 669 |
STATIC INT | fileBtreeClose(Btree *pBt)
static int fileBtreeClose(Btree *pBt){
while( pBt->pCursor ){
fileBtreeCloseCursor(pBt->pCursor);
}
sqlitepager_close(pBt->pPager);
sqliteFree(pBt);
return SQLITE_OK;
}
| btree.c | 728 |
STATIC INT | fileBtreeSetCacheSize(Btree *pBt, int mxPage)
static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
sqlitepager_set_cachesize(pBt->pPager, mxPage);
return SQLITE_OK;
}
| btree.c | 740 |
STATIC INT | fileBtreeSetSafetyLevel(Btree *pBt, int level)
static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
sqlitepager_set_safety_level(pBt->pPager, level);
return SQLITE_OK;
}
| btree.c | 760 |
STATIC INT | lockBtree(Btree *pBt)
static int lockBtree(Btree *pBt){
int rc;
if( pBt->page1 ) return SQLITE_OK;
rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1);
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
if( sqlitepager_pagecount(pBt->pPager)>0 ){
PageOne *pP1 = pBt->page1;
if( strcmp(pP1->zMagic,zMagicHeader)!=0 ||
(pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){
rc = SQLITE_NOTADB;
goto page1_init_failed;
}
pBt->needSwab = pP1->iMagic!=MAGIC;
}
return rc;
page1_init_failed:
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
return rc;
}
| btree.c | 773 |
STATIC VOID | unlockBtreeIfUnused(Btree *pBt)
static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
pBt->inTrans = 0;
pBt->inCkpt = 0;
}
}
| btree.c | 809 |
STATIC INT | newDatabase(Btree *pBt)
static int newDatabase(Btree *pBt){
MemPage *pRoot;
PageOne *pP1;
int rc;
if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
pP1 = pBt->page1;
rc = sqlitepager_write(pBt->page1);
if( rc ) return rc;
rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot);
if( rc ) return rc;
rc = sqlitepager_write(pRoot);
if( rc ){
sqlitepager_unref(pRoot);
return rc;
}
strcpy(pP1->zMagic, zMagicHeader);
if( btree_native_byte_order ){
pP1->iMagic = MAGIC;
pBt->needSwab = 0;
}else{
pP1->iMagic = swab32(MAGIC);
pBt->needSwab = 1;
}
zeroPage(pBt, pRoot);
sqlitepager_unref(pRoot);
return SQLITE_OK;
}
| btree.c | 828 |
STATIC INT | fileBtreeBeginTrans(Btree *pBt)
static int fileBtreeBeginTrans(Btree *pBt){
int rc;
if( pBt->inTrans ) return SQLITE_ERROR;
if( pBt->readOnly ) return SQLITE_READONLY;
if( pBt->page1==0 ){
rc = lockBtree(pBt);
if( rc!=SQLITE_OK ){
return rc;
}
}
rc = sqlitepager_begin(pBt->page1);
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
if( rc==SQLITE_OK ){
pBt->inTrans = 1;
pBt->inCkpt = 0;
}else{
unlockBtreeIfUnused(pBt);
}
return rc;
}
| btree.c | 860 |
STATIC INT | fileBtreeCommit(Btree *pBt)
static int fileBtreeCommit(Btree *pBt){
int rc;
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0;
pBt->inCkpt = 0;
unlockBtreeIfUnused(pBt);
return rc;
}
| btree.c | 898 |
STATIC INT | fileBtreeRollback(Btree *pBt)
static int fileBtreeRollback(Btree *pBt){
int rc;
BtCursor *pCur;
if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0;
pBt->inCkpt = 0;
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage && pCur->pPage->isInit==0 ){
sqlitepager_unref(pCur->pPage);
pCur->pPage = 0;
}
}
unlockBtreeIfUnused(pBt);
return rc;
}
| btree.c | 913 |
STATIC INT | fileBtreeBeginCkpt(Btree *pBt)
static int fileBtreeBeginCkpt(Btree *pBt){
int rc;
if( !pBt->inTrans || pBt->inCkpt ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
pBt->inCkpt = 1;
return rc;
}
| btree.c | 939 |
STATIC INT | fileBtreeCommitCkpt(Btree *pBt)
static int fileBtreeCommitCkpt(Btree *pBt){
int rc;
if( pBt->inCkpt && !pBt->readOnly ){
rc = sqlitepager_ckpt_commit(pBt->pPager);
}else{
rc = SQLITE_OK;
}
pBt->inCkpt = 0;
return rc;
}
| btree.c | 960 |
STATIC INT | fileBtreeRollbackCkpt(Btree *pBt)
static int fileBtreeRollbackCkpt(Btree *pBt){
int rc;
BtCursor *pCur;
if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
rc = sqlitepager_ckpt_rollback(pBt->pPager);
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage && pCur->pPage->isInit==0 ){
sqlitepager_unref(pCur->pPage);
pCur->pPage = 0;
}
}
pBt->inCkpt = 0;
return rc;
}
| btree.c | 975 |
STATIC INT | fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur)
static
int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
int rc;
BtCursor *pCur, *pRing;
if( pBt->readOnly && wrFlag ){
*ppCur = 0;
return SQLITE_READONLY;
}
if( pBt->page1==0 ){
rc = lockBtree(pBt);
if( rc!=SQLITE_OK ){
*ppCur = 0;
return rc;
}
}
pCur = sqliteMalloc( sizeof(*pCur) );
if( pCur==0 ){
rc = SQLITE_NOMEM;
goto create_cursor_exception;
}
pCur->pgnoRoot = (Pgno)iTable;
rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
pCur->pOps = &sqliteBtreeCursorOps;
pCur->pBt = pBt;
pCur->wrFlag = wrFlag;
pCur->idx = 0;
pCur->eSkip = SKIP_INVALID;
pCur->pNext = pBt->pCursor;
if( pCur->pNext ){
pCur->pNext->pPrev = pCur;
}
pCur->pPrev = 0;
pRing = pBt->pCursor;
while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; }
if( pRing ){
pCur->pShared = pRing->pShared;
pRing->pShared = pCur;
}else{
pCur->pShared = pCur;
}
pBt->pCursor = pCur;
*ppCur = pCur;
return SQLITE_OK;
create_cursor_exception:
*ppCur = 0;
if( pCur ){
if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
sqliteFree(pCur);
}
unlockBtreeIfUnused(pBt);
return rc;
}
| btree.c | 998 |
STATIC INT | fileBtreeCloseCursor(BtCursor *pCur)
static int fileBtreeCloseCursor(BtCursor *pCur){
Btree *pBt = pCur->pBt;
if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext;
}else{
pBt->pCursor = pCur->pNext;
}
if( pCur->pNext ){
pCur->pNext->pPrev = pCur->pPrev;
}
if( pCur->pPage ){
sqlitepager_unref(pCur->pPage);
}
if( pCur->pShared!=pCur ){
BtCursor *pRing = pCur->pShared;
while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
pRing->pShared = pCur->pShared;
}
unlockBtreeIfUnused(pBt);
sqliteFree(pCur);
return SQLITE_OK;
}
| btree.c | 1096 |
STATIC VOID | getTempCursor(BtCursor *pCur, BtCursor *pTempCur)
static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
memcpy(pTempCur, pCur, sizeof(*pCur));
pTempCur->pNext = 0;
pTempCur->pPrev = 0;
if( pTempCur->pPage ){
sqlitepager_ref(pTempCur->pPage);
}
}
| btree.c | 1123 |
STATIC VOID | releaseTempCursor(BtCursor *pCur)
static void releaseTempCursor(BtCursor *pCur){
if( pCur->pPage ){
sqlitepager_unref(pCur->pPage);
}
}
| btree.c | 1136 |
STATIC INT | fileBtreeKeySize(BtCursor *pCur, int *pSize)
static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
Cell *pCell;
MemPage *pPage;
pPage = pCur->pPage;
assert( pPage!=0 );
if( pCur->idx >= pPage->nCell ){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
*pSize = NKEY(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
| btree.c | 1146 |
STATIC INT | getPayload(BtCursor *pCur, int offset, int amt, char *zBuf)
static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
char *aPayload;
Pgno nextPage;
int rc;
Btree *pBt = pCur->pBt;
assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->idx>=0 && pCur->idxpPage->nCell );
aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
if( offsetMX_LOCAL_PAYLOAD ){
a = MX_LOCAL_PAYLOAD - offset;
}
memcpy(zBuf, &aPayload[offset], a);
if( a==amt ){
return SQLITE_OK;
}
offset = 0;
zBuf += a;
amt -= a;
}else{
offset -= MX_LOCAL_PAYLOAD;
}
if( amt>0 ){
nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
}
while( amt>0 && nextPage ){
OverflowPage *pOvfl;
rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
if( rc!=0 ){
return rc;
}
nextPage = SWAB32(pBt, pOvfl->iNext);
if( offset OVERFLOW_SIZE ){
a = OVERFLOW_SIZE - offset;
}
memcpy(zBuf, &pOvfl->aPayload[offset], a);
offset = 0;
amt -= a;
zBuf += a;
}else{
offset -= OVERFLOW_SIZE;
}
sqlitepager_unref(pOvfl);
}
if( amt>0 ){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}
| btree.c | 1168 |
STATIC INT | fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf)
static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
MemPage *pPage;
assert( amt>=0 );
assert( offset>=0 );
assert( pCur->pPage!=0 );
pPage = pCur->pPage;
if( pCur->idx >= pPage->nCell ){
return 0;
}
assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
getPayload(pCur, offset, amt, zBuf);
return amt;
}
| btree.c | 1229 |
STATIC INT | fileBtreeDataSize(BtCursor *pCur, int *pSize)
static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
Cell *pCell;
MemPage *pPage;
pPage = pCur->pPage;
assert( pPage!=0 );
if( pCur->idx >= pPage->nCell ){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
*pSize = NDATA(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
| btree.c | 1257 |
STATIC INT | fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf)
static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
Cell *pCell;
MemPage *pPage;
assert( amt>=0 );
assert( offset>=0 );
assert( pCur->pPage!=0 );
pPage = pCur->pPage;
if( pCur->idx >= pPage->nCell ){
return 0;
}
pCell = pPage->apCell[pCur->idx];
assert( amt+offset <= NDATA(pCur->pBt, pCell->h) );
getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
return amt;
}
| btree.c | 1279 |
STATIC INT | fileBtreeKeyCompare( BtCursor *pCur, const void *pKey, int nKey, int nIgnore, int *pResult )
static int fileBtreeKeyCompare(
BtCursor *pCur, /* Pointer to entry to compare against */
const void *pKey, /* Key to compare against entry that pCur points to */
int nKey, /* Number of bytes in pKey */
int nIgnore, /* Ignore this many bytes at the end of pCur */
int *pResult /* Write the result here */
){
Pgno nextPage;
int n, c, rc, nLocal;
Cell *pCell;
Btree *pBt = pCur->pBt;
const char *zKey = (const char*)pKey;
assert( pCur->pPage );
assert( pCur->idx>=0 && pCur->idxpPage->nCell );
pCell = pCur->pPage->apCell[pCur->idx];
nLocal = NKEY(pBt, pCell->h) - nIgnore;
if( nLocal<0 ) nLocal = 0;
n = nKeyMX_LOCAL_PAYLOAD ){
n = MX_LOCAL_PAYLOAD;
}
c = memcmp(pCell->aPayload, zKey, n);
if( c!=0 ){
*pResult = c;
return SQLITE_OK;
}
zKey += n;
nKey -= n;
nLocal -= n;
nextPage = SWAB32(pBt, pCell->ovfl);
while( nKey>0 && nLocal>0 ){
OverflowPage *pOvfl;
if( nextPage==0 ){
return SQLITE_CORRUPT;
}
rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
if( rc ){
return rc;
}
nextPage = SWAB32(pBt, pOvfl->iNext);
n = nKeyOVERFLOW_SIZE ){
n = OVERFLOW_SIZE;
}
c = memcmp(pOvfl->aPayload, zKey, n);
sqlitepager_unref(pOvfl);
if( c!=0 ){
*pResult = c;
return SQLITE_OK;
}
nKey -= n;
nLocal -= n;
zKey += n;
}
if( c==0 ){
c = nLocal - nKey;
}
*pResult = c;
return SQLITE_OK;
}
| btree.c | 1304 |
STATIC INT | moveToChild(BtCursor *pCur, int newPgno)
static int moveToChild(BtCursor *pCur, int newPgno){
int rc;
MemPage *pNewPage;
Btree *pBt = pCur->pBt;
newPgno = SWAB32(pBt, newPgno);
rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
if( rc ) return rc;
rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
if( rc ) return rc;
assert( pCur->idx>=pCur->pPage->nCell
|| pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
assert( pCur->idxpPage->nCell
|| pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
pNewPage->idxParent = pCur->idx;
pCur->pPage->idxShift = 0;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNewPage;
pCur->idx = 0;
if( pNewPage->nCell<1 ){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}
| btree.c | 1387 |
STATIC VOID | moveToParent(BtCursor *pCur)
static void moveToParent(BtCursor *pCur){
Pgno oldPgno;
MemPage *pParent;
MemPage *pPage;
int idxParent;
pPage = pCur->pPage;
assert( pPage!=0 );
pParent = pPage->pParent;
assert( pParent!=0 );
idxParent = pPage->idxParent;
sqlitepager_ref(pParent);
sqlitepager_unref(pPage);
pCur->pPage = pParent;
assert( pParent->idxShift==0 );
if( pParent->idxShift==0 ){
pCur->idx = idxParent;
#ifndef NDEBUG
/* Verify that pCur->idx is the correct index to point back to the child
** page we just came from
*/
oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
if( pCur->idxnCell ){
assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
}else{
assert( pParent->u.hdr.rightChild==oldPgno );
}
#endif
}else{
/* The MemPage.idxShift flag indicates that cell indices might have
** changed since idxParent was set and hence idxParent might be out
** of date. So recompute the parent cell index by scanning all cells
** and locating the one that points to the child we just came from.
*/
int i;
pCur->idx = pParent->nCell;
oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
for(i=0; inCell; i++){
if( pParent->apCell[i]->h.leftChild==oldPgno ){
pCur->idx = i;
break;
}
}
}
}
| btree.c | 1416 |
STATIC INT | moveToRoot(BtCursor *pCur)
static int moveToRoot(BtCursor *pCur){
MemPage *pNew;
int rc;
Btree *pBt = pCur->pBt;
rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
if( rc ) return rc;
rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
if( rc ) return rc;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNew;
pCur->idx = 0;
return SQLITE_OK;
}
| btree.c | 1469 |
STATIC INT | moveToLeftmost(BtCursor *pCur)
static int moveToLeftmost(BtCursor *pCur){
Pgno pgno;
int rc;
while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
return SQLITE_OK;
}
| btree.c | 1487 |
STATIC INT | moveToRightmost(BtCursor *pCur)
static int moveToRightmost(BtCursor *pCur){
Pgno pgno;
int rc;
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
pCur->idx = pCur->pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
pCur->idx = pCur->pPage->nCell - 1;
return SQLITE_OK;
}
| btree.c | 1502 |
STATIC INT | fileBtreeFirst(BtCursor *pCur, int *pRes)
static int fileBtreeFirst(BtCursor *pCur, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur);
if( rc ) return rc;
if( pCur->pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
*pRes = 0;
rc = moveToLeftmost(pCur);
pCur->eSkip = SKIP_NONE;
return rc;
}
| btree.c | 1522 |
STATIC INT | fileBtreeLast(BtCursor *pCur, int *pRes)
static int fileBtreeLast(BtCursor *pCur, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur);
if( rc ) return rc;
assert( pCur->pPage->isInit );
if( pCur->pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
*pRes = 0;
rc = moveToRightmost(pCur);
pCur->eSkip = SKIP_NONE;
return rc;
}
| btree.c | 1541 |
STATIC INT | fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes)
static
int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT;
pCur->eSkip = SKIP_NONE;
rc = moveToRoot(pCur);
if( rc ) return rc;
for(;;){
int lwr, upr;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
int c = -1; /* pRes return if table is empty must be -1 */
lwr = 0;
upr = pPage->nCell-1;
while( lwr<=upr ){
pCur->idx = (lwr+upr)/2;
rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
if( rc ) return rc;
if( c==0 ){
pCur->iMatch = c;
if( pRes ) *pRes = 0;
return SQLITE_OK;
}
if( c<0 ){
lwr = pCur->idx+1;
}else{
upr = pCur->idx-1;
}
}
assert( lwr==upr+1 );
assert( pPage->isInit );
if( lwr>=pPage->nCell ){
chldPg = pPage->u.hdr.rightChild;
}else{
chldPg = pPage->apCell[lwr]->h.leftChild;
}
if( chldPg==0 ){
pCur->iMatch = c;
if( pRes ) *pRes = c;
return SQLITE_OK;
}
pCur->idx = lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) return rc;
}
/* NOT REACHED */
}
| btree.c | 1561 |
STATIC INT | fileBtreeNext(BtCursor *pCur, int *pRes)
static int fileBtreeNext(BtCursor *pCur, int *pRes){
int rc;
MemPage *pPage = pCur->pPage;
assert( pRes!=0 );
if( pPage==0 ){
*pRes = 1;
return SQLITE_ABORT;
}
assert( pPage->isInit );
assert( pCur->eSkip!=SKIP_INVALID );
if( pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
assert( pCur->idxnCell );
if( pCur->eSkip==SKIP_NEXT ){
pCur->eSkip = SKIP_NONE;
*pRes = 0;
return SQLITE_OK;
}
pCur->eSkip = SKIP_NONE;
pCur->idx++;
if( pCur->idx>=pPage->nCell ){
if( pPage->u.hdr.rightChild ){
rc = moveToChild(pCur, pPage->u.hdr.rightChild);
if( rc ) return rc;
rc = moveToLeftmost(pCur);
*pRes = 0;
return rc;
}
do{
if( pPage->pParent==0 ){
*pRes = 1;
return SQLITE_OK;
}
moveToParent(pCur);
pPage = pCur->pPage;
}while( pCur->idx>=pPage->nCell );
*pRes = 0;
return SQLITE_OK;
}
*pRes = 0;
if( pPage->u.hdr.rightChild==0 ){
return SQLITE_OK;
}
rc = moveToLeftmost(pCur);
return rc;
}
| btree.c | 1632 |
STATIC INT | fileBtreePrevious(BtCursor *pCur, int *pRes)
static int fileBtreePrevious(BtCursor *pCur, int *pRes){
int rc;
Pgno pgno;
MemPage *pPage;
pPage = pCur->pPage;
if( pPage==0 ){
*pRes = 1;
return SQLITE_ABORT;
}
assert( pPage->isInit );
assert( pCur->eSkip!=SKIP_INVALID );
if( pPage->nCell==0 ){
*pRes = 1;
return SQLITE_OK;
}
if( pCur->eSkip==SKIP_PREV ){
pCur->eSkip = SKIP_NONE;
*pRes = 0;
return SQLITE_OK;
}
pCur->eSkip = SKIP_NONE;
assert( pCur->idx>=0 );
if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
while( pCur->idx==0 ){
if( pPage->pParent==0 ){
if( pRes ) *pRes = 1;
return SQLITE_OK;
}
moveToParent(pCur);
pPage = pCur->pPage;
}
pCur->idx--;
rc = SQLITE_OK;
}
*pRes = 0;
return rc;
}
| btree.c | 1687 |
STATIC INT | allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby)
static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
PageOne *pPage1 = pBt->page1;
int rc;
if( pPage1->freeList ){
OverflowPage *pOvfl;
FreelistInfo *pInfo;
rc = sqlitepager_write(pPage1);
if( rc ) return rc;
SWAB_ADD(pBt, pPage1->nFree, -1);
rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
(void**)&pOvfl);
if( rc ) return rc;
rc = sqlitepager_write(pOvfl);
if( rc ){
sqlitepager_unref(pOvfl);
return rc;
}
pInfo = (FreelistInfo*)pOvfl->aPayload;
if( pInfo->nFree==0 ){
*pPgno = SWAB32(pBt, pPage1->freeList);
pPage1->freeList = pOvfl->iNext;
*ppPage = (MemPage*)pOvfl;
}else{
int closest, n;
n = SWAB32(pBt, pInfo->nFree);
if( n>1 && nearby>0 ){
int i, dist;
closest = 0;
dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
if( dist<0 ) dist = -dist;
for(i=1; iaFree[i]) - nearby;
if( d2<0 ) d2 = -d2;
if( d2nFree, -1);
*pPgno = SWAB32(pBt, pInfo->aFree[closest]);
pInfo->aFree[closest] = pInfo->aFree[n-1];
rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
sqlitepager_unref(pOvfl);
if( rc==SQLITE_OK ){
sqlitepager_dont_rollback(*ppPage);
rc = sqlitepager_write(*ppPage);
}
}
}else{
*pPgno = sqlitepager_pagecount(pBt->pPager) + 1;
rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
if( rc ) return rc;
rc = sqlitepager_write(*ppPage);
}
return rc;
}
| btree.c | 1735 |
STATIC INT | freePage(Btree *pBt, void *pPage, Pgno pgno)
static int freePage(Btree *pBt, void *pPage, Pgno pgno){
PageOne *pPage1 = pBt->page1;
OverflowPage *pOvfl = (OverflowPage*)pPage;
int rc;
int needUnref = 0;
MemPage *pMemPage;
if( pgno==0 ){
assert( pOvfl!=0 );
pgno = sqlitepager_pagenumber(pOvfl);
}
assert( pgno>2 );
assert( sqlitepager_pagenumber(pOvfl)==pgno );
pMemPage = (MemPage*)pPage;
pMemPage->isInit = 0;
if( pMemPage->pParent ){
sqlitepager_unref(pMemPage->pParent);
pMemPage->pParent = 0;
}
rc = sqlitepager_write(pPage1);
if( rc ){
return rc;
}
SWAB_ADD(pBt, pPage1->nFree, 1);
if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
OverflowPage *pFreeIdx;
rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
(void**)&pFreeIdx);
if( rc==SQLITE_OK ){
FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
int n = SWAB32(pBt, pInfo->nFree);
if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
rc = sqlitepager_write(pFreeIdx);
if( rc==SQLITE_OK ){
pInfo->aFree[n] = SWAB32(pBt, pgno);
SWAB_ADD(pBt, pInfo->nFree, 1);
sqlitepager_unref(pFreeIdx);
sqlitepager_dont_write(pBt->pPager, pgno);
return rc;
}
}
sqlitepager_unref(pFreeIdx);
}
}
if( pOvfl==0 ){
assert( pgno>0 );
rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
if( rc ) return rc;
needUnref = 1;
}
rc = sqlitepager_write(pOvfl);
if( rc ){
if( needUnref ) sqlitepager_unref(pOvfl);
return rc;
}
pOvfl->iNext = pPage1->freeList;
pPage1->freeList = SWAB32(pBt, pgno);
memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
if( needUnref ) rc = sqlitepager_unref(pOvfl);
return rc;
}
| btree.c | 1810 |
STATIC INT | clearCell(Btree *pBt, Cell *pCell)
static int clearCell(Btree *pBt, Cell *pCell){
Pager *pPager = pBt->pPager;
OverflowPage *pOvfl;
Pgno ovfl, nextOvfl;
int rc;
if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
return SQLITE_OK;
}
ovfl = SWAB32(pBt, pCell->ovfl);
pCell->ovfl = 0;
while( ovfl ){
rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
if( rc ) return rc;
nextOvfl = SWAB32(pBt, pOvfl->iNext);
rc = freePage(pBt, pOvfl, ovfl);
if( rc ) return rc;
sqlitepager_unref(pOvfl);
ovfl = nextOvfl;
}
return SQLITE_OK;
}
| btree.c | 1878 |
STATIC INT | fillInCell( Btree *pBt, Cell *pCell, const void *pKey, int nKey, const void *pData,int nData )
static int fillInCell(
Btree *pBt, /* The whole Btree. Needed to allocate pages */
Cell *pCell, /* Populate this Cell structure */
const void *pKey, int nKey, /* The key */
const void *pData,int nData /* The data */
){
OverflowPage *pOvfl, *pPrior;
Pgno *pNext;
int spaceLeft;
int n, rc;
int nPayload;
const char *pPayload;
char *pSpace;
Pgno nearby = 0;
pCell->h.leftChild = 0;
pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
pCell->h.nKeyHi = nKey >> 16;
pCell->h.nData = SWAB16(pBt, nData & 0xffff);
pCell->h.nDataHi = nData >> 16;
pCell->h.iNext = 0;
pNext = &pCell->ovfl;
pSpace = pCell->aPayload;
spaceLeft = MX_LOCAL_PAYLOAD;
pPayload = pKey;
pKey = 0;
nPayload = nKey;
pPrior = 0;
while( nPayload>0 ){
if( spaceLeft==0 ){
rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby);
if( rc ){
*pNext = 0;
}else{
nearby = *pNext;
}
if( pPrior ) sqlitepager_unref(pPrior);
if( rc ){
clearCell(pBt, pCell);
return rc;
}
if( pBt->needSwab ) *pNext = swab32(*pNext);
pPrior = pOvfl;
spaceLeft = OVERFLOW_SIZE;
pSpace = pOvfl->aPayload;
pNext = &pOvfl->iNext;
}
n = nPayload;
if( n>spaceLeft ) n = spaceLeft;
memcpy(pSpace, pPayload, n);
nPayload -= n;
if( nPayload==0 && pData ){
pPayload = pData;
nPayload = nData;
pData = 0;
}else{
pPayload += n;
}
spaceLeft -= n;
pSpace += n;
}
*pNext = 0;
if( pPrior ){
sqlitepager_unref(pPrior);
}
return SQLITE_OK;
}
| btree.c | 1905 |
STATIC VOID | reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx)
static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){
MemPage *pThis;
if( pgno==0 ) return;
assert( pPager!=0 );
pThis = sqlitepager_lookup(pPager, pgno);
if( pThis && pThis->isInit ){
if( pThis->pParent!=pNewParent ){
if( pThis->pParent ) sqlitepager_unref(pThis->pParent);
pThis->pParent = pNewParent;
if( pNewParent ) sqlitepager_ref(pNewParent);
}
pThis->idxParent = idx;
sqlitepager_unref(pThis);
}
}
| btree.c | 1978 |
STATIC VOID | reparentChildPages(Btree *pBt, MemPage *pPage)
static void reparentChildPages(Btree *pBt, MemPage *pPage){
int i;
Pager *pPager = pBt->pPager;
for(i=0; inCell; i++){
reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i);
}
reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i);
pPage->idxShift = 0;
}
| btree.c | 2000 |
STATIC VOID | dropCell(Btree *pBt, MemPage *pPage, int idx, int sz)
static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){
int j;
assert( idx>=0 && idxnCell );
assert( sz==cellSize(pBt, pPage->apCell[idx]) );
assert( sqlitepager_iswriteable(pPage) );
freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
for(j=idx; jnCell-1; j++){
pPage->apCell[j] = pPage->apCell[j+1];
}
pPage->nCell--;
pPage->idxShift = 1;
}
| btree.c | 2018 |
STATIC VOID | insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz)
static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){
int idx, j;
assert( i>=0 && i<=pPage->nCell );
assert( sz==cellSize(pBt, pCell) );
assert( sqlitepager_iswriteable(pPage) );
idx = allocateSpace(pBt, pPage, sz);
for(j=pPage->nCell; j>i; j--){
pPage->apCell[j] = pPage->apCell[j-1];
}
pPage->nCell++;
if( idx<=0 ){
pPage->isOverfull = 1;
pPage->apCell[i] = pCell;
}else{
memcpy(&pPage->u.aDisk[idx], pCell, sz);
pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
}
pPage->idxShift = 1;
}
| btree.c | 2044 |
STATIC VOID | relinkCellList(Btree *pBt, MemPage *pPage)
static void relinkCellList(Btree *pBt, MemPage *pPage){
int i;
u16 *pIdx;
assert( sqlitepager_iswriteable(pPage) );
pIdx = &pPage->u.hdr.firstCell;
for(i=0; inCell; i++){
int idx = Addr(pPage->apCell[i]) - Addr(pPage);
assert( idx>0 && idxapCell[i]->h.iNext;
}
*pIdx = 0;
}
| btree.c | 2077 |
STATIC VOID | copyPage(MemPage *pTo, MemPage *pFrom)
static void copyPage(MemPage *pTo, MemPage *pFrom){
uptr from, to;
int i;
memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE);
pTo->pParent = 0;
pTo->isInit = 1;
pTo->nCell = pFrom->nCell;
pTo->nFree = pFrom->nFree;
pTo->isOverfull = pFrom->isOverfull;
to = Addr(pTo);
from = Addr(pFrom);
for(i=0; inCell; i++){
uptr x = Addr(pFrom->apCell[i]);
if( x>from && xapCell[i]) = x + to - from;
}else{
pTo->apCell[i] = pFrom->apCell[i];
}
}
}
| btree.c | 2097 |
STATIC INT | balance(Btree *pBt, MemPage *pPage, BtCursor *pCur)
static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
MemPage *pParent; /* The parent of pPage */
int nCell; /* Number of cells in apCell[] */
int nOld; /* Number of pages in apOld[] */
int nNew; /* Number of pages in apNew[] */
int nDiv; /* Number of cells in apDiv[] */
int i, j, k; /* Loop counters */
int idx; /* Index of pPage in pParent->apCell[] */
int nxDiv; /* Next divider slot in pParent->apCell[] */
int rc; /* The return code */
int iCur; /* apCell[iCur] is the cell of the cursor */
MemPage *pOldCurPage; /* The cursor originally points to this page */
int subtotal; /* Subtotal of bytes in cells on one page */
MemPage *extraUnref = 0; /* A page that needs to be unref-ed */
MemPage *apOld[NB]; /* pPage and up to two siblings */
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
MemPage *apNew[NB+1]; /* pPage and up to NB siblings after balancing */
Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */
int idxDiv[NB]; /* Indices of divider cells in pParent */
Cell *apDiv[NB]; /* Divider cells in pParent */
Cell aTemp[NB]; /* Temporary holding area for apDiv[] */
int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */
int szNew[NB+1]; /* Combined size of cells place on i-th page */
MemPage aOld[NB]; /* Temporary copies of pPage and its siblings */
Cell *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
/*
** Return without doing any work if pPage is neither overfull nor
** underfull.
*/
assert( sqlitepager_iswriteable(pPage) );
if( !pPage->isOverfull && pPage->nFreenCell>=2){
relinkCellList(pBt, pPage);
return SQLITE_OK;
}
/*
** Find the parent of the page to be balanceed.
** If there is no parent, it means this page is the root page and
** special rules apply.
*/
pParent = pPage->pParent;
if( pParent==0 ){
Pgno pgnoChild;
MemPage *pChild;
assert( pPage->isInit );
if( pPage->nCell==0 ){
if( pPage->u.hdr.rightChild ){
/*
** The root page is empty. Copy the one child page
** into the root page and return. This reduces the depth
** of the BTree by one.
*/
pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild);
rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
if( rc ) return rc;
memcpy(pPage, pChild, SQLITE_USABLE_SIZE);
pPage->isInit = 0;
rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0);
assert( rc==SQLITE_OK );
reparentChildPages(pBt, pPage);
if( pCur && pCur->pPage==pChild ){
sqlitepager_unref(pChild);
pCur->pPage = pPage;
sqlitepager_ref(pPage);
}
freePage(pBt, pChild, pgnoChild);
sqlitepager_unref(pChild);
}else{
relinkCellList(pBt, pPage);
}
return SQLITE_OK;
}
if( !pPage->isOverfull ){
/* It is OK for the root page to be less than half full.
*/
relinkCellList(pBt, pPage);
return SQLITE_OK;
}
/*
** If we get to here, it means the root page is overfull.
** When this happens, Create a new child page and copy the
** contents of the root into the child. Then make the root
** page an empty page with rightChild pointing to the new
** child. Then fall thru to the code below which will cause
** the overfull child page to be split.
*/
rc = sqlitepager_write(pPage);
if( rc ) return rc;
rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage));
if( rc ) return rc;
assert( sqlitepager_iswriteable(pChild) );
copyPage(pChild, pPage);
pChild->pParent = pPage;
pChild->idxParent = 0;
sqlitepager_ref(pPage);
pChild->isOverfull = 1;
if( pCur && pCur->pPage==pPage ){
sqlitepager_unref(pPage);
pCur->pPage = pChild;
}else{
extraUnref = pChild;
}
zeroPage(pBt, pPage);
pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild);
pParent = pPage;
pPage = pChild;
}
rc = sqlitepager_write(pParent);
if( rc ) return rc;
assert( pParent->isInit );
/*
** Find the Cell in the parent page whose h.leftChild points back
** to pPage. The "idx" variable is the index of that cell. If pPage
** is the rightmost child of pParent then set idx to pParent->nCell
*/
if( pParent->idxShift ){
Pgno pgno, swabPgno;
pgno = sqlitepager_pagenumber(pPage);
swabPgno = SWAB32(pBt, pgno);
for(idx=0; idxnCell; idx++){
if( pParent->apCell[idx]->h.leftChild==swabPgno ){
break;
}
}
assert( idxnCell || pParent->u.hdr.rightChild==swabPgno );
}else{
idx = pPage->idxParent;
}
/*
** Initialize variables so that it will be safe to jump
** directly to balance_cleanup at any moment.
*/
nOld = nNew = 0;
sqlitepager_ref(pParent);
/*
** Find sibling pages to pPage and the Cells in pParent that divide
** the siblings. An attempt is made to find NN siblings on either
** side of pPage. More siblings are taken from one side, however, if
** pPage there are fewer than NN siblings on the other side. If pParent
** has NB or fewer children then all children of pParent are taken.
*/
nxDiv = idx - NN;
if( nxDiv + NB > pParent->nCell ){
nxDiv = pParent->nCell - NB + 1;
}
if( nxDiv<0 ){
nxDiv = 0;
}
nDiv = 0;
for(i=0, k=nxDiv; inCell ){
idxDiv[i] = k;
apDiv[i] = pParent->apCell[k];
nDiv++;
pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild);
}else if( k==pParent->nCell ){
pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild);
}else{
break;
}
rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
if( rc ) goto balance_cleanup;
rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
if( rc ) goto balance_cleanup;
apOld[i]->idxParent = k;
nOld++;
}
/*
** Set iCur to be the index in apCell[] of the cell that the cursor
** is pointing to. We will need this later on in order to keep the
** cursor pointing at the same cell. If pCur points to a page that
** has no involvement with this rebalancing, then set iCur to a large
** number so that the iCur==j tests always fail in the main cell
** distribution loop below.
*/
if( pCur ){
iCur = 0;
for(i=0; ipPage==apOld[i] ){
iCur += pCur->idx;
break;
}
iCur += apOld[i]->nCell;
if( ipPage==pParent && pCur->idx==idxDiv[i] ){
break;
}
iCur++;
}
pOldCurPage = pCur->pPage;
}
/*
** Make copies of the content of pPage and its siblings into aOld[].
** The rest of this function will use data from the copies rather
** that the original pages since the original pages will be in the
** process of being overwritten.
*/
for(i=0; inCell; j++){
apCell[nCell] = pOld->apCell[j];
szCell[nCell] = cellSize(pBt, apCell[nCell]);
nCell++;
}
if( ih.leftChild)==pgnoOld[i] );
apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
nCell++;
}
}
/*
** Figure out the number of pages needed to hold all nCell cells.
** Store this number in "k". Also compute szNew[] which is the total
** size of all cells on the i-th page and cntNew[] which is the index
** in apCell[] of the cell that divides path i from path i+1.
** cntNew[k] should equal nCell.
**
** This little patch of code is critical for keeping the tree
** balanced.
*/
for(subtotal=k=i=0; i USABLE_SPACE ){
szNew[k] = subtotal - szCell[i];
cntNew[k] = i;
subtotal = 0;
k++;
}
}
szNew[k] = subtotal;
cntNew[k] = nCell;
k++;
for(i=k-1; i>0; i--){
while( szNew[i]0 );
szNew[i] += szCell[cntNew[i-1]];
szNew[i-1] -= szCell[cntNew[i-1]-1];
}
}
assert( cntNew[0]>0 );
/*
** Allocate k new pages. Reuse old pages where possible.
*/
for(i=0; iisInit = 1;
}
/* Free any old pages that were not reused as new pages.
*/
while( ii ){
int t;
MemPage *pT;
t = pgnoNew[i];
pT = apNew[i];
pgnoNew[i] = pgnoNew[minI];
apNew[i] = apNew[minI];
pgnoNew[minI] = t;
apNew[minI] = pT;
}
}
/*
** Evenly distribute the data in apCell[] across the new pages.
** Insert divider cells into pParent as necessary.
*/
j = 0;
for(i=0; inFree>=szCell[j] );
if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; }
insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]);
j++;
}
assert( pNew->nCell>0 );
assert( !pNew->isOverfull );
relinkCellList(pBt, pNew);
if( iu.hdr.rightChild = apCell[j]->h.leftChild;
apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]);
if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; }
insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]);
j++;
nxDiv++;
}
}
assert( j==nCell );
apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild;
if( nxDiv==pParent->nCell ){
pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]);
}else{
pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]);
}
if( pCur ){
if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){
assert( pCur->pPage==pOldCurPage );
pCur->idx += nNew - nOld;
}else{
assert( pOldCurPage!=0 );
sqlitepager_ref(pCur->pPage);
sqlitepager_unref(pOldCurPage);
}
}
/*
** Reparent children of all cells.
*/
for(i=0; ipPage==0 ){
pCur->pPage = pParent;
pCur->idx = 0;
}else{
sqlitepager_unref(pParent);
}
return rc;
}
| btree.c | 2139 |
STATIC INT | checkReadLocks(BtCursor *pCur)
static int checkReadLocks(BtCursor *pCur){
BtCursor *p;
assert( pCur->wrFlag );
for(p=pCur->pShared; p!=pCur; p=p->pShared){
assert( p );
assert( p->pgnoRoot==pCur->pgnoRoot );
if( p->wrFlag==0 ) return SQLITE_LOCKED;
if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){
moveToRoot(p);
}
}
return SQLITE_OK;
}
| btree.c | 2584 |
STATIC INT | fileBtreeInsert( BtCursor *pCur, const void *pKey, int nKey, const void *pData, int nData )
static int fileBtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const void *pKey, int nKey, /* The key of the new record */
const void *pData, int nData /* The data of the new record */
){
Cell newCell;
int rc;
int loc;
int szNew;
MemPage *pPage;
Btree *pBt = pCur->pBt;
if( pCur->pPage==0 ){
return SQLITE_ABORT; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans || nKey+nData==0 ){
/* Must start a transaction before doing an insert */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( !pBt->readOnly );
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Cursor not open for writing */
}
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
rc = fileBtreeMoveto(pCur, pKey, nKey, &loc);
if( rc ) return rc;
pPage = pCur->pPage;
assert( pPage->isInit );
rc = sqlitepager_write(pPage);
if( rc ) return rc;
rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData);
if( rc ) return rc;
szNew = cellSize(pBt, &newCell);
if( loc==0 ){
newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild;
rc = clearCell(pBt, pPage->apCell[pCur->idx]);
if( rc ) return rc;
dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx]));
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
pCur->idx++;
}else{
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
}
insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
rc = balance(pCur->pBt, pPage, pCur);
/* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
pCur->eSkip = SKIP_INVALID;
return rc;
}
| btree.c | 2613 |
STATIC INT | fileBtreeDelete(BtCursor *pCur)
static int fileBtreeDelete(BtCursor *pCur){
MemPage *pPage = pCur->pPage;
Cell *pCell;
int rc;
Pgno pgnoChild;
Btree *pBt = pCur->pBt;
assert( pPage->isInit );
if( pCur->pPage==0 ){
return SQLITE_ABORT; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans ){
/* Must start a transaction before doing a delete */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( !pBt->readOnly );
if( pCur->idx >= pPage->nCell ){
return SQLITE_ERROR; /* The cursor is not pointing to anything */
}
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Did not open this cursor for writing */
}
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
rc = sqlitepager_write(pPage);
if( rc ) return rc;
pCell = pPage->apCell[pCur->idx];
pgnoChild = SWAB32(pBt, pCell->h.leftChild);
clearCell(pBt, pCell);
if( pgnoChild ){
/*
** The entry we are about to delete is not a leaf so if we do not
** do something we will leave a hole on an internal page.
** We have to fill the hole by moving in a cell from a leaf. The
** next Cell after the one to be deleted is guaranteed to exist and
** to be a leaf so we can use it.
*/
BtCursor leafCur;
Cell *pNext;
int szNext;
int notUsed;
getTempCursor(pCur, &leafCur);
rc = fileBtreeNext(&leafCur, ¬Used);
if( rc!=SQLITE_OK ){
if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT;
return rc;
}
rc = sqlitepager_write(leafCur.pPage);
if( rc ) return rc;
dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
pNext = leafCur.pPage->apCell[leafCur.idx];
szNext = cellSize(pBt, pNext);
pNext->h.leftChild = SWAB32(pBt, pgnoChild);
insertCell(pBt, pPage, pCur->idx, pNext, szNext);
rc = balance(pBt, pPage, pCur);
if( rc ) return rc;
pCur->eSkip = SKIP_NEXT;
dropCell(pBt, leafCur.pPage, leafCur.idx, szNext);
rc = balance(pBt, leafCur.pPage, pCur);
releaseTempCursor(&leafCur);
}else{
dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
if( pCur->idx>=pPage->nCell ){
pCur->idx = pPage->nCell-1;
if( pCur->idx<0 ){
pCur->idx = 0;
pCur->eSkip = SKIP_NEXT;
}else{
pCur->eSkip = SKIP_PREV;
}
}else{
pCur->eSkip = SKIP_NEXT;
}
rc = balance(pBt, pPage, pCur);
}
return rc;
}
| btree.c | 2673 |
STATIC INT | fileBtreeCreateTable(Btree *pBt, int *piTable)
static int fileBtreeCreateTable(Btree *pBt, int *piTable){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
if( !pBt->inTrans ){
/* Must start a transaction first */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
if( pBt->readOnly ){
return SQLITE_READONLY;
}
rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
if( rc ) return rc;
assert( sqlitepager_iswriteable(pRoot) );
zeroPage(pBt, pRoot);
sqlitepager_unref(pRoot);
*piTable = (int)pgnoRoot;
return SQLITE_OK;
}
| btree.c | 2766 |
STATIC INT | clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag)
static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
MemPage *pPage;
int rc;
Cell *pCell;
int idx;
rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage);
if( rc ) return rc;
rc = sqlitepager_write(pPage);
if( rc ) return rc;
rc = initPage(pBt, pPage, pgno, 0);
if( rc ) return rc;
idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 ){
pCell = (Cell*)&pPage->u.aDisk[idx];
idx = SWAB16(pBt, pCell->h.iNext);
if( pCell->h.leftChild ){
rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
if( rc ) return rc;
}
rc = clearCell(pBt, pCell);
if( rc ) return rc;
}
if( pPage->u.hdr.rightChild ){
rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
if( rc ) return rc;
}
if( freePageFlag ){
rc = freePage(pBt, pPage, pgno);
}else{
zeroPage(pBt, pPage);
}
sqlitepager_unref(pPage);
return rc;
}
| btree.c | 2796 |
STATIC INT | fileBtreeClearTable(Btree *pBt, int iTable)
static int fileBtreeClearTable(Btree *pBt, int iTable){
int rc;
BtCursor *pCur;
if( !pBt->inTrans ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pgnoRoot==(Pgno)iTable ){
if( pCur->wrFlag==0 ) return SQLITE_LOCKED;
moveToRoot(pCur);
}
}
rc = clearDatabasePage(pBt, (Pgno)iTable, 0);
if( rc ){
fileBtreeRollback(pBt);
}
return rc;
}
| btree.c | 2836 |
STATIC INT | fileBtreeDropTable(Btree *pBt, int iTable)
static int fileBtreeDropTable(Btree *pBt, int iTable){
int rc;
MemPage *pPage;
BtCursor *pCur;
if( !pBt->inTrans ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pgnoRoot==(Pgno)iTable ){
return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
}
}
rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
if( rc ) return rc;
rc = fileBtreeClearTable(pBt, iTable);
if( rc ) return rc;
if( iTable>2 ){
rc = freePage(pBt, pPage, iTable);
}else{
zeroPage(pBt, pPage);
}
sqlitepager_unref(pPage);
return rc;
}
| btree.c | 2858 |
STATIC INT | copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell)
static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){
Pager *pFromPager = pBtFrom->pPager;
OverflowPage *pOvfl;
Pgno ovfl, nextOvfl;
Pgno *pPrev;
int rc = SQLITE_OK;
MemPage *pNew, *pPrevPg;
Pgno new;
if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){
return SQLITE_OK;
}
pPrev = &pCell->ovfl;
pPrevPg = 0;
ovfl = SWAB32(pBtTo, pCell->ovfl);
while( ovfl && rc==SQLITE_OK ){
rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl);
if( rc ) return rc;
nextOvfl = SWAB32(pBtFrom, pOvfl->iNext);
rc = allocatePage(pBtTo, &pNew, &new, 0);
if( rc==SQLITE_OK ){
rc = sqlitepager_write(pNew);
if( rc==SQLITE_OK ){
memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE);
*pPrev = SWAB32(pBtTo, new);
if( pPrevPg ){
sqlitepager_unref(pPrevPg);
}
pPrev = &pOvfl->iNext;
pPrevPg = pNew;
}
}
sqlitepager_unref(pOvfl);
ovfl = nextOvfl;
}
if( pPrevPg ){
sqlitepager_unref(pPrevPg);
}
return rc;
}
| btree.c | 2889 |
STATIC INT | copyDatabasePage( Btree *pBtFrom, Pgno pgnoFrom, Btree *pBtTo, Pgno *pTo )
static int copyDatabasePage(
Btree *pBtFrom,
Pgno pgnoFrom,
Btree *pBtTo,
Pgno *pTo
){
MemPage *pPageFrom, *pPage;
Pgno to;
int rc;
Cell *pCell;
int idx;
rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom);
if( rc ) return rc;
rc = allocatePage(pBt, &pPage, pTo, 0);
if( rc==SQLITE_OK ){
rc = sqlitepager_write(pPage);
}
if( rc==SQLITE_OK ){
memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE);
idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 ){
pCell = (Cell*)&pPage->u.aDisk[idx];
idx = SWAB16(pBt, pCell->h.iNext);
if( pCell->h.leftChild ){
Pgno newChld;
rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild),
pBtTo, &newChld);
if( rc ) return rc;
pCell->h.leftChild = SWAB32(pBtFrom, newChld);
}
rc = copyCell(pBtFrom, pBtTo, pCell);
if( rc ) return rc;
}
if( pPage->u.hdr.rightChild ){
Pgno newChld;
rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild),
pBtTo, &newChld);
if( rc ) return rc;
pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild);
}
}
sqlitepager_unref(pPage);
return rc;
}
| btree.c | 2937 |
STATIC INT | fileBtreeGetMeta(Btree *pBt, int *aMeta)
static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
PageOne *pP1;
int rc;
int i;
rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
if( rc ) return rc;
aMeta[0] = SWAB32(pBt, pP1->nFree);
for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){
aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]);
}
sqlitepager_unref(pP1);
return SQLITE_OK;
}
| btree.c | 2987 |
STATIC INT | fileBtreeUpdateMeta(Btree *pBt, int *aMeta)
static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){
PageOne *pP1;
int rc, i;
if( !pBt->inTrans ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
pP1 = pBt->page1;
rc = sqlitepager_write(pP1);
if( rc ) return rc;
for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){
pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]);
}
return SQLITE_OK;
}
/******************************************************************************
** The complete implementation of the BTree subsystem is above this line.
** All the code the follows is for testing and troubleshooting the BTree
** subsystem. None of the code that follows is used during normal operation.
******************************************************************************/
| btree.c | 3005 |
STATIC INT | fileBtreePageDump(Btree *pBt, int pgno, int recursive)
static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){
int rc;
MemPage *pPage;
int i, j;
int nFree;
u16 idx;
char range[20];
unsigned char payload[20];
rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage);
if( rc ){
return rc;
}
if( recursive ) printf("PAGE %d:\n", pgno);
i = 0;
idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
int sz = cellSize(pBt, pCell);
sprintf(range,"%d..%d", idx, idx+sz-1);
sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
memcpy(payload, pCell->aPayload, sz);
for(j=0; j0x7f ) payload[j] = '.';
}
payload[sz] = 0;
printf(
"cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n",
i, range, (int)pCell->h.leftChild,
NKEY(pBt, pCell->h), NDATA(pBt, pCell->h),
payload
);
if( pPage->isInit && pPage->apCell[i]!=pCell ){
printf("**** apCell[%d] does not match on prior entry ****\n", i);
}
i++;
idx = SWAB16(pBt, pCell->h.iNext);
}
if( idx!=0 ){
printf("ERROR: next cell index out of range: %d\n", idx);
}
printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild));
nFree = 0;
i = 0;
idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx>0 && idxu.aDisk[idx];
sprintf(range,"%d..%d", idx, idx+p->iSize-1);
nFree += SWAB16(pBt, p->iSize);
printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
i, range, SWAB16(pBt, p->iSize), nFree);
idx = SWAB16(pBt, p->iNext);
i++;
}
if( idx!=0 ){
printf("ERROR: next freeblock index out of range: %d\n", idx);
}
if( recursive && pPage->u.hdr.rightChild!=0 ){
idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 && idxu.aDisk[idx];
fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
idx = SWAB16(pBt, pCell->h.iNext);
}
fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
}
sqlitepager_unref(pPage);
return SQLITE_OK;
}
| btree.c | 3034 |
STATIC INT | fileBtreeCursorDump(BtCursor *pCur, int *aResult)
static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){
int cnt, idx;
MemPage *pPage = pCur->pPage;
Btree *pBt = pCur->pBt;
aResult[0] = sqlitepager_pagenumber(pPage);
aResult[1] = pCur->idx;
aResult[2] = pPage->nCell;
if( pCur->idx>=0 && pCur->idxnCell ){
aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]);
aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild);
}else{
aResult[3] = 0;
aResult[6] = 0;
}
aResult[4] = pPage->nFree;
cnt = 0;
idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx>0 && idxu.aDisk[idx])->iNext);
}
aResult[5] = cnt;
aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild);
return SQLITE_OK;
}
| btree.c | 3106 |
STATIC PAGER | fileBtreePager(Btree *pBt)
static Pager *fileBtreePager(Btree *pBt){
return pBt->pPager;
}
/*
** This structure is passed around through all the sanity checking routines
** in order to keep track of some global state information.
*/
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
Btree *pBt; /* The tree being checked out */
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
int nPage; /* Number of pages in the database */
int *anRef; /* Number of times each page is referenced */
char *zErrMsg; /* An error message. NULL of no errors seen. */
};
| btree.c | 3148 |
STATIC VOID | checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2)
static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
if( pCheck->zErrMsg ){
char *zOld = pCheck->zErrMsg;
pCheck->zErrMsg = 0;
sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
sqliteFree(zOld);
}else{
sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
}
}
| btree.c | 3169 |
STATIC INT | checkRef(IntegrityCk *pCheck, int iPage, char *zContext)
static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
if( iPage==0 ) return 1;
if( iPage>pCheck->nPage || iPage<0 ){
char zBuf[100];
sprintf(zBuf, "invalid page number %d", iPage);
checkAppendMsg(pCheck, zContext, zBuf);
return 1;
}
if( pCheck->anRef[iPage]==1 ){
char zBuf[100];
sprintf(zBuf, "2nd reference to page %d", iPage);
checkAppendMsg(pCheck, zContext, zBuf);
return 1;
}
return (pCheck->anRef[iPage]++)>1;
}
| btree.c | 3183 |
STATIC VOID | checkList( IntegrityCk *pCheck, int isFreeList, int iPage, int N, char *zContext )
static void checkList(
IntegrityCk *pCheck, /* Integrity checking context */
int isFreeList, /* True for a freelist. False for overflow page list */
int iPage, /* Page number for first page in the list */
int N, /* Expected number of pages in the list */
char *zContext /* Context for error messages */
){
int i;
char zMsg[100];
while( N-- > 0 ){
OverflowPage *pOvfl;
if( iPage<1 ){
sprintf(zMsg, "%d pages missing from overflow list", N+1);
checkAppendMsg(pCheck, zContext, zMsg);
break;
}
if( checkRef(pCheck, iPage, zContext) ) break;
if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
sprintf(zMsg, "failed to get page %d", iPage);
checkAppendMsg(pCheck, zContext, zMsg);
break;
}
if( isFreeList ){
FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload;
int n = SWAB32(pCheck->pBt, pInfo->nFree);
for(i=0; ipBt, pInfo->aFree[i]), zContext);
}
N -= n;
}
iPage = SWAB32(pCheck->pBt, pOvfl->iNext);
sqlitepager_unref(pOvfl);
}
}
| btree.c | 3208 |
STATIC INT | keyCompare( const char *zKey1, int nKey1, const char *zKey2, int nKey2 )
static int keyCompare(
const char *zKey1, int nKey1,
const char *zKey2, int nKey2
){
int min = nKey1>nKey2 ? nKey2 : nKey1;
int c = memcmp(zKey1, zKey2, min);
if( c==0 ){
c = nKey1 - nKey2;
}
return c;
}
| btree.c | 3247 |
STATIC INT | checkTreePage( IntegrityCk *pCheck, int iPage, MemPage *pParent, char *zParentContext, char *zLowerBound, int nLower, char *zUpperBound, int nUpper )
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
MemPage *pParent, /* Parent page */
char *zParentContext, /* Parent context */
char *zLowerBound, /* All keys should be greater than this, if not NULL */
int nLower, /* Number of characters in zLowerBound */
char *zUpperBound, /* All keys should be less than this, if not NULL */
int nUpper /* Number of characters in zUpperBound */
){
MemPage *pPage;
int i, rc, depth, d2, pgno;
char *zKey1, *zKey2;
int nKey1, nKey2;
BtCursor cur;
Btree *pBt;
char zMsg[100];
char zContext[100];
char hit[SQLITE_USABLE_SIZE];
/* Check that the page exists
*/
cur.pBt = pBt = pCheck->pBt;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
sprintf(zContext, "On tree page %d: ", iPage);
if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){
sprintf(zMsg, "unable to get the page. error code=%d", rc);
checkAppendMsg(pCheck, zContext, zMsg);
return 0;
}
if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){
sprintf(zMsg, "initPage() returns error code %d", rc);
checkAppendMsg(pCheck, zContext, zMsg);
sqlitepager_unref(pPage);
return 0;
}
/* Check out all the cells.
*/
depth = 0;
if( zLowerBound ){
zKey1 = sqliteMalloc( nLower+1 );
memcpy(zKey1, zLowerBound, nLower);
zKey1[nLower] = 0;
}else{
zKey1 = 0;
}
nKey1 = nLower;
cur.pPage = pPage;
for(i=0; inCell; i++){
Cell *pCell = pPage->apCell[i];
int sz;
/* Check payload overflow pages
*/
nKey2 = NKEY(pBt, pCell->h);
sz = nKey2 + NDATA(pBt, pCell->h);
sprintf(zContext, "On page %d cell %d: ", iPage, i);
if( sz>MX_LOCAL_PAYLOAD ){
int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE;
checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext);
}
/* Check that keys are in the right order
*/
cur.idx = i;
zKey2 = sqliteMallocRaw( nKey2+1 );
getPayload(&cur, 0, nKey2, zKey2);
if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){
checkAppendMsg(pCheck, zContext, "Key is out of order");
}
/* Check sanity of left child page.
*/
pgno = SWAB32(pBt, pCell->h.leftChild);
d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
depth = d2;
sqliteFree(zKey1);
zKey1 = zKey2;
nKey1 = nKey2;
}
pgno = SWAB32(pBt, pPage->u.hdr.rightChild);
sprintf(zContext, "On page %d at right child: ", iPage);
checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper);
sqliteFree(zKey1);
/* Check for complete coverage of the page
*/
memset(hit, 0, sizeof(hit));
memset(hit, 1, sizeof(PageHdr));
for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && iu.aDisk[i];
int j;
for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++;
i = SWAB16(pBt, pCell->h.iNext);
}
for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && iu.aDisk[i];
int j;
for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++;
i = SWAB16(pBt,pFBlk->iNext);
}
for(i=0; i1 ){
sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
checkAppendMsg(pCheck, zMsg, 0);
break;
}
}
/* Check that free space is kept to a minimum
*/
#if 0
if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){
sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree,
SQLITE_USABLE_SIZE/3);
checkAppendMsg(pCheck, zContext, zMsg);
}
#endif
sqlitepager_unref(pPage);
return depth;
}
| btree.c | 3264 |
CHAR | fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot)
char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
int i;
int nRef;
IntegrityCk sCheck;
nRef = *sqlitepager_stats(pBt->pPager);
if( lockBtree(pBt)!=SQLITE_OK ){
return sqliteStrDup("Unable to acquire a read lock on the database");
}
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = sqlitepager_pagecount(sCheck.pPager);
if( sCheck.nPage==0 ){
unlockBtreeIfUnused(pBt);
return 0;
}
sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
sCheck.anRef[1] = 1;
for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
sCheck.zErrMsg = 0;
/* Check the integrity of the freelist
*/
checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList),
SWAB32(pBt, pBt->page1->nFree), "Main freelist: ");
/* Check all the tables.
*/
for(i=0; ipPager) ){
char zBuf[100];
sprintf(zBuf,
"Outstanding page count goes from %d to %d during this analysis",
nRef, *sqlitepager_stats(pBt->pPager)
);
checkAppendMsg(&sCheck, zBuf, 0);
}
/* Clean up and report errors.
*/
sqliteFree(sCheck.anRef);
return sCheck.zErrMsg;
}
| btree.c | 3414 |
STATIC CONST CHAR | fileBtreeGetFilename(Btree *pBt)
static const char *fileBtreeGetFilename(Btree *pBt){
assert( pBt->pPager!=0 );
return sqlitepager_filename(pBt->pPager);
}
| btree.c | 3485 |
STATIC INT | fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom)
static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
int rc = SQLITE_OK;
Pgno i, nPage, nToPage;
if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR;
if( pBtTo->pCursor ) return SQLITE_BUSY;
memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE);
rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1);
nToPage = sqlitepager_pagecount(pBtTo->pPager);
nPage = sqlitepager_pagecount(pBtFrom->pPager);
for(i=2; rc==SQLITE_OK && i<=nPage; i++){
void *pPage;
rc = sqlitepager_get(pBtFrom->pPager, i, &pPage);
if( rc ) break;
rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage);
if( rc ) break;
sqlitepager_unref(pPage);
}
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
void *pPage;
rc = sqlitepager_get(pBtTo->pPager, i, &pPage);
if( rc ) break;
rc = sqlitepager_write(pPage);
sqlitepager_unref(pPage);
sqlitepager_dont_write(pBtTo->pPager, i);
}
if( !rc && nPagepPager, nPage);
}
if( rc ){
fileBtreeRollback(pBtTo);
}
return rc;
}
/*
** The following tables contain pointers to all of the interface
** routines for this implementation of the B*Tree backend. To
** substitute a different implemention of the backend, one has merely
** to provide pointers to alternative functions in similar tables.
*/
static BtOps sqliteBtreeOps = {
fileBtreeClose,
fileBtreeSetCacheSize,
fileBtreeSetSafetyLevel,
fileBtreeBeginTrans,
fileBtreeCommit,
fileBtreeRollback,
fileBtreeBeginCkpt,
fileBtreeCommitCkpt,
fileBtreeRollbackCkpt,
fileBtreeCreateTable,
fileBtreeCreateTable, /* Really sqliteBtreeCreateIndex() */
fileBtreeDropTable,
fileBtreeClearTable,
fileBtreeCursor,
fileBtreeGetMeta,
fileBtreeUpdateMeta,
fileBtreeIntegrityCheck,
fileBtreeGetFilename,
fileBtreeCopyFile,
fileBtreePager,
#ifdef SQLITE_TEST
fileBtreePageDump,
#endif
};
static BtCursorOps sqliteBtreeCursorOps = {
fileBtreeMoveto,
fileBtreeDelete,
fileBtreeInsert,
fileBtreeFirst,
fileBtreeLast,
fileBtreeNext,
fileBtreePrevious,
fileBtreeKeySize,
fileBtreeKey,
fileBtreeKeyCompare,
fileBtreeDataSize,
fileBtreeData,
fileBtreeCloseCursor,
#ifdef SQLITE_TEST
fileBtreeCursorDump,
#endif
};
| btree.c | 3493 |
btree_rb.c |
Type | Function | Source | Line |
STATIC INT | checkReadLocks(RbtCursor *pCur)
static int checkReadLocks(RbtCursor *pCur){
RbtCursor *p;
assert( pCur->wrFlag );
for(p=pCur->pTree->pCursors; p; p=p->pShared){
if( p!=pCur ){
if( p->wrFlag==0 ) return SQLITE_LOCKED;
p->pNode = 0;
}
}
return SQLITE_OK;
}
| btree_rb.c | 146 |
STATIC INT | key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2)
static int key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2)
{
int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2);
if( mcmp == 0){
if( nKey1 == nKey2 ) return 0;
return ((nKey1 < nKey2)?-1:1);
}
return ((mcmp>0)?1:-1);
}
| btree_rb.c | 172 |
STATIC VOID | leftRotate(BtRbTree *pTree, BtRbNode *pX)
static void leftRotate(BtRbTree *pTree, BtRbNode *pX)
{
BtRbNode *pY;
BtRbNode *pb;
pY = pX->pRight;
pb = pY->pLeft;
pY->pParent = pX->pParent;
if( pX->pParent ){
if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
else pX->pParent->pRight = pY;
}
pY->pLeft = pX;
pX->pParent = pY;
pX->pRight = pb;
if( pb ) pb->pParent = pX;
if( pTree->pHead == pX ) pTree->pHead = pY;
}
| btree_rb.c | 192 |
STATIC VOID | rightRotate(BtRbTree *pTree, BtRbNode *pX)
static void rightRotate(BtRbTree *pTree, BtRbNode *pX)
{
BtRbNode *pY;
BtRbNode *pb;
pY = pX->pLeft;
pb = pY->pRight;
pY->pParent = pX->pParent;
if( pX->pParent ){
if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
else pX->pParent->pRight = pY;
}
pY->pRight = pX;
pX->pParent = pY;
pX->pLeft = pb;
if( pb ) pb->pParent = pX;
if( pTree->pHead == pX ) pTree->pHead = pY;
}
| btree_rb.c | 224 |
STATIC CHAR | append_val(char * orig, char const * val)
static char *append_val(char * orig, char const * val){
char *z;
if( !orig ){
z = sqliteStrDup( val );
} else{
z = 0;
sqliteSetString(&z, orig, val, (char*)0);
sqliteFree( orig );
}
return z;
}
| btree_rb.c | 256 |
STATIC CHAR | append_node(char * orig, BtRbNode *pNode, int indent)
static char *append_node(char * orig, BtRbNode *pNode, int indent)
{
char buf[128];
int i;
for( i=0; iisBlack ){
orig = append_val(orig, " B \n");
}else{
orig = append_val(orig, " R \n");
}
orig = append_node( orig, pNode->pLeft, indent );
orig = append_node( orig, pNode->pRight, indent );
}else{
orig = append_val(orig, "\n");
}
return orig;
}
| btree_rb.c | 274 |
STATIC VOID | print_node(BtRbNode *pNode)
static void print_node(BtRbNode *pNode)
{
char * str = append_node(0, pNode, 0);
printf("%s", str);
/* Suppress a warning message about print_node() being unused */
(void)print_node;
}
| btree_rb.c | 306 |
STATIC VOID | check_redblack_tree(BtRbTree * tree, char ** msg)
static void check_redblack_tree(BtRbTree * tree, char ** msg)
{
BtRbNode *pNode;
/* 0 -> came from parent
* 1 -> came from left
* 2 -> came from right */
int prev_step = 0;
pNode = tree->pHead;
while( pNode ){
switch( prev_step ){
case 0:
if( pNode->pLeft ){
pNode = pNode->pLeft;
}else{
prev_step = 1;
}
break;
case 1:
if( pNode->pRight ){
pNode = pNode->pRight;
prev_step = 0;
}else{
prev_step = 2;
}
break;
case 2:
/* Check red-black property (1) */
if( !pNode->isBlack &&
( (pNode->pLeft && !pNode->pLeft->isBlack) ||
(pNode->pRight && !pNode->pRight->isBlack) )
){
char buf[128];
sprintf(buf, "Red node with red child at %p\n", pNode);
*msg = append_val(*msg, buf);
*msg = append_node(*msg, tree->pHead, 0);
*msg = append_val(*msg, "\n");
}
/* Check red-black property (2) */
{
int leftHeight = 0;
int rightHeight = 0;
if( pNode->pLeft ){
leftHeight += pNode->pLeft->nBlackHeight;
leftHeight += (pNode->pLeft->isBlack?1:0);
}
if( pNode->pRight ){
rightHeight += pNode->pRight->nBlackHeight;
rightHeight += (pNode->pRight->isBlack?1:0);
}
if( leftHeight != rightHeight ){
char buf[128];
sprintf(buf, "Different black-heights at %p\n", pNode);
*msg = append_val(*msg, buf);
*msg = append_node(*msg, tree->pHead, 0);
*msg = append_val(*msg, "\n");
}
pNode->nBlackHeight = leftHeight;
}
if( pNode->pParent ){
if( pNode == pNode->pParent->pLeft ) prev_step = 1;
else prev_step = 2;
}
pNode = pNode->pParent;
break;
default: assert(0);
}
}
}
| btree_rb.c | 320 |
STATIC VOID | do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
{
/* In the first iteration of this loop, pX points to the red node just
* inserted in the tree. If the parent of pX exists (pX is not the root
* node) and is red, then the properties of the red-black tree are
* violated.
*
* At the start of any subsequent iterations, pX points to a red node
* with a red parent. In all other respects the tree is a legal red-black
* binary tree. */
while( pX != pTree->pHead && !pX->pParent->isBlack ){
BtRbNode *pUncle;
BtRbNode *pGrandparent;
/* Grandparent of pX must exist and must be black. */
pGrandparent = pX->pParent->pParent;
assert( pGrandparent );
assert( pGrandparent->isBlack );
/* Uncle of pX may or may not exist. */
if( pX->pParent == pGrandparent->pLeft )
pUncle = pGrandparent->pRight;
else
pUncle = pGrandparent->pLeft;
/* If the uncle of pX exists and is red, we do the following:
* | |
* G(b) G(r)
* / \ / \
* U(r) P(r) U(b) P(b)
* \ \
* X(r) X(r)
*
* BEFORE AFTER
* pX is then set to G. If the parent of G is red, then the while loop
* will run again. */
if( pUncle && !pUncle->isBlack ){
pGrandparent->isBlack = 0;
pUncle->isBlack = 1;
pX->pParent->isBlack = 1;
pX = pGrandparent;
}else{
if( pX->pParent == pGrandparent->pLeft ){
if( pX == pX->pParent->pRight ){
/* If pX is a right-child, do the following transform, essentially
* to change pX into a left-child:
* | |
* G(b) G(b)
* / \ / \
* P(r) U(b) X(r) U(b)
* \ /
* X(r) P(r) <-- new X
*
* BEFORE AFTER
*/
pX = pX->pParent;
leftRotate(pTree, pX);
}
/* Do the following transform, which balances the tree :)
* | |
* G(b) P(b)
* / \ / \
* P(r) U(b) X(r) G(r)
* / \
* X(r) U(b)
*
* BEFORE AFTER
*/
assert( pGrandparent == pX->pParent->pParent );
pGrandparent->isBlack = 0;
pX->pParent->isBlack = 1;
rightRotate( pTree, pGrandparent );
}else{
/* This code is symetric to the illustrated case above. */
if( pX == pX->pParent->pLeft ){
pX = pX->pParent;
rightRotate(pTree, pX);
}
assert( pGrandparent == pX->pParent->pParent );
pGrandparent->isBlack = 0;
pX->pParent->isBlack = 1;
leftRotate( pTree, pGrandparent );
}
}
}
pTree->pHead->isBlack = 1;
}
| btree_rb.c | 401 |
STATIC VOID | do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
static
void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
{
BtRbNode *pSib;
/* TODO: Comment this code! */
while( pX != pTree->pHead && (!pX || pX->isBlack) ){
if( pX == pParent->pLeft ){
pSib = pParent->pRight;
if( pSib && !(pSib->isBlack) ){
pSib->isBlack = 1;
pParent->isBlack = 0;
leftRotate(pTree, pParent);
pSib = pParent->pRight;
}
if( !pSib ){
pX = pParent;
}else if(
(!pSib->pLeft || pSib->pLeft->isBlack) &&
(!pSib->pRight || pSib->pRight->isBlack) ) {
pSib->isBlack = 0;
pX = pParent;
}else{
if( (!pSib->pRight || pSib->pRight->isBlack) ){
if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
pSib->isBlack = 0;
rightRotate( pTree, pSib );
pSib = pParent->pRight;
}
pSib->isBlack = pParent->isBlack;
pParent->isBlack = 1;
if( pSib->pRight ) pSib->pRight->isBlack = 1;
leftRotate(pTree, pParent);
pX = pTree->pHead;
}
}else{
pSib = pParent->pLeft;
if( pSib && !(pSib->isBlack) ){
pSib->isBlack = 1;
pParent->isBlack = 0;
rightRotate(pTree, pParent);
pSib = pParent->pLeft;
}
if( !pSib ){
pX = pParent;
}else if(
(!pSib->pLeft || pSib->pLeft->isBlack) &&
(!pSib->pRight || pSib->pRight->isBlack) ){
pSib->isBlack = 0;
pX = pParent;
}else{
if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
if( pSib->pRight ) pSib->pRight->isBlack = 1;
pSib->isBlack = 0;
leftRotate( pTree, pSib );
pSib = pParent->pLeft;
}
pSib->isBlack = pParent->isBlack;
pParent->isBlack = 1;
if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
rightRotate(pTree, pParent);
pX = pTree->pHead;
}
}
pParent = pX->pParent;
}
if( pX ) pX->isBlack = 1;
}
| btree_rb.c | 498 |
STATIC VOID | btreeCreateTable(Rbtree* pRbtree, int n)
static void btreeCreateTable(Rbtree* pRbtree, int n)
{
BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree));
sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl);
}
| btree_rb.c | 582 |
STATIC VOID | btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp)
static void btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp)
{
assert( pRbtree->eTransState == TRANS_INCHECKPOINT ||
pRbtree->eTransState == TRANS_INTRANSACTION );
if( pRbtree->eTransState == TRANS_INTRANSACTION ){
pRollbackOp->pNext = pRbtree->pTransRollback;
pRbtree->pTransRollback = pRollbackOp;
}
if( pRbtree->eTransState == TRANS_INCHECKPOINT ){
if( !pRbtree->pCheckRollback ){
pRbtree->pCheckRollbackTail = pRollbackOp;
}
pRollbackOp->pNext = pRbtree->pCheckRollback;
pRbtree->pCheckRollback = pRollbackOp;
}
}
| btree_rb.c | 591 |
INT | sqliteRbtreeOpen( const char *zFilename, int mode, int nPg, Btree **ppBtree )
int sqliteRbtreeOpen(
const char *zFilename,
int mode,
int nPg,
Btree **ppBtree
){
Rbtree **ppRbtree = (Rbtree**)ppBtree;
*ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
if( sqlite_malloc_failed ) goto open_no_mem;
sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);
/* Create a binary tree for the SQLITE_MASTER table at location 2 */
btreeCreateTable(*ppRbtree, 2);
if( sqlite_malloc_failed ) goto open_no_mem;
(*ppRbtree)->next_idx = 3;
(*ppRbtree)->pOps = &sqliteRbtreeOps;
/* Set file type to 4; this is so that "attach ':memory:' as ...." does not
** think that the database in uninitialised and refuse to attach
*/
(*ppRbtree)->aMetaData[2] = 4;
return SQLITE_OK;
open_no_mem:
*ppBtree = 0;
return SQLITE_NOMEM;
}
| btree_rb.c | 612 |
STATIC INT | memRbtreeCreateTable(Rbtree* tree, int* n)
static int memRbtreeCreateTable(Rbtree* tree, int* n)
{
assert( tree->eTransState != TRANS_NONE );
*n = tree->next_idx++;
btreeCreateTable(tree, *n);
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
/* Set up the rollback structure (if we are not doing this as part of a
* rollback) */
if( tree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
if( pRollbackOp==0 ) return SQLITE_NOMEM;
pRollbackOp->eOp = ROLLBACK_DROP;
pRollbackOp->iTab = *n;
btreeLogRollbackOp(tree, pRollbackOp);
}
return SQLITE_OK;
}
| btree_rb.c | 640 |
STATIC INT | memRbtreeDropTable(Rbtree* tree, int n)
static int memRbtreeDropTable(Rbtree* tree, int n)
{
BtRbTree *pTree;
assert( tree->eTransState != TRANS_NONE );
memRbtreeClearTable(tree, n);
pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
assert(pTree);
assert( pTree->pCursors==0 );
sqliteFree(pTree);
if( tree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
if( pRollbackOp==0 ) return SQLITE_NOMEM;
pRollbackOp->eOp = ROLLBACK_CREATE;
pRollbackOp->iTab = n;
btreeLogRollbackOp(tree, pRollbackOp);
}
return SQLITE_OK;
}
| btree_rb.c | 665 |
STATIC INT | memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey, int nIgnore, int *pRes)
static int memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey,
int nIgnore, int *pRes)
{
assert(pCur);
if( !pCur->pNode ) {
*pRes = -1;
} else {
if( (pCur->pNode->nKey - nIgnore) < 0 ){
*pRes = -1;
}else{
*pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore,
pKey, nKey);
}
}
return SQLITE_OK;
}
| btree_rb.c | 690 |
STATIC INT | memRbtreeCursor( Rbtree* tree, int iTable, int wrFlag, RbtCursor **ppCur )
static int memRbtreeCursor(
Rbtree* tree,
int iTable,
int wrFlag,
RbtCursor **ppCur
){
RbtCursor *pCur;
assert(tree);
pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
pCur->pTree = sqliteHashFind(&tree->tblHash, 0, iTable);
assert( pCur->pTree );
pCur->pRbtree = tree;
pCur->iTree = iTable;
pCur->pOps = &sqliteRbtreeCursorOps;
pCur->wrFlag = wrFlag;
pCur->pShared = pCur->pTree->pCursors;
pCur->pTree->pCursors = pCur;
assert( (*ppCur)->pTree );
return SQLITE_OK;
}
| btree_rb.c | 708 |
STATIC INT | memRbtreeInsert( RbtCursor* pCur, const void *pKey, int nKey, const void *pDataInput, int nData )
static int memRbtreeInsert(
RbtCursor* pCur,
const void *pKey,
int nKey,
const void *pDataInput,
int nData
){
void * pData;
int match;
/* It is illegal to call sqliteRbtreeInsert() if we are
** not in a transaction */
assert( pCur->pRbtree->eTransState != TRANS_NONE );
/* Make sure some other cursor isn't trying to read this same table */
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
/* Take a copy of the input data now, in case we need it for the
* replace case */
pData = sqliteMallocRaw(nData);
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
memcpy(pData, pDataInput, nData);
/* Move the cursor to a node near the key to be inserted. If the key already
* exists in the table, then (match == 0). In this case we can just replace
* the data associated with the entry, we don't need to manipulate the tree.
*
* If there is no exact match, then the cursor points at what would be either
* the predecessor (match == -1) or successor (match == 1) of the
* searched-for key, were it to be inserted. The new node becomes a child of
* this node.
*
* The new node is initially red.
*/
memRbtreeMoveto( pCur, pKey, nKey, &match);
if( match ){
BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
if( pNode==0 ) return SQLITE_NOMEM;
pNode->nKey = nKey;
pNode->pKey = sqliteMallocRaw(nKey);
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
memcpy(pNode->pKey, pKey, nKey);
pNode->nData = nData;
pNode->pData = pData;
if( pCur->pNode ){
switch( match ){
case -1:
assert( !pCur->pNode->pRight );
pNode->pParent = pCur->pNode;
pCur->pNode->pRight = pNode;
break;
case 1:
assert( !pCur->pNode->pLeft );
pNode->pParent = pCur->pNode;
pCur->pNode->pLeft = pNode;
break;
default:
assert(0);
}
}else{
pCur->pTree->pHead = pNode;
}
/* Point the cursor at the node just inserted, as per SQLite requirements */
pCur->pNode = pNode;
/* A new node has just been inserted, so run the balancing code */
do_insert_balancing(pCur->pTree, pNode);
/* Set up a rollback-op in case we have to roll this operation back */
if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
if( pOp==0 ) return SQLITE_NOMEM;
pOp->eOp = ROLLBACK_DELETE;
pOp->iTab = pCur->iTree;
pOp->nKey = pNode->nKey;
pOp->pKey = sqliteMallocRaw( pOp->nKey );
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
memcpy( pOp->pKey, pNode->pKey, pOp->nKey );
btreeLogRollbackOp(pCur->pRbtree, pOp);
}
}else{
/* No need to insert a new node in the tree, as the key already exists.
* Just clobber the current nodes data. */
/* Set up a rollback-op in case we have to roll this operation back */
if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
if( pOp==0 ) return SQLITE_NOMEM;
pOp->iTab = pCur->iTree;
pOp->nKey = pCur->pNode->nKey;
pOp->pKey = sqliteMallocRaw( pOp->nKey );
if( sqlite_malloc_failed ) return SQLITE_NOMEM;
memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey );
pOp->nData = pCur->pNode->nData;
pOp->pData = pCur->pNode->pData;
pOp->eOp = ROLLBACK_INSERT;
btreeLogRollbackOp(pCur->pRbtree, pOp);
}else{
sqliteFree( pCur->pNode->pData );
}
/* Actually clobber the nodes data */
pCur->pNode->pData = pData;
pCur->pNode->nData = nData;
}
return SQLITE_OK;
}
| btree_rb.c | 737 |
STATIC INT | memRbtreeMoveto( RbtCursor* pCur, const void *pKey, int nKey, int *pRes )
static int memRbtreeMoveto(
RbtCursor* pCur,
const void *pKey,
int nKey,
int *pRes
){
BtRbNode *pTmp = 0;
pCur->pNode = pCur->pTree->pHead;
*pRes = -1;
while( pCur->pNode && *pRes ) {
*pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
pTmp = pCur->pNode;
switch( *pRes ){
case 1: /* cursor > key */
pCur->pNode = pCur->pNode->pLeft;
break;
case -1: /* cursor < key */
pCur->pNode = pCur->pNode->pRight;
break;
}
}
/* If (pCur->pNode == NULL), then we have failed to find a match. Set
* pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
* last node traversed in the search. In either case the relation ship
* between pTmp and the searched for key is already stored in *pRes. pTmp is
* either the successor or predecessor of the key we tried to move to. */
if( !pCur->pNode ) pCur->pNode = pTmp;
pCur->eSkip = SKIP_NONE;
return SQLITE_OK;
}
| btree_rb.c | 858 |
STATIC INT | memRbtreeDelete(RbtCursor* pCur)
static int memRbtreeDelete(RbtCursor* pCur)
{
BtRbNode *pZ; /* The one being deleted */
BtRbNode *pChild; /* The child of the spliced out node */
/* It is illegal to call sqliteRbtreeDelete() if we are
** not in a transaction */
assert( pCur->pRbtree->eTransState != TRANS_NONE );
/* Make sure some other cursor isn't trying to read this same table */
if( checkReadLocks(pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
pZ = pCur->pNode;
if( !pZ ){
return SQLITE_OK;
}
/* If we are not currently doing a rollback, set up a rollback op for this
* deletion */
if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
if( pOp==0 ) return SQLITE_NOMEM;
pOp->iTab = pCur->iTree;
pOp->nKey = pZ->nKey;
pOp->pKey = pZ->pKey;
pOp->nData = pZ->nData;
pOp->pData = pZ->pData;
pOp->eOp = ROLLBACK_INSERT;
btreeLogRollbackOp(pCur->pRbtree, pOp);
}
/* First do a standard binary-tree delete (node pZ is to be deleted). How
* to do this depends on how many children pZ has:
*
* If pZ has no children or one child, then splice out pZ. If pZ has two
* children, splice out the successor of pZ and replace the key and data of
* pZ with the key and data of the spliced out successor. */
if( pZ->pLeft && pZ->pRight ){
BtRbNode *pTmp;
int dummy;
pCur->eSkip = SKIP_NONE;
memRbtreeNext(pCur, &dummy);
assert( dummy == 0 );
if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
sqliteFree(pZ->pKey);
sqliteFree(pZ->pData);
}
pZ->pData = pCur->pNode->pData;
pZ->nData = pCur->pNode->nData;
pZ->pKey = pCur->pNode->pKey;
pZ->nKey = pCur->pNode->nKey;
pTmp = pZ;
pZ = pCur->pNode;
pCur->pNode = pTmp;
pCur->eSkip = SKIP_NEXT;
}else{
int res;
pCur->eSkip = SKIP_NONE;
memRbtreeNext(pCur, &res);
pCur->eSkip = SKIP_NEXT;
if( res ){
memRbtreeLast(pCur, &res);
memRbtreePrevious(pCur, &res);
pCur->eSkip = SKIP_PREV;
}
if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
sqliteFree(pZ->pKey);
sqliteFree(pZ->pData);
}
}
/* pZ now points at the node to be spliced out. This block does the
* splicing. */
{
BtRbNode **ppParentSlot = 0;
assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */
pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight);
if( pZ->pParent ){
assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
ppParentSlot = ((pZ == pZ->pParent->pLeft)
?&pZ->pParent->pLeft:&pZ->pParent->pRight);
*ppParentSlot = pChild;
}else{
pCur->pTree->pHead = pChild;
}
if( pChild ) pChild->pParent = pZ->pParent;
}
/* pZ now points at the spliced out node. pChild is the only child of pZ, or
* NULL if pZ has no children. If pZ is black, and not the tree root, then we
* will have violated the "same number of black nodes in every path to a
* leaf" property of the red-black tree. The code in do_delete_balancing()
* repairs this. */
if( pZ->isBlack ){
do_delete_balancing(pCur->pTree, pChild, pZ->pParent);
}
sqliteFree(pZ);
return SQLITE_OK;
}
| btree_rb.c | 906 |
STATIC INT | memRbtreeClearTable(Rbtree* tree, int n)
static int memRbtreeClearTable(Rbtree* tree, int n)
{
BtRbTree *pTree;
BtRbNode *pNode;
pTree = sqliteHashFind(&tree->tblHash, 0, n);
assert(pTree);
pNode = pTree->pHead;
while( pNode ){
if( pNode->pLeft ){
pNode = pNode->pLeft;
}
else if( pNode->pRight ){
pNode = pNode->pRight;
}
else {
BtRbNode *pTmp = pNode->pParent;
if( tree->eTransState == TRANS_ROLLBACK ){
sqliteFree( pNode->pKey );
sqliteFree( pNode->pData );
}else{
BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp));
if( pRollbackOp==0 ) return SQLITE_NOMEM;
pRollbackOp->eOp = ROLLBACK_INSERT;
pRollbackOp->iTab = n;
pRollbackOp->nKey = pNode->nKey;
pRollbackOp->pKey = pNode->pKey;
pRollbackOp->nData = pNode->nData;
pRollbackOp->pData = pNode->pData;
btreeLogRollbackOp(tree, pRollbackOp);
}
sqliteFree( pNode );
if( pTmp ){
if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
}
pNode = pTmp;
}
}
pTree->pHead = 0;
return SQLITE_OK;
}
| btree_rb.c | 1023 |
STATIC INT | memRbtreeFirst(RbtCursor* pCur, int *pRes)
static int memRbtreeFirst(RbtCursor* pCur, int *pRes)
{
if( pCur->pTree->pHead ){
pCur->pNode = pCur->pTree->pHead;
while( pCur->pNode->pLeft ){
pCur->pNode = pCur->pNode->pLeft;
}
}
if( pCur->pNode ){
*pRes = 0;
}else{
*pRes = 1;
}
pCur->eSkip = SKIP_NONE;
return SQLITE_OK;
}
| btree_rb.c | 1071 |
STATIC INT | memRbtreeLast(RbtCursor* pCur, int *pRes)
static int memRbtreeLast(RbtCursor* pCur, int *pRes)
{
if( pCur->pTree->pHead ){
pCur->pNode = pCur->pTree->pHead;
while( pCur->pNode->pRight ){
pCur->pNode = pCur->pNode->pRight;
}
}
if( pCur->pNode ){
*pRes = 0;
}else{
*pRes = 1;
}
pCur->eSkip = SKIP_NONE;
return SQLITE_OK;
}
| btree_rb.c | 1088 |
STATIC INT | memRbtreeNext(RbtCursor* pCur, int *pRes)
static int memRbtreeNext(RbtCursor* pCur, int *pRes)
{
if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
if( pCur->pNode->pRight ){
pCur->pNode = pCur->pNode->pRight;
while( pCur->pNode->pLeft )
pCur->pNode = pCur->pNode->pLeft;
}else{
BtRbNode * pX = pCur->pNode;
pCur->pNode = pX->pParent;
while( pCur->pNode && (pCur->pNode->pRight == pX) ){
pX = pCur->pNode;
pCur->pNode = pX->pParent;
}
}
}
pCur->eSkip = SKIP_NONE;
if( !pCur->pNode ){
*pRes = 1;
}else{
*pRes = 0;
}
return SQLITE_OK;
}
| btree_rb.c | 1105 |
STATIC INT | memRbtreePrevious(RbtCursor* pCur, int *pRes)
static int memRbtreePrevious(RbtCursor* pCur, int *pRes)
{
if( pCur->pNode && pCur->eSkip != SKIP_PREV ){
if( pCur->pNode->pLeft ){
pCur->pNode = pCur->pNode->pLeft;
while( pCur->pNode->pRight )
pCur->pNode = pCur->pNode->pRight;
}else{
BtRbNode * pX = pCur->pNode;
pCur->pNode = pX->pParent;
while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
pX = pCur->pNode;
pCur->pNode = pX->pParent;
}
}
}
pCur->eSkip = SKIP_NONE;
if( !pCur->pNode ){
*pRes = 1;
}else{
*pRes = 0;
}
return SQLITE_OK;
}
| btree_rb.c | 1138 |
STATIC INT | memRbtreeKeySize(RbtCursor* pCur, int *pSize)
static int memRbtreeKeySize(RbtCursor* pCur, int *pSize)
{
if( pCur->pNode ){
*pSize = pCur->pNode->nKey;
}else{
*pSize = 0;
}
return SQLITE_OK;
}
| btree_rb.c | 1165 |
STATIC INT | memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf)
static int memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf)
{
if( !pCur->pNode ) return 0;
if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
}else{
memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
amt = pCur->pNode->nKey-offset;
}
return amt;
}
| btree_rb.c | 1175 |
STATIC INT | memRbtreeDataSize(RbtCursor* pCur, int *pSize)
static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
{
if( pCur->pNode ){
*pSize = pCur->pNode->nData;
}else{
*pSize = 0;
}
return SQLITE_OK;
}
| btree_rb.c | 1187 |
STATIC INT | memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf)
static int memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf)
{
if( !pCur->pNode ) return 0;
if( (amt + offset) <= pCur->pNode->nData ){
memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
}else{
memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
amt = pCur->pNode->nData-offset;
}
return amt;
}
| btree_rb.c | 1197 |
STATIC INT | memRbtreeCloseCursor(RbtCursor* pCur)
static int memRbtreeCloseCursor(RbtCursor* pCur)
{
if( pCur->pTree->pCursors==pCur ){
pCur->pTree->pCursors = pCur->pShared;
}else{
RbtCursor *p = pCur->pTree->pCursors;
while( p && p->pShared!=pCur ){ p = p->pShared; }
assert( p!=0 );
if( p ){
p->pShared = pCur->pShared;
}
}
sqliteFree(pCur);
return SQLITE_OK;
}
| btree_rb.c | 1209 |
STATIC INT | memRbtreeGetMeta(Rbtree* tree, int* aMeta)
static int memRbtreeGetMeta(Rbtree* tree, int* aMeta)
{
memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META );
return SQLITE_OK;
}
| btree_rb.c | 1225 |
STATIC INT | memRbtreeUpdateMeta(Rbtree* tree, int* aMeta)
static int memRbtreeUpdateMeta(Rbtree* tree, int* aMeta)
{
memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META );
return SQLITE_OK;
}
| btree_rb.c | 1231 |
STATIC CHAR | memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot)
static char *memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot)
{
char * msg = 0;
HashElem *p;
for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
BtRbTree *pTree = sqliteHashData(p);
check_redblack_tree(pTree, &msg);
}
return msg;
}
| btree_rb.c | 1237 |
STATIC INT | memRbtreeSetCacheSize(Rbtree* tree, int sz)
static int memRbtreeSetCacheSize(Rbtree* tree, int sz)
{
return SQLITE_OK;
}
| btree_rb.c | 1255 |
STATIC INT | memRbtreeSetSafetyLevel(Rbtree *pBt, int level)
static int memRbtreeSetSafetyLevel(Rbtree *pBt, int level){
return SQLITE_OK;
}
| btree_rb.c | 1260 |
STATIC INT | memRbtreeBeginTrans(Rbtree* tree)
static int memRbtreeBeginTrans(Rbtree* tree)
{
if( tree->eTransState != TRANS_NONE )
return SQLITE_ERROR;
assert( tree->pTransRollback == 0 );
tree->eTransState = TRANS_INTRANSACTION;
return SQLITE_OK;
}
| btree_rb.c | 1264 |
STATIC VOID | deleteRollbackList(BtRollbackOp *pOp)
static void deleteRollbackList(BtRollbackOp *pOp){
while( pOp ){
BtRollbackOp *pTmp = pOp->pNext;
sqliteFree(pOp->pData);
sqliteFree(pOp->pKey);
sqliteFree(pOp);
pOp = pTmp;
}
}
| btree_rb.c | 1274 |
STATIC INT | memRbtreeCommit(Rbtree* tree)
static int memRbtreeCommit(Rbtree* tree){
/* Just delete pTransRollback and pCheckRollback */
deleteRollbackList(tree->pCheckRollback);
deleteRollbackList(tree->pTransRollback);
tree->pTransRollback = 0;
tree->pCheckRollback = 0;
tree->pCheckRollbackTail = 0;
tree->eTransState = TRANS_NONE;
return SQLITE_OK;
}
| btree_rb.c | 1287 |
STATIC INT | memRbtreeClose(Rbtree* tree)
static int memRbtreeClose(Rbtree* tree)
{
HashElem *p;
memRbtreeCommit(tree);
while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){
tree->eTransState = TRANS_ROLLBACK;
memRbtreeDropTable(tree, sqliteHashKeysize(p));
}
sqliteHashClear(&tree->tblHash);
sqliteFree(tree);
return SQLITE_OK;
}
| btree_rb.c | 1298 |
STATIC VOID | execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList)
static void execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList)
{
BtRollbackOp *pTmp;
RbtCursor cur;
int res;
cur.pRbtree = pRbtree;
cur.wrFlag = 1;
while( pList ){
switch( pList->eOp ){
case ROLLBACK_INSERT:
cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
assert(cur.pTree);
cur.iTree = pList->iTab;
cur.eSkip = SKIP_NONE;
memRbtreeInsert( &cur, pList->pKey,
pList->nKey, pList->pData, pList->nData );
break;
case ROLLBACK_DELETE:
cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
assert(cur.pTree);
cur.iTree = pList->iTab;
cur.eSkip = SKIP_NONE;
memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
assert(res == 0);
memRbtreeDelete( &cur );
break;
case ROLLBACK_CREATE:
btreeCreateTable(pRbtree, pList->iTab);
break;
case ROLLBACK_DROP:
memRbtreeDropTable(pRbtree, pList->iTab);
break;
default:
assert(0);
}
sqliteFree(pList->pKey);
sqliteFree(pList->pData);
pTmp = pList->pNext;
sqliteFree(pList);
pList = pTmp;
}
}
| btree_rb.c | 1314 |
STATIC INT | memRbtreeRollback(Rbtree* tree)
static int memRbtreeRollback(Rbtree* tree)
{
tree->eTransState = TRANS_ROLLBACK;
execute_rollback_list(tree, tree->pCheckRollback);
execute_rollback_list(tree, tree->pTransRollback);
tree->pTransRollback = 0;
tree->pCheckRollback = 0;
tree->pCheckRollbackTail = 0;
tree->eTransState = TRANS_NONE;
return SQLITE_OK;
}
| btree_rb.c | 1361 |
STATIC INT | memRbtreeBeginCkpt(Rbtree* tree)
static int memRbtreeBeginCkpt(Rbtree* tree)
{
if( tree->eTransState != TRANS_INTRANSACTION )
return SQLITE_ERROR;
assert( tree->pCheckRollback == 0 );
assert( tree->pCheckRollbackTail == 0 );
tree->eTransState = TRANS_INCHECKPOINT;
return SQLITE_OK;
}
| btree_rb.c | 1373 |
STATIC INT | memRbtreeCommitCkpt(Rbtree* tree)
static int memRbtreeCommitCkpt(Rbtree* tree)
{
if( tree->eTransState == TRANS_INCHECKPOINT ){
if( tree->pCheckRollback ){
tree->pCheckRollbackTail->pNext = tree->pTransRollback;
tree->pTransRollback = tree->pCheckRollback;
tree->pCheckRollback = 0;
tree->pCheckRollbackTail = 0;
}
tree->eTransState = TRANS_INTRANSACTION;
}
return SQLITE_OK;
}
| btree_rb.c | 1384 |
STATIC INT | memRbtreeRollbackCkpt(Rbtree* tree)
static int memRbtreeRollbackCkpt(Rbtree* tree)
{
if( tree->eTransState != TRANS_INCHECKPOINT ) return SQLITE_OK;
tree->eTransState = TRANS_ROLLBACK;
execute_rollback_list(tree, tree->pCheckRollback);
tree->pCheckRollback = 0;
tree->pCheckRollbackTail = 0;
tree->eTransState = TRANS_INTRANSACTION;
return SQLITE_OK;
}
| btree_rb.c | 1398 |
STATIC INT | memRbtreePageDump(Rbtree* tree, int pgno, int rec)
static int memRbtreePageDump(Rbtree* tree, int pgno, int rec)
{
assert(!"Cannot call sqliteRbtreePageDump");
return SQLITE_OK;
}
| btree_rb.c | 1410 |
STATIC INT | memRbtreeCursorDump(RbtCursor* pCur, int* aRes)
static int memRbtreeCursorDump(RbtCursor* pCur, int* aRes)
{
assert(!"Cannot call sqliteRbtreeCursorDump");
return SQLITE_OK;
}
| btree_rb.c | 1416 |
STATIC STRUCT PAGER | memRbtreePager(Rbtree* tree)
static struct Pager *memRbtreePager(Rbtree* tree)
{
return 0;
}
| btree_rb.c | 1423 |
STATIC CONST CHAR | memRbtreeGetFilename(Rbtree *pBt)
static const char *memRbtreeGetFilename(Rbtree *pBt){
return 0; /* A NULL return indicates there is no underlying file */
}
| btree_rb.c | 1428 |
STATIC INT | memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2)
static int memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2){
return SQLITE_INTERNAL; /* Not implemented */
}
static BtOps sqliteRbtreeOps = {
(int(*)(Btree*)) memRbtreeClose,
(int(*)(Btree*,int)) memRbtreeSetCacheSize,
(int(*)(Btree*,int)) memRbtreeSetSafetyLevel,
(int(*)(Btree*)) memRbtreeBeginTrans,
(int(*)(Btree*)) memRbtreeCommit,
(int(*)(Btree*)) memRbtreeRollback,
(int(*)(Btree*)) memRbtreeBeginCkpt,
(int(*)(Btree*)) memRbtreeCommitCkpt,
(int(*)(Btree*)) memRbtreeRollbackCkpt,
(int(*)(Btree*,int*)) memRbtreeCreateTable,
(int(*)(Btree*,int*)) memRbtreeCreateTable,
(int(*)(Btree*,int)) memRbtreeDropTable,
(int(*)(Btree*,int)) memRbtreeClearTable,
(int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor,
(int(*)(Btree*,int*)) memRbtreeGetMeta,
(int(*)(Btree*,int*)) memRbtreeUpdateMeta,
(char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
(const char*(*)(Btree*)) memRbtreeGetFilename,
(int(*)(Btree*,Btree*)) memRbtreeCopyFile,
(struct Pager*(*)(Btree*)) memRbtreePager,
#ifdef SQLITE_TEST
(int(*)(Btree*,int,int)) memRbtreePageDump,
#endif
};
static BtCursorOps sqliteRbtreeCursorOps = {
(int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto,
(int(*)(BtCursor*)) memRbtreeDelete,
(int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert,
(int(*)(BtCursor*,int*)) memRbtreeFirst,
(int(*)(BtCursor*,int*)) memRbtreeLast,
(int(*)(BtCursor*,int*)) memRbtreeNext,
(int(*)(BtCursor*,int*)) memRbtreePrevious,
(int(*)(BtCursor*,int*)) memRbtreeKeySize,
(int(*)(BtCursor*,int,int,char*)) memRbtreeKey,
(int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare,
(int(*)(BtCursor*,int*)) memRbtreeDataSize,
(int(*)(BtCursor*,int,int,char*)) memRbtreeData,
(int(*)(BtCursor*)) memRbtreeCloseCursor,
#ifdef SQLITE_TEST
(int(*)(BtCursor*,int*)) memRbtreeCursorDump,
#endif
};
| btree_rb.c | 1435 |
build.c |
Type | Function | Source | Line |
VOID | sqliteBeginParse(Parse *pParse, int explainFlag)
void sqliteBeginParse(Parse *pParse, int explainFlag){
sqlite *db = pParse->db;
int i;
pParse->explain = explainFlag;
if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
int rc = sqliteInit(db, &pParse->zErrMsg);
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
}
}
for(i=0; inDb; i++){
DbClearProperty(db, i, DB_Locked);
if( !db->aDb[i].inTrans ){
DbClearProperty(db, i, DB_Cookie);
}
}
pParse->nVar = 0;
}
| build.c | 31 |
VOID | sqliteExec(Parse *pParse)
void sqliteExec(Parse *pParse){
sqlite *db = pParse->db;
Vdbe *v = pParse->pVdbe;
if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
}
if( sqlite_malloc_failed ) return;
if( v && pParse->nErr==0 ){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqliteVdbeTrace(v, trace);
sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);
pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
pParse->nTab = 0;
pParse->nMem = 0;
pParse->nSet = 0;
pParse->nAgg = 0;
pParse->nVar = 0;
}
| build.c | 57 |
TABLE | sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase)
Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
Table *p = 0;
int i;
for(i=0; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;
p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
if( p ) break;
}
return p;
}
| build.c | 91 |
TABLE | sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase)
Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){
Table *p;
p = sqliteFindTable(pParse->db, zName, zDbase);
if( p==0 ){
if( zDbase ){
sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
}else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){
sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
zName, zDbase);
}else{
sqliteErrorMsg(pParse, "no such table: %s", zName);
}
}
return p;
}
| build.c | 117 |
INDEX | sqliteFindIndex(sqlite *db, const char *zName, const char *zDb)
Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
Index *p = 0;
int i;
for(i=0; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;
p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
if( p ) break;
}
return p;
}
| build.c | 145 |
STATIC VOID | sqliteDeleteIndex(sqlite *db, Index *p)
static void sqliteDeleteIndex(sqlite *db, Index *p){
Index *pOld;
assert( db!=0 && p->zName!=0 );
pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,
strlen(p->zName)+1, 0);
if( pOld!=0 && pOld!=p ){
sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
strlen(pOld->zName)+1, pOld);
}
sqliteFree(p);
}
| build.c | 169 |
VOID | sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex)
void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
if( pIndex->pTable->pIndex==pIndex ){
pIndex->pTable->pIndex = pIndex->pNext;
}else{
Index *p;
for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
if( p && p->pNext==pIndex ){
p->pNext = pIndex->pNext;
}
}
sqliteDeleteIndex(db, pIndex);
}
| build.c | 190 |
VOID | sqliteResetInternalSchema(sqlite *db, int iDb)
void sqliteResetInternalSchema(sqlite *db, int iDb){
HashElem *pElem;
Hash temp1;
Hash temp2;
int i, j;
assert( iDb>=0 && iDbnDb );
db->flags &= ~SQLITE_Initialized;
for(i=iDb; inDb; i++){
Db *pDb = &db->aDb[i];
temp1 = pDb->tblHash;
temp2 = pDb->trigHash;
sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
sqliteHashClear(&pDb->aFKey);
sqliteHashClear(&pDb->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
Trigger *pTrigger = sqliteHashData(pElem);
sqliteDeleteTrigger(pTrigger);
}
sqliteHashClear(&temp2);
sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
sqliteDeleteTable(db, pTab);
}
sqliteHashClear(&temp1);
DbClearProperty(db, i, DB_SchemaLoaded);
if( iDb>0 ) return;
}
assert( iDb==0 );
db->flags &= ~SQLITE_InternChanges;
/* If one or more of the auxiliary database files has been closed,
** then remove then from the auxiliary database list. We take the
** opportunity to do this here since we have just deleted all of the
** schema hash tables and therefore do not have to make any changes
** to any of those tables.
*/
for(i=0; inDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
pDb->pAux = 0;
}
}
for(i=j=2; inDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
sqliteFree(pDb->zName);
pDb->zName = 0;
continue;
}
if( jaDb[j] = db->aDb[i];
}
j++;
}
memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
db->nDb = j;
if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
sqliteFree(db->aDb);
db->aDb = db->aDbStatic;
}
}
| build.c | 208 |
VOID | sqliteRollbackInternalChanges(sqlite *db)
void sqliteRollbackInternalChanges(sqlite *db){
if( db->flags & SQLITE_InternChanges ){
sqliteResetInternalSchema(db, 0);
}
}
| build.c | 284 |
VOID | sqliteCommitInternalChanges(sqlite *db)
void sqliteCommitInternalChanges(sqlite *db){
db->aDb[0].schema_cookie = db->next_cookie;
db->flags &= ~SQLITE_InternChanges;
}
| build.c | 295 |
VOID | sqliteDeleteTable(sqlite *db, Table *pTable)
void sqliteDeleteTable(sqlite *db, Table *pTable){
int i;
Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey;
if( pTable==0 ) return;
/* Delete all indices associated with this table
*/
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
pNext = pIndex->pNext;
assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );
sqliteDeleteIndex(db, pIndex);
}
/* Delete all foreign keys associated with this table. The keys
** should have already been unlinked from the db->aFKey hash table
*/
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
pNextFKey = pFKey->pNextFrom;
assert( pTable->iDbnDb );
assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
sqliteFree(pFKey);
}
/* Delete the Table structure itself.
*/
for(i=0; inCol; i++){
sqliteFree(pTable->aCol[i].zName);
sqliteFree(pTable->aCol[i].zDflt);
sqliteFree(pTable->aCol[i].zType);
}
sqliteFree(pTable->zName);
sqliteFree(pTable->aCol);
sqliteSelectDelete(pTable->pSelect);
sqliteFree(pTable);
}
| build.c | 303 |
STATIC VOID | sqliteUnlinkAndDeleteTable(sqlite *db, Table *p)
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
Table *pOld;
FKey *pF1, *pF2;
int i = p->iDb;
assert( db!=0 );
pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
assert( pOld==0 || pOld==p );
for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
int nTo = strlen(pF1->zTo) + 1;
pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
if( pF2==pF1 ){
sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
}else{
while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
if( pF2 ){
pF2->pNextTo = pF1->pNextTo;
}
}
}
sqliteDeleteTable(db, p);
}
| build.c | 357 |
CHAR | sqliteTableNameFromToken(Token *pName)
char *sqliteTableNameFromToken(Token *pName){
char *zName = sqliteStrNDup(pName->z, pName->n);
sqliteDequote(zName);
return zName;
}
| build.c | 383 |
VOID | sqliteOpenMasterTable(Vdbe *v, int isTemp)
void sqliteOpenMasterTable(Vdbe *v, int isTemp){
sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
}
| build.c | 395 |
VOID | sqliteStartTable( Parse *pParse, Token *pStart, Token *pName, int isTemp, int isView )
void sqliteStartTable(
Parse *pParse, /* Parser context */
Token *pStart, /* The "CREATE" token */
Token *pName, /* Name of table or view to create */
int isTemp, /* True if this is a TEMP table */
int isView /* True if this is a VIEW */
){
Table *pTable;
Index *pIdx;
char *zName;
sqlite *db = pParse->db;
Vdbe *v;
int iDb;
pParse->sFirstToken = *pStart;
zName = sqliteTableNameFromToken(pName);
if( zName==0 ) return;
if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( (isTemp & 1)==isTemp );
{
int code;
char *zDb = isTemp ? "temp" : "main";
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
sqliteFree(zName);
return;
}
if( isView ){
if( isTemp ){
code = SQLITE_CREATE_TEMP_VIEW;
}else{
code = SQLITE_CREATE_VIEW;
}
}else{
if( isTemp ){
code = SQLITE_CREATE_TEMP_TABLE;
}else{
code = SQLITE_CREATE_TABLE;
}
}
if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){
sqliteFree(zName);
return;
}
}
#endif
/* Before trying to create a temporary table, make sure the Btree for
** holding temporary tables is open.
*/
if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);
if( rc!=SQLITE_OK ){
sqliteErrorMsg(pParse, "unable to open a temporary database "
"file for storing temporary tables");
pParse->nErr++;
return;
}
if( db->flags & SQLITE_InTrans ){
rc = sqliteBtreeBeginTrans(db->aDb[1].pBt);
if( rc!=SQLITE_OK ){
sqliteErrorMsg(pParse, "unable to get a write lock on "
"the temporary database file");
return;
}
}
}
/* Make sure the new table name does not collide with an existing
** index or table name. Issue an error message if it does.
**
** If we are re-reading the sqlite_master table because of a schema
** change and a new permanent table is found whose name collides with
** an existing temporary table, that is not an error.
*/
pTable = sqliteFindTable(db, zName, 0);
iDb = isTemp ? 1 : db->init.iDb;
if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
sqliteErrorMsg(pParse, "table %T already exists", pName);
sqliteFree(zName);
return;
}
if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
(pIdx->iDb==0 || !db->init.busy) ){
sqliteErrorMsg(pParse, "there is already an index named %s", zName);
sqliteFree(zName);
return;
}
pTable = sqliteMalloc( sizeof(Table) );
if( pTable==0 ){
sqliteFree(zName);
return;
}
pTable->zName = zName;
pTable->nCol = 0;
pTable->aCol = 0;
pTable->iPKey = -1;
pTable->pIndex = 0;
pTable->iDb = iDb;
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
pParse->pNewTable = pTable;
/* Begin generating the code that will insert the table record into
** the SQLITE_MASTER table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
** indices to be created and the table record must come before the
** indices. Hence, the record number for the table must be allocated
** now.
*/
if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
sqliteBeginWriteOperation(pParse, 0, isTemp);
if( !isTemp ){
sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
}
sqliteOpenMasterTable(v, isTemp);
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
}
}
| build.c | 406 |
VOID | sqliteAddColumn(Parse *pParse, Token *pName)
void sqliteAddColumn(Parse *pParse, Token *pName){
Table *p;
int i;
char *z = 0;
Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
sqliteSetNString(&z, pName->z, pName->n, 0);
if( z==0 ) return;
sqliteDequote(z);
for(i=0; inCol; i++){
if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){
sqliteErrorMsg(pParse, "duplicate column name: %s", z);
sqliteFree(z);
return;
}
}
if( (p->nCol & 0x7)==0 ){
Column *aNew;
aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
if( aNew==0 ) return;
p->aCol = aNew;
}
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
pCol->sortOrder = SQLITE_SO_NUM;
p->nCol++;
}
| build.c | 548 |
VOID | sqliteAddNotNull(Parse *pParse, int onError)
void sqliteAddNotNull(Parse *pParse, int onError){
Table *p;
int i;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i>=0 ) p->aCol[i].notNull = onError;
}
| build.c | 585 |
VOID | sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast)
void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
Table *p;
int i, j;
int n;
char *z, **pz;
Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
pz = &pCol->zType;
n = pLast->n + Addr(pLast->z) - Addr(pFirst->z);
sqliteSetNString(pz, pFirst->z, n, 0);
z = *pz;
if( z==0 ) return;
for(i=j=0; z[i]; i++){
int c = z[i];
if( isspace(c) ) continue;
z[j++] = c;
}
z[j] = 0;
if( pParse->db->file_format>=4 ){
pCol->sortOrder = sqliteCollateType(z, n);
}else{
pCol->sortOrder = SQLITE_SO_NUM;
}
}
| build.c | 599 |
VOID | sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag)
void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
Table *p;
int i;
char **pz;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pz = &p->aCol[i].zDflt;
if( minusFlag ){
sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
}else{
sqliteSetNString(pz, pVal->z, pVal->n, 0);
}
sqliteDequote(*pz);
}
| build.c | 636 |
VOID | sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError)
void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
if( pTab==0 ) goto primary_key_exit;
if( pTab->hasPrimKey ){
sqliteErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
pTab->hasPrimKey = 1;
if( pList==0 ){
iCol = pTab->nCol - 1;
pTab->aCol[iCol].isPrimKey = 1;
}else{
for(i=0; inId; i++){
for(iCol=0; iColnCol; iCol++){
if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break;
}
if( iColnCol ) pTab->aCol[iCol].isPrimKey = 1;
}
if( pList->nId>1 ) iCol = -1;
}
if( iCol>=0 && iColnCol ){
zType = pTab->aCol[iCol].zType;
}
if( pParse->db->file_format>=1 &&
zType && sqliteStrICmp(zType, "INTEGER")==0 ){
pTab->iPKey = iCol;
pTab->keyConf = onError;
}else{
sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
pList = 0;
}
primary_key_exit:
sqliteIdListDelete(pList);
return;
}
| build.c | 660 |
INT | sqliteCollateType(const char *zType, int nType)
int sqliteCollateType(const char *zType, int nType){
int i;
for(i=0; ibuild.c | 720 | |
VOID | sqliteAddCollateType(Parse *pParse, int collType)
void sqliteAddCollateType(Parse *pParse, int collType){
Table *p;
int i;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i>=0 ) p->aCol[i].sortOrder = collType;
}
| build.c | 745 |
VOID | sqliteChangeCookie(sqlite *db, Vdbe *v)
void sqliteChangeCookie(sqlite *db, Vdbe *v){
if( db->next_cookie==db->aDb[0].schema_cookie ){
unsigned char r;
sqliteRandomness(1, &r);
db->next_cookie = db->aDb[0].schema_cookie + r + 1;
db->flags |= SQLITE_InternChanges;
sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
}
}
| build.c | 759 |
STATIC INT | identLength(const char *z)
static int identLength(const char *z){
int n;
int needQuote = 0;
for(n=0; *z; n++, z++){
if( *z=='\'' ){ n++; needQuote=1; }
}
return n + needQuote*2;
}
| build.c | 787 |
STATIC VOID | identPut(char *z, int *pIdx, char *zIdent)
static void identPut(char *z, int *pIdx, char *zIdent){
int i, j, needQuote;
i = *pIdx;
for(j=0; zIdent[j]; j++){
if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
}
needQuote = zIdent[j]!=0 || isdigit(zIdent[0])
|| sqliteKeywordCode(zIdent, j)!=TK_ID;
if( needQuote ) z[i++] = '\'';
for(j=0; zIdent[j]; j++){
z[i++] = zIdent[j];
if( zIdent[j]=='\'' ) z[i++] = '\'';
}
if( needQuote ) z[i++] = '\'';
z[i] = 0;
*pIdx = i;
}
| build.c | 801 |
STATIC CHAR | createTableStmt(Table *p)
static char *createTableStmt(Table *p){
int i, k, n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
n = 0;
for(i=0; inCol; i++){
n += identLength(p->aCol[i].zName);
}
n += identLength(p->zName);
if( n<40 ){
zSep = "";
zSep2 = ",";
zEnd = ")";
}else{
zSep = "\n ";
zSep2 = ",\n ";
zEnd = "\n)";
}
n += 35 + 6*p->nCol;
zStmt = sqliteMallocRaw( n );
if( zStmt==0 ) return 0;
strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
k = strlen(zStmt);
identPut(zStmt, &k, p->zName);
zStmt[k++] = '(';
for(i=0; inCol; i++){
strcpy(&zStmt[k], zSep);
k += strlen(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, p->aCol[i].zName);
}
strcpy(&zStmt[k], zEnd);
return zStmt;
}
| build.c | 823 |
VOID | sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect)
void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
Table *p;
sqlite *db = pParse->db;
if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return;
p = pParse->pNewTable;
if( p==0 ) return;
/* If the table is generated from a SELECT, then construct the
** list of columns and the text of the table.
*/
if( pSelect ){
Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqliteDeleteTable(0, pSelTab);
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" or "sqlite_temp_master" table on the disk.
** So do not write to the disk again. Extract the root page number
** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.)
*/
if( db->init.busy ){
p->tnum = db->init.newTnum;
}
/* If not initializing, then create a record for the new table
** in the SQLITE_MASTER table of the database. The record number
** for the new table entry should already be on the stack.
**
** If this is a TEMPORARY table, write the entry into the auxiliary
** file instead of into the main database file.
*/
if( !db->init.busy ){
int n;
Vdbe *v;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( p->pSelect==0 ){
/* A regular table */
sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
}else{
/* A view */
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
}
p->tnum = 0;
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
sqliteVdbeAddOp(v, OP_Dup, 4, 0);
sqliteVdbeAddOp(v, OP_String, 0, 0);
if( pSelect ){
char *z = createTableStmt(p);
n = z ? strlen(z) : 0;
sqliteVdbeChangeP3(v, -1, z, n);
sqliteFree(z);
}else{
assert( pEnd!=0 );
n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
}
sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
if( !p->iDb ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
if( pSelect ){
sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
pParse->nTab = 2;
sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
}
sqliteEndWriteOperation(pParse);
}
/* Add the table to the in-memory representation of the database.
*/
if( pParse->explain==0 && pParse->nErr==0 ){
Table *pOld;
FKey *pFKey;
pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash,
p->zName, strlen(p->zName)+1, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
int nTo = strlen(pFKey->zTo) + 1;
pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
}
pParse->pNewTable = 0;
db->nTable++;
db->flags |= SQLITE_InternChanges;
}
}
| build.c | 863 |
VOID | sqliteCreateView( Parse *pParse, Token *pBegin, Token *pName, Select *pSelect, int isTemp )
void sqliteCreateView(
Parse *pParse, /* The parsing context */
Token *pBegin, /* The CREATE token that begins the statement */
Token *pName, /* The token that holds the name of the view */
Select *pSelect, /* A SELECT statement that will become the new view */
int isTemp /* TRUE for a TEMPORARY view */
){
Table *p;
int n;
const char *z;
Token sEnd;
DbFixer sFix;
sqliteStartTable(pParse, pBegin, pName, isTemp, 1);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
sqliteSelectDelete(pSelect);
return;
}
if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName)
&& sqliteFixSelect(&sFix, pSelect)
){
sqliteSelectDelete(pSelect);
return;
}
/* Make a copy of the entire SELECT statement that defines the view.
** This will force all the Expr.token.z values to be dynamically
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite_exec() call returns.
*/
p->pSelect = sqliteSelectDup(pSelect);
sqliteSelectDelete(pSelect);
if( !pParse->db->init.busy ){
sqliteViewGetColumnNames(pParse, p);
}
/* Locate the end of the CREATE VIEW statement. Make sEnd point to
** the end.
*/
sEnd = pParse->sLastToken;
if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
sEnd.z += sEnd.n;
}
sEnd.n = 0;
n = sEnd.z - pBegin->z;
z = pBegin->z;
while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
sEnd.z = &z[n-1];
sEnd.n = 1;
/* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
sqliteEndTable(pParse, &sEnd, 0);
return;
}
| build.c | 989 |
INT | sqliteViewGetColumnNames(Parse *pParse, Table *pTable)
int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
ExprList *pEList;
Select *pSel;
Table *pSelTab;
int nErr = 0;
assert( pTable );
/* A positive nCol means the columns names for this view are
** already known.
*/
if( pTable->nCol>0 ) return 0;
/* A negative nCol is a special marker meaning that we are currently
** trying to compute the column names. If we enter this routine with
** a negative nCol, it means two or more views form a loop, like this:
**
** CREATE VIEW one AS SELECT * FROM two;
** CREATE VIEW two AS SELECT * FROM one;
**
** 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( pTable->nCol<0 ){
sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
return 1;
}
/* If we get this far, it means we need to compute the table names.
*/
assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
pSel = pTable->pSelect;
/* Note that the call to sqliteResultSetOfSelect() will expand any
** "*" elements in this list. But we will need to restore the list
** back to its original configuration afterwards, so we save a copy of
** the original in pEList.
*/
pEList = pSel->pEList;
pSel->pEList = sqliteExprListDup(pEList);
if( pSel->pEList==0 ){
pSel->pEList = pEList;
return 1; /* Malloc failed */
}
pTable->nCol = -1;
pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel);
if( pSelTab ){
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqliteDeleteTable(0, pSelTab);
DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
}else{
pTable->nCol = 0;
nErr++;
}
sqliteSelectUnbind(pSel);
sqliteExprListDelete(pSel->pEList);
pSel->pEList = pEList;
return nErr;
}
| build.c | 1048 |
STATIC VOID | sqliteViewResetColumnNames(Table *pTable)
static void sqliteViewResetColumnNames(Table *pTable){
int i;
Column *pCol;
assert( pTable!=0 && pTable->pSelect!=0 );
for(i=0, pCol=pTable->aCol; inCol; i++, pCol++){
sqliteFree(pCol->zName);
sqliteFree(pCol->zDflt);
sqliteFree(pCol->zType);
}
sqliteFree(pTable->aCol);
pTable->aCol = 0;
pTable->nCol = 0;
}
| build.c | 1117 |
STATIC VOID | sqliteViewResetAll(sqlite *db, int idx)
static void sqliteViewResetAll(sqlite *db, int idx){
HashElem *i;
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
if( pTab->pSelect ){
sqliteViewResetColumnNames(pTab);
}
}
DbClearProperty(db, idx, DB_UnresetViews);
}
| build.c | 1139 |
TABLE | sqliteTableFromToken(Parse *pParse, Token *pTok)
Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
char *zName;
Table *pTab;
zName = sqliteTableNameFromToken(pTok);
if( zName==0 ) return 0;
pTab = sqliteFindTable(pParse->db, zName, 0);
sqliteFree(zName);
if( pTab==0 ){
sqliteErrorMsg(pParse, "no such table: %T", pTok);
}
return pTab;
}
| build.c | 1154 |
VOID | sqliteDropTable(Parse *pParse, Token *pName, int isView)
void sqliteDropTable(Parse *pParse, Token *pName, int isView){
Table *pTable;
Vdbe *v;
int base;
sqlite *db = pParse->db;
int iDb;
if( pParse->nErr || sqlite_malloc_failed ) return;
pTable = sqliteTableFromToken(pParse, pName);
if( pTable==0 ) return;
iDb = pTable->iDb;
assert( iDb>=0 && iDbnDb );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code;
const char *zTab = SCHEMA_TABLE(pTable->iDb);
const char *zDb = db->aDb[pTable->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
return;
}
if( isView ){
if( iDb==1 ){
code = SQLITE_DROP_TEMP_VIEW;
}else{
code = SQLITE_DROP_VIEW;
}
}else{
if( iDb==1 ){
code = SQLITE_DROP_TEMP_TABLE;
}else{
code = SQLITE_DROP_TABLE;
}
}
if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){
return;
}
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){
return;
}
}
#endif
if( pTable->readOnly ){
sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName);
pParse->nErr++;
return;
}
if( isView && pTable->pSelect==0 ){
sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName);
return;
}
if( !isView && pTable->pSelect ){
sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName);
return;
}
/* Generate code to remove the table from the master table
** on disk.
*/
v = sqliteGetVdbe(pParse);
if( v ){
static VdbeOpList dropTable[] = {
{ OP_Rewind, 0, ADDR(8), 0},
{ OP_String, 0, 0, 0}, /* 1 */
{ OP_MemStore, 1, 1, 0},
{ OP_MemLoad, 1, 0, 0}, /* 3 */
{ OP_Column, 0, 2, 0},
{ OP_Ne, 0, ADDR(7), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Next, 0, ADDR(3), 0}, /* 7 */
};
Index *pIdx;
Trigger *pTrigger;
sqliteBeginWriteOperation(pParse, 0, pTable->iDb);
/* Drop all triggers associated with the table being dropped */
pTrigger = pTable->pTrigger;
while( pTrigger ){
assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 );
sqliteDropTriggerPtr(pParse, pTrigger, 1);
if( pParse->explain ){
pTrigger = pTrigger->pNext;
}else{
pTrigger = pTable->pTrigger;
}
}
/* Drop all SQLITE_MASTER entries that refer to the table */
sqliteOpenMasterTable(v, pTable->iDb);
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
/* Drop all SQLITE_TEMP_MASTER entries that refer to the table */
if( pTable->iDb!=1 ){
sqliteOpenMasterTable(v, 1);
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
}
if( pTable->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);
for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
}
}
sqliteEndWriteOperation(pParse);
}
/* Delete the in-memory description of the table.
**
** Exception: if the SQL statement began with the EXPLAIN keyword,
** then no changes should be made.
*/
if( !pParse->explain ){
sqliteUnlinkAndDeleteTable(db, pTable);
db->flags |= SQLITE_InternChanges;
}
sqliteViewResetAll(db, iDb);
}
| build.c | 1171 |
VOID | sqliteAddIdxKeyType(Vdbe *v, Index *pIdx)
void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
char *zType;
Table *pTab;
int i, n;
assert( pIdx!=0 && pIdx->pTable!=0 );
pTab = pIdx->pTable;
n = pIdx->nColumn;
zType = sqliteMallocRaw( n+1 );
if( zType==0 ) return;
for(i=0; iaiColumn[i];
assert( iCol>=0 && iColnCol );
if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
zType[i] = 't';
}else{
zType[i] = 'n';
}
}
zType[n] = 0;
sqliteVdbeChangeP3(v, -1, zType, n);
sqliteFree(zType);
}
| build.c | 1298 |
VOID | sqliteCreateForeignKey( Parse *pParse, IdList *pFromCol, Token *pTo, IdList *pToCol, int flags )
void sqliteCreateForeignKey(
Parse *pParse, /* Parsing context */
IdList *pFromCol, /* Columns in this table that point to other table */
Token *pTo, /* Name of the other table */
IdList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
Table *p = pParse->pNewTable;
int nByte;
int i;
int nCol;
char *z;
FKey *pFKey = 0;
assert( pTo!=0 );
if( p==0 || pParse->nErr ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
if( iCol<0 ) goto fk_end;
if( pToCol && pToCol->nId!=1 ){
sqliteErrorMsg(pParse, "foreign key on %s"
" should reference only one column of table %T",
p->aCol[iCol].zName, pTo);
goto fk_end;
}
nCol = 1;
}else if( pToCol && pToCol->nId!=pFromCol->nId ){
sqliteErrorMsg(pParse,
"number of columns in foreign key does not match the number of "
"columns in the referenced table");
goto fk_end;
}else{
nCol = pFromCol->nId;
}
nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; inId; i++){
nByte += strlen(pToCol->a[i].zName) + 1;
}
}
pFKey = sqliteMalloc( nByte );
if( pFKey==0 ) goto fk_end;
pFKey->pFrom = p;
pFKey->pNextFrom = p->pFKey;
z = (char*)&pFKey[1];
pFKey->aCol = (struct sColMap*)z;
z += sizeof(struct sColMap)*nCol;
pFKey->zTo = z;
memcpy(z, pTo->z, pTo->n);
z[pTo->n] = 0;
z += pTo->n+1;
pFKey->pNextTo = 0;
pFKey->nCol = nCol;
if( pFromCol==0 ){
pFKey->aCol[0].iFrom = p->nCol-1;
}else{
for(i=0; inCol; j++){
if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
}
if( j>=p->nCol ){
sqliteErrorMsg(pParse,
"unknown column \"%s\" in foreign key definition",
pFromCol->a[i].zName);
goto fk_end;
}
}
}
if( pToCol ){
for(i=0; ia[i].zName);
pFKey->aCol[i].zCol = z;
memcpy(z, pToCol->a[i].zName, n);
z[n] = 0;
z += n+1;
}
}
pFKey->isDeferred = 0;
pFKey->deleteConf = flags & 0xff;
pFKey->updateConf = (flags >> 8 ) & 0xff;
pFKey->insertConf = (flags >> 16 ) & 0xff;
/* Link the foreign key to the table as the last step.
*/
p->pFKey = pFKey;
pFKey = 0;
fk_end:
sqliteFree(pFKey);
sqliteIdListDelete(pFromCol);
sqliteIdListDelete(pToCol);
}
| build.c | 1331 |
VOID | sqliteDeferForeignKey(Parse *pParse, int isDeferred)
void sqliteDeferForeignKey(Parse *pParse, int isDeferred){
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
pFKey->isDeferred = isDeferred;
}
| build.c | 1446 |
VOID | sqliteCreateIndex( Parse *pParse, Token *pName, SrcList *pTable, IdList *pList, int onError, Token *pStart, Token *pEnd )
void sqliteCreateIndex(
Parse *pParse, /* All information about this parse */
Token *pName, /* Name of the index. May be NULL */
SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */
IdList *pList, /* A list of columns to be indexed */
int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
Token *pEnd /* The ")" that closes the CREATE INDEX statement */
){
Table *pTab; /* Table to be indexed */
Index *pIndex; /* The index to be created */
char *zName = 0;
int i, j;
Token nullId; /* Fake token for an empty ID list */
DbFixer sFix; /* For assigning database names to pTable */
int isTemp; /* True for a temporary index */
sqlite *db = pParse->db;
if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
if( db->init.busy
&& sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
&& sqliteFixSrcList(&sFix, pTable)
){
goto exit_create_index;
}
/*
** Find the table that is to be indexed. Return early if not found.
*/
if( pTable!=0 ){
assert( pName!=0 );
assert( pTable->nSrc==1 );
pTab = sqliteSrcListLookup(pParse, pTable);
}else{
assert( pName==0 );
pTab = pParse->pNewTable;
}
if( pTab==0 || pParse->nErr ) goto exit_create_index;
if( pTab->readOnly ){
sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
if( pTab->iDb>=2 && db->init.busy==0 ){
sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
goto exit_create_index;
}
if( pTab->pSelect ){
sqliteErrorMsg(pParse, "views may not be indexed");
goto exit_create_index;
}
isTemp = pTab->iDb==1;
/*
** Find the name of the index. Make sure there is not already another
** index or table with the same name.
**
** Exception: If we are reading the names of permanent indices from the
** sqlite_master table (because some other process changed the schema) and
** one of the index names collides with the name of a temporary table or
** index, then we will continue to process this index.
**
** If pName==0 it means that we are
** dealing with a primary key or UNIQUE constraint. We have to invent our
** own name.
*/
if( pName && !db->init.busy ){
Index *pISameName; /* Another index with the same name */
Table *pTSameName; /* A table with same name as the index */
zName = sqliteTableNameFromToken(pName);
if( zName==0 ) goto exit_create_index;
if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
sqliteErrorMsg(pParse, "index %s already exists", zName);
goto exit_create_index;
}
if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
sqliteErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
}else if( pName==0 ){
char zBuf[30];
int n;
Index *pLoop;
for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
sprintf(zBuf,"%d)",n);
zName = 0;
sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
if( zName==0 ) goto exit_create_index;
}else{
zName = sqliteTableNameFromToken(pName);
}
/* Check for authorization to create an index.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
{
const char *zDb = db->aDb[pTab->iDb].zName;
assert( pTab->iDb==db->init.iDb || isTemp );
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto exit_create_index;
}
i = SQLITE_CREATE_INDEX;
if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
goto exit_create_index;
}
}
#endif
/* If pList==0, it means this routine was called to make a primary
** key out of the last column added to the table under construction.
** So create a fake list to simulate this.
*/
if( pList==0 ){
nullId.z = pTab->aCol[pTab->nCol-1].zName;
nullId.n = strlen(nullId.z);
pList = sqliteIdListAppend(0, &nullId);
if( pList==0 ) goto exit_create_index;
}
/*
** Allocate the index structure.
*/
pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
sizeof(int)*pList->nId );
if( pIndex==0 ) goto exit_create_index;
pIndex->aiColumn = (int*)&pIndex[1];
pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
strcpy(pIndex->zName, zName);
pIndex->pTable = pTab;
pIndex->nColumn = pList->nId;
pIndex->onError = onError;
pIndex->autoIndex = pName==0;
pIndex->iDb = isTemp ? 1 : db->init.iDb;
/* Scan the names of the columns of the table to be indexed and
** load the column indices into the Index structure. Report an error
** if any column is not found.
*/
for(i=0; inId; i++){
for(j=0; jnCol; j++){
if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
}
if( j>=pTab->nCol ){
sqliteErrorMsg(pParse, "table %s has no column named %s",
pTab->zName, pList->a[i].zName);
sqliteFree(pIndex);
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
}
/* Link the new Index structure to its table and to the other
** in-memory database structures.
*/
if( !pParse->explain ){
Index *p;
p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash,
pIndex->zName, strlen(pIndex->zName)+1, pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
sqliteFree(pIndex);
goto exit_create_index;
}
db->flags |= SQLITE_InternChanges;
}
/* When adding an index to the list of indices for a table, make
** sure all indices labeled OE_Replace come after all those labeled
** OE_Ignore. This is necessary for the correct operation of UPDATE
** and INSERT.
*/
if( onError!=OE_Replace || pTab->pIndex==0
|| pTab->pIndex->onError==OE_Replace){
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
}else{
Index *pOther = pTab->pIndex;
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
pOther = pOther->pNext;
}
pIndex->pNext = pOther->pNext;
pOther->pNext = pIndex;
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" table on the disk. So do not write to the disk
** again. Extract the table number from the db->init.newTnum field.
*/
if( db->init.busy && pTable!=0 ){
pIndex->tnum = db->init.newTnum;
}
/* If the db->init.busy is 0 then create the index on disk. This
** involves writing the index into the master table and filling in the
** index with the current table contents.
**
** The db->init.busy is 0 when the user first enters a CREATE INDEX
** command. db->init.busy is 1 when a database is opened and
** CREATE INDEX statements are read out of the master table. In
** the latter case the index already exists on disk, which is why
** we don't want to recreate it.
**
** If pTable==0 it means this index is generated as a primary key
** or UNIQUE constraint of a CREATE TABLE statement. Since the table
** has just been created, it contains no data and the index initialization
** step can be skipped.
*/
else if( db->init.busy==0 ){
int n;
Vdbe *v;
int lbl1, lbl2;
int i;
int addr;
v = sqliteGetVdbe(pParse);
if( v==0 ) goto exit_create_index;
if( pTable!=0 ){
sqliteBeginWriteOperation(pParse, 0, isTemp);
sqliteOpenMasterTable(v, isTemp);
}
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC);
sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0);
sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER);
pIndex->tnum = 0;
if( pTable ){
sqliteVdbeCode(v,
OP_Dup, 0, 0,
OP_Integer, isTemp, 0,
OP_OpenWrite, 1, 0,
0);
}
addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
if( pStart && pEnd ){
n = Addr(pEnd->z) - Addr(pStart->z) + 1;
sqliteVdbeChangeP3(v, addr, pStart->z, n);
}
sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
if( pTable ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0);
lbl2 = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
for(i=0; inColumn; i++){
int iCol = pIndex->aiColumn[i];
if( pTab->iPKey==iCol ){
sqliteVdbeAddOp(v, OP_Dup, i, 0);
}else{
sqliteVdbeAddOp(v, OP_Column, 2, iCol);
}
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex);
sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
"indexed columns are not unique", P3_STATIC);
sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
sqliteVdbeResolveLabel(v, lbl2);
sqliteVdbeAddOp(v, OP_Close, 2, 0);
sqliteVdbeAddOp(v, OP_Close, 1, 0);
}
if( pTable!=0 ){
if( !isTemp ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteEndWriteOperation(pParse);
}
}
/* Clean up before exiting */
exit_create_index:
sqliteIdListDelete(pList);
sqliteSrcListDelete(pTable);
sqliteFree(zName);
return;
}
| build.c | 1460 |
VOID | sqliteDropIndex(Parse *pParse, SrcList *pName)
void sqliteDropIndex(Parse *pParse, SrcList *pName){
Index *pIndex;
Vdbe *v;
sqlite *db = pParse->db;
if( pParse->nErr || sqlite_malloc_failed ) return;
assert( pName->nSrc==1 );
pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
sqliteErrorMsg(pParse, "no such index: %S", pName, 0);
goto exit_drop_index;
}
if( pIndex->autoIndex ){
sqliteErrorMsg(pParse, "index associated with UNIQUE "
"or PRIMARY KEY constraint cannot be dropped", 0);
goto exit_drop_index;
}
if( pIndex->iDb>1 ){
sqliteErrorMsg(pParse, "cannot alter schema of attached "
"databases", 0);
goto exit_drop_index;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
Table *pTab = pIndex->pTable;
const char *zDb = db->aDb[pIndex->iDb].zName;
const char *zTab = SCHEMA_TABLE(pIndex->iDb);
if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto exit_drop_index;
}
if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
goto exit_drop_index;
}
}
#endif
/* Generate code to remove the index and from the master table */
v = sqliteGetVdbe(pParse);
if( v ){
static VdbeOpList dropIndex[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String, 0, 0, 0}, /* 1 */
{ OP_MemStore, 1, 1, 0},
{ OP_MemLoad, 1, 0, 0}, /* 3 */
{ OP_Column, 0, 1, 0},
{ OP_Eq, 0, ADDR(8), 0},
{ OP_Next, 0, ADDR(3), 0},
{ OP_Goto, 0, ADDR(9), 0},
{ OP_Delete, 0, 0, 0}, /* 8 */
};
int base;
sqliteBeginWriteOperation(pParse, 0, pIndex->iDb);
sqliteOpenMasterTable(v, pIndex->iDb);
base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
if( pIndex->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
sqliteEndWriteOperation(pParse);
}
/* Delete the in-memory description of this index.
*/
if( !pParse->explain ){
sqliteUnlinkAndDeleteIndex(db, pIndex);
db->flags |= SQLITE_InternChanges;
}
exit_drop_index:
sqliteSrcListDelete(pName);
}
| build.c | 1753 |
IDLIST | sqliteIdListAppend(IdList *pList, Token *pToken)
IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
if( pList==0 ){
pList = sqliteMalloc( sizeof(IdList) );
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
if( pList->nId>=pList->nAlloc ){
struct IdList_item *a;
pList->nAlloc = pList->nAlloc*2 + 5;
a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
if( a==0 ){
sqliteIdListDelete(pList);
return 0;
}
pList->a = a;
}
memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
if( pToken ){
char **pz = &pList->a[pList->nId].zName;
sqliteSetNString(pz, pToken->z, pToken->n, 0);
if( *pz==0 ){
sqliteIdListDelete(pList);
return 0;
}else{
sqliteDequote(*pz);
}
}
pList->nId++;
return pList;
}
| build.c | 1834 |
SRCLIST | sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase)
SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
if( pList==0 ){
pList = sqliteMalloc( sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
}
if( pList->nSrc>=pList->nAlloc ){
SrcList *pNew;
pList->nAlloc *= 2;
pNew = sqliteRealloc(pList,
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
if( pNew==0 ){
sqliteSrcListDelete(pList);
return 0;
}
pList = pNew;
}
memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
if( pDatabase && pTable ){
Token *pTemp = pDatabase;
pDatabase = pTable;
pTable = pTemp;
}
if( pTable ){
char **pz = &pList->a[pList->nSrc].zName;
sqliteSetNString(pz, pTable->z, pTable->n, 0);
if( *pz==0 ){
sqliteSrcListDelete(pList);
return 0;
}else{
sqliteDequote(*pz);
}
}
if( pDatabase ){
char **pz = &pList->a[pList->nSrc].zDatabase;
sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0);
if( *pz==0 ){
sqliteSrcListDelete(pList);
return 0;
}else{
sqliteDequote(*pz);
}
}
pList->a[pList->nSrc].iCursor = -1;
pList->nSrc++;
return pList;
}
| build.c | 1871 |
VOID | sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList)
void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
for(i=0; inSrc; i++){
if( pList->a[i].iCursor<0 ){
pList->a[i].iCursor = pParse->nTab++;
}
}
}
| build.c | 1947 |
VOID | sqliteSrcListAddAlias(SrcList *pList, Token *pToken)
void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){
if( pList && pList->nSrc>0 ){
int i = pList->nSrc - 1;
sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0);
sqliteDequote(pList->a[i].zAlias);
}
}
| build.c | 1959 |
VOID | sqliteIdListDelete(IdList *pList)
void sqliteIdListDelete(IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; inId; i++){
sqliteFree(pList->a[i].zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
}
| build.c | 1970 |
INT | sqliteIdListIndex(IdList *pList, const char *zName)
int sqliteIdListIndex(IdList *pList, const char *zName){
int i;
if( pList==0 ) return -1;
for(i=0; inId; i++){
if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i;
}
return -1;
}
| build.c | 1983 |
VOID | sqliteSrcListDelete(SrcList *pList)
void sqliteSrcListDelete(SrcList *pList){
int i;
if( pList==0 ) return;
for(i=0; inSrc; i++){
sqliteFree(pList->a[i].zDatabase);
sqliteFree(pList->a[i].zName);
sqliteFree(pList->a[i].zAlias);
if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){
sqliteDeleteTable(0, pList->a[i].pTab);
}
sqliteSelectDelete(pList->a[i].pSelect);
sqliteExprDelete(pList->a[i].pOn);
sqliteIdListDelete(pList->a[i].pUsing);
}
sqliteFree(pList);
}
| build.c | 1996 |
VOID | sqliteBeginTransaction(Parse *pParse, int onError)
void sqliteBeginTransaction(Parse *pParse, int onError){
sqlite *db;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
if( db->flags & SQLITE_InTrans ){
sqliteErrorMsg(pParse, "cannot start a transaction within a transaction");
return;
}
sqliteBeginWriteOperation(pParse, 0, 0);
if( !pParse->explain ){
db->flags |= SQLITE_InTrans;
db->onError = onError;
}
}
| build.c | 2016 |
VOID | sqliteCommitTransaction(Parse *pParse)
void sqliteCommitTransaction(Parse *pParse){
sqlite *db;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
return;
}
if( !pParse->explain ){
db->flags &= ~SQLITE_InTrans;
}
sqliteEndWriteOperation(pParse);
if( !pParse->explain ){
db->onError = OE_Default;
}
}
| build.c | 2036 |
VOID | sqliteRollbackTransaction(Parse *pParse)
void sqliteRollbackTransaction(Parse *pParse){
sqlite *db;
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
if( pParse->nErr || sqlite_malloc_failed ) return;
if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteErrorMsg(pParse, "cannot rollback - no transaction is active");
return;
}
v = sqliteGetVdbe(pParse);
if( v ){
sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
}
if( !pParse->explain ){
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
}
| build.c | 2058 |
VOID | sqliteCodeVerifySchema(Parse *pParse, int iDb)
void sqliteCodeVerifySchema(Parse *pParse, int iDb){
sqlite *db = pParse->db;
Vdbe *v = sqliteGetVdbe(pParse);
assert( iDb>=0 && iDbnDb );
assert( db->aDb[iDb].pBt!=0 );
if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){
sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie);
DbSetProperty(db, iDb, DB_Cookie);
}
}
| build.c | 2082 |
VOID | sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb)
void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){
Vdbe *v;
sqlite *db = pParse->db;
if( DbHasProperty(db, iDb, DB_Locked) ) return;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( !db->aDb[iDb].inTrans ){
sqliteVdbeAddOp(v, OP_Transaction, iDb, 0);
DbSetProperty(db, iDb, DB_Locked);
sqliteCodeVerifySchema(pParse, iDb);
if( iDb!=1 ){
sqliteBeginWriteOperation(pParse, setCheckpoint, 1);
}
}else if( setCheckpoint ){
sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0);
DbSetProperty(db, iDb, DB_Locked);
}
}
| build.c | 2097 |
VOID | sqliteEndWriteOperation(Parse *pParse)
void sqliteEndWriteOperation(Parse *pParse){
Vdbe *v;
sqlite *db = pParse->db;
if( pParse->trigStack ) return; /* if this is in a trigger */
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( db->flags & SQLITE_InTrans ){
/* A BEGIN has executed. Do not commit until we see an explicit
** COMMIT statement. */
}else{
sqliteVdbeAddOp(v, OP_Commit, 0, 0);
}
}
| build.c | 2134 |
copy.c |
Type | Function | Source | Line |
VOID | sqliteCopy( Parse *pParse, SrcList *pTableName, Token *pFilename, Token *pDelimiter, int onError )
void sqliteCopy(
Parse *pParse, /* The parser context */
SrcList *pTableName, /* The name of the table into which we will insert */
Token *pFilename, /* The file from which to obtain information */
Token *pDelimiter, /* Use this as the field delimiter */
int onError /* What to do if a constraint fails */
){
Table *pTab;
int i;
Vdbe *v;
int addr, end;
char *zFile = 0;
const char *zDb;
sqlite *db = pParse->db;
if( sqlite_malloc_failed ) goto copy_cleanup;
assert( pTableName->nSrc==1 );
pTab = sqliteSrcListLookup(pParse, pTableName);
if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
zFile = sqliteStrNDup(pFilename->z, pFilename->n);
sqliteDequote(zFile);
assert( pTab->iDbnDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
|| sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
goto copy_cleanup;
}
v = sqliteGetVdbe(pParse);
if( v ){
sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
sqliteVdbeDequoteP3(v, addr);
sqliteOpenTableAndIndices(pParse, pTab, 0);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */
}
end = sqliteVdbeMakeLabel(v);
addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
if( pDelimiter ){
sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
sqliteVdbeDequoteP3(v, addr);
}else{
sqliteVdbeChangeP3(v, addr, "\t", 1);
}
if( pTab->iPKey>=0 ){
sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
}
for(i=0; inCol; i++){
if( i==pTab->iPKey ){
/* The integer primary key column is filled with NULL since its
** value is always pulled from the record number */
sqliteVdbeAddOp(v, OP_String, 0, 0);
}else{
sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
}
}
sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
0, onError, addr);
sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
if( (db->flags & SQLITE_CountRows)!=0 ){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */
}
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_Noop, 0, 0);
sqliteEndWriteOperation(pParse);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
}
}
copy_cleanup:
sqliteSrcListDelete(pTableName);
sqliteFree(zFile);
return;
}
| copy.c | 18 |
date.c |
Type | Function | Source | Line |
STATIC INT | getDigits(const char *zDate, ...)
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(*zDate) ){
return cnt;
}
val = val*10 + *zDate - '0';
zDate++;
}
if( valmax || (nextC!=0 && nextC!=*zDate) ){
return cnt;
}
*pVal = val;
zDate++;
cnt++;
}while( nextC );
return cnt;
}
| date.c | 76 |
STATIC INT | getValue(const char *z, double *pR)
static int getValue(const char *z, double *pR){
const char *zEnd;
*pR = sqliteAtoF(z, &zEnd);
return zEnd - z;
}
| date.c | 123 |
STATIC INT | parseTimezone(const char *zDate, DateTime *p)
static int parseTimezone(const char *zDate, DateTime *p){
int sgn = 0;
int nHr, nMn;
while( isspace(*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(*zDate) ){ zDate++; }
return *zDate!=0;
}
| date.c | 133 |
STATIC INT | parseHhMmSs(const char *zDate, DateTime *p)
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(zDate[1]) ){
double rScale = 1.0;
zDate++;
while( isdigit(*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;
}
| date.c | 167 |
STATIC VOID | computeJD(DateTime *p)
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;
}
}
}
| date.c | 210 |
STATIC INT | parseYyyyMmDd(const char *zDate, DateTime *p)
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(*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;
}
| date.c | 250 |
STATIC INT | parseDateOrTime(const char *zDate, DateTime *p)
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( sqliteStrICmp(zDate,"now")==0){
double r;
if( sqliteOsCurrentTime(&r)==0 ){
p->rJD = r;
p->validJD = 1;
return 0;
}
return 1;
}else if( sqliteIsNumber(zDate) ){
p->rJD = sqliteAtoF(zDate, 0);
p->validJD = 1;
return 0;
}
return 1;
}
| date.c | 294 |
STATIC VOID | computeYMD(DateTime *p)
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;
}
| date.c | 332 |
STATIC VOID | computeHMS(DateTime *p)
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;
}
| date.c | 358 |
STATIC VOID | computeYMD_HMS(DateTime *p)
static void computeYMD_HMS(DateTime *p){
computeYMD(p);
computeHMS(p);
}
| date.c | 376 |
STATIC VOID | clearYMD_HMS_TZ(DateTime *p)
static void clearYMD_HMS_TZ(DateTime *p){
p->validYMD = 0;
p->validHMS = 0;
p->validTZ = 0;
}
| date.c | 384 |
STATIC DOUBLE | localtimeOffset(DateTime *p)
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;
sqliteOsEnterMutex();
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;
sqliteOsLeaveMutex();
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
y.validTZ = 0;
computeJD(&y);
return y.rJD - x.rJD;
}
| date.c | 393 |
STATIC INT | parseModifier(const char *zMod, DateTime *p)
static int parseModifier(const char *zMod, DateTime *p){
int rc = 1;
int n;
double r;
char *z, zBuf[30];
z = zBuf;
for(n=0; nrJD += 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 occurrance 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(*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(z[0]) ) 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;
}
| date.c | 435 |
STATIC INT | isDate(int argc, const char **argv, DateTime *p)
static int isDate(int argc, const char **argv, DateTime *p){
int i;
if( argc==0 ) return 1;
if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
for(i=1; idate.c | 638 | |
STATIC VOID | juliandayFunc(sqlite_func *context, int argc, const char **argv)
static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
computeJD(&x);
sqlite_set_result_double(context, x.rJD);
}
}
| date.c | 660 |
STATIC VOID | datetimeFunc(sqlite_func *context, int argc, const char **argv)
static void datetimeFunc(sqlite_func *context, int argc, const char **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));
sqlite_set_result_string(context, zBuf, -1);
}
}
| date.c | 673 |
STATIC VOID | timeFunc(sqlite_func *context, int argc, const char **argv)
static void timeFunc(sqlite_func *context, int argc, const char **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);
sqlite_set_result_string(context, zBuf, -1);
}
}
| date.c | 689 |
STATIC VOID | dateFunc(sqlite_func *context, int argc, const char **argv)
static void dateFunc(sqlite_func *context, int argc, const char **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);
sqlite_set_result_string(context, zBuf, -1);
}
}
| date.c | 704 |
STATIC VOID | strftimeFunc(sqlite_func *context, int argc, const char **argv)
static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
DateTime x;
int n, i, j;
char *z;
const char *zFmt = argv[0];
char zBuf[100];
if( argv[0]==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( ndate.c | 719 | |
VOID | sqliteRegisterDateTimeFunctions(sqlite *db)
void sqliteRegisterDateTimeFunctions(sqlite *db){
#ifndef SQLITE_OMIT_DATETIME_FUNCS
static struct {
char *zName;
int nArg;
int dataType;
void (*xFunc)(sqlite_func*,int,const char**);
} aFuncs[] = {
{ "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
{ "date", -1, SQLITE_TEXT, dateFunc },
{ "time", -1, SQLITE_TEXT, timeFunc },
{ "datetime", -1, SQLITE_TEXT, datetimeFunc },
{ "strftime", -1, SQLITE_TEXT, strftimeFunc },
};
int i;
for(i=0; idate.c | 846 | |
delete.c |
Type | Function | Source | Line |
TABLE | sqliteSrcListLookup(Parse *pParse, SrcList *pSrc)
Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab = 0;
int i;
for(i=0; inSrc; i++){
const char *zTab = pSrc->a[i].zName;
const char *zDb = pSrc->a[i].zDatabase;
pTab = sqliteLocateTable(pParse, zTab, zDb);
pSrc->a[i].pTab = pTab;
}
return pTab;
}
| delete.c | 19 |
INT | sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk)
int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( pTab->readOnly ){
sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
if( !viewOk && pTab->pSelect ){
sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
return 1;
}
return 0;
}
| delete.c | 36 |
VOID | sqliteDeleteFrom( Parse *pParse, SrcList *pTabList, Expr *pWhere )
void sqliteDeleteFrom(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere /* The WHERE clause. May be null */
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
int end, addr; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
int iCur; /* VDBE Cursor number for pTab */
sqlite *db; /* Main database structure */
int isView; /* True if attempting to delete from a view */
AuthContext sContext; /* Authorization context */
int row_triggers_exist = 0; /* True if any triggers exist */
int before_triggers; /* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ){
pTabList = 0;
goto delete_from_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
pTab = sqliteSrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_DELETE, TK_BEFORE, TK_ROW, 0);
after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_DELETE, TK_AFTER, TK_ROW, 0);
row_triggers_exist = before_triggers || after_triggers;
isView = pTab->pSelect!=0;
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
goto delete_from_cleanup;
}
assert( pTab->iDbnDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}
/* If pTab is really a view, make sure it has been initialized.
*/
if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
/* Allocate a cursor used to store the old.* data for a trigger.
*/
if( row_triggers_exist ){
oldIdx = pParse->nTab++;
}
/* Resolve the column names in all the expressions.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
if( pWhere ){
if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
goto delete_from_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto delete_from_cleanup;
}
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
/* If we are trying to delete from a view, construct that view into
** a temporary table.
*/
if( isView ){
Select *pView = sqliteSelectDup(pTab->pSelect);
sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqliteSelectDelete(pView);
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
*/
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
if( pWhere==0 && !row_triggers_exist ){
if( db->flags & SQLITE_CountRows ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
int endOfLoop = sqliteVdbeMakeLabel(v);
int addr;
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
}
sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
sqliteVdbeAddOp(v, OP_Next, iCur, addr);
sqliteVdbeResolveLabel(v, endOfLoop);
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
if( !isView ){
sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
}
}
}
/* The usual case: There is a WHERE clause so we have to scan through
** the table and pick which records to delete.
*/
else{
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
/* Remember the key of every item to be deleted.
*/
sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
}
/* End the database scan loop.
*/
sqliteWhereEnd(pWInfo);
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( row_triggers_exist ){
sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
}
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
end = sqliteVdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( row_triggers_exist ){
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
}
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
pParse->nTab = iCur + 1;
sqliteOpenTableAndIndices(pParse, pTab, iCur);
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !row_triggers_exist ){
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
}
/* Delete the row */
sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
if( row_triggers_exist ){
if( !isView ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
/* End of the delete loop */
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
if( !row_triggers_exist ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
}
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were deleted.
*/
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
}
delete_from_cleanup:
sqliteAuthContextPop(&sContext);
sqliteSrcListDelete(pTabList);
sqliteExprDelete(pWhere);
return;
}
| delete.c | 53 |
VOID | sqliteGenerateRowDelete( sqlite *db, Vdbe *v, Table *pTab, int iCur, int count )
void sqliteGenerateRowDelete(
sqlite *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
int count /* Increment the row change counter */
){
int addr;
addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
sqliteVdbeAddOp(v, OP_Delete, iCur,
(count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
}
| delete.c | 316 |
VOID | sqliteGenerateRowIndexDelete( sqlite *db, Vdbe *v, Table *pTab, int iCur, char *aIdxUsed )
void sqliteGenerateRowIndexDelete(
sqlite *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
){
int i;
Index *pIdx;
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
int j;
if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
for(j=0; jnColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_Dup, j, 0);
}else{
sqliteVdbeAddOp(v, OP_Column, iCur, idx);
}
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
}
}
| delete.c | 351 |
encode.c |
Type | Function | Source | Line |
INT | sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out)
int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
int i, j, e, m;
unsigned char x;
int cnt[256];
if( n<=0 ){
if( out ){
out[0] = 'x';
out[1] = 0;
}
return 1;
}
memset(cnt, 0, sizeof(cnt));
for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
m = n;
for(i=1; i<256; i++){
int sum;
if( i=='\'' ) continue;
sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
if( sumencode.c | 103 | |
} INT | sqlite_decode_binary(const unsigned char *in, unsigned char *out)
int sqlite_decode_binary(const unsigned char *in, unsigned char *out){
int i, e;
unsigned char c;
e = *(in++);
i = 0;
while( (c = *(in++))!=0 ){
if( c==1 ){
c = *(in++) - 1;
}
out[i++] = c + e;
}
return i;
}
| encode.c | 165 |
INT | main(int argc, char **argv)
int main(int argc, char **argv){
int i, j, n, m, nOut, nByteIn, nByteOut;
unsigned char in[30000];
unsigned char out[33000];
nByteIn = nByteOut = 0;
for(i=0; i%d (max %d)", n, strlen(out)+1, m);
if( strlen(out)+1>m ){
printf(" ERROR output too big\n");
exit(1);
}
for(j=0; out[j]; j++){
if( out[j]=='\'' ){
printf(" ERROR contains (')\n");
exit(1);
}
}
j = sqlite_decode_binary(out, out);
if( j!=n ){
printf(" ERROR decode size %d\n", j);
exit(1);
}
if( memcmp(in, out, n)!=0 ){
printf(" ERROR decode mismatch\n");
exit(1);
}
printf(" OK\n");
}
fprintf(stderr,"Finished. Total encoding: %d->%d bytes\n",
nByteIn, nByteOut);
fprintf(stderr,"Avg size increase: %.3f%%\n",
(nByteOut-nByteIn)*100.0/(double)nByteIn);
}
| encode.c | 191 |
expr.c |
Type | Function | Source | Line |
EXPR | sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken)
Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
/* When malloc fails, we leak memory from pLeft and pRight */
return 0;
}
pNew->op = op;
pNew->pLeft = pLeft;
pNew->pRight = pRight;
if( pToken ){
assert( pToken->dyn==0 );
pNew->token = *pToken;
pNew->span = *pToken;
}else{
assert( pNew->token.dyn==0 );
assert( pNew->token.z==0 );
assert( pNew->token.n==0 );
if( pLeft && pRight ){
sqliteExprSpan(pNew, &pLeft->span, &pRight->span);
}else{
pNew->span = pNew->token;
}
}
return pNew;
}
| expr.c | 20 |
VOID | sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight)
void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pRight!=0 );
assert( pLeft!=0 );
/* Note: pExpr might be NULL due to a prior malloc failure */
if( pExpr && pRight->z && pLeft->z ){
if( pLeft->dyn==0 && pRight->dyn==0 ){
pExpr->span.z = pLeft->z;
pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
}else{
pExpr->span.z = 0;
}
}
}
| expr.c | 52 |
EXPR | sqliteExprFunction(ExprList *pList, Token *pToken)
Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
/* sqliteExprListDelete(pList); // Leak pList when malloc fails */
return 0;
}
pNew->op = TK_FUNCTION;
pNew->pList = pList;
if( pToken ){
assert( pToken->dyn==0 );
pNew->token = *pToken;
}else{
pNew->token.z = 0;
}
pNew->span = pNew->token;
return pNew;
}
| expr.c | 70 |
VOID | sqliteExprDelete(Expr *p)
void sqliteExprDelete(Expr *p){
if( p==0 ) return;
if( p->span.dyn ) sqliteFree((char*)p->span.z);
if( p->token.dyn ) sqliteFree((char*)p->token.z);
sqliteExprDelete(p->pLeft);
sqliteExprDelete(p->pRight);
sqliteExprListDelete(p->pList);
sqliteSelectDelete(p->pSelect);
sqliteFree(p);
}
| expr.c | 93 |
EXPR | sqliteExprDup(Expr *p)
Expr *sqliteExprDup(Expr *p){
Expr *pNew;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*p) );
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
}
pNew->span.z = 0;
pNew->pLeft = sqliteExprDup(p->pLeft);
pNew->pRight = sqliteExprDup(p->pRight);
pNew->pList = sqliteExprListDup(p->pList);
pNew->pSelect = sqliteSelectDup(p->pSelect);
return pNew;
}
| expr.c | 108 |
VOID | sqliteTokenCopy(Token *pTo, Token *pFrom)
void sqliteTokenCopy(Token *pTo, Token *pFrom){
if( pTo->dyn ) sqliteFree((char*)pTo->z);
if( pFrom->z ){
pTo->n = pFrom->n;
pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
pTo->dyn = 1;
}else{
pTo->z = 0;
}
}
| expr.c | 139 |
EXPRLIST | sqliteExprListDup(ExprList *p)
ExprList *sqliteExprListDup(ExprList *p){
ExprList *pNew;
struct ExprList_item *pItem;
int i;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nExpr = pNew->nAlloc = p->nExpr;
pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
if( pItem==0 ){
sqliteFree(pNew);
return 0;
}
for(i=0; inExpr; i++, pItem++){
Expr *pNewExpr, *pOldExpr;
pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
if( pOldExpr->span.z!=0 && pNewExpr ){
/* Always make a copy of the span for top-level expressions in the
** expression list. The logic in SELECT processing that determines
** the names of columns in the result set needs this information */
sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span);
}
assert( pNewExpr==0 || pNewExpr->span.z!=0
|| pOldExpr->span.z==0 || sqlite_malloc_failed );
pItem->zName = sqliteStrDup(p->a[i].zName);
pItem->sortOrder = p->a[i].sortOrder;
pItem->isAgg = p->a[i].isAgg;
pItem->done = 0;
}
return pNew;
}
| expr.c | 149 |
SRCLIST | sqliteSrcListDup(SrcList *p)
SrcList *sqliteSrcListDup(SrcList *p){
SrcList *pNew;
int i;
int nByte;
if( p==0 ) return 0;
nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
pNew = sqliteMallocRaw( nByte );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; inSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->pTab = 0;
pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect);
pNewItem->pOn = sqliteExprDup(pOldItem->pOn);
pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing);
}
return pNew;
}
| expr.c | 180 |
IDLIST | sqliteIdListDup(IdList *p)
IdList *sqliteIdListDup(IdList *p){
IdList *pNew;
int i;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nId = pNew->nAlloc = p->nId;
pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ) return 0;
for(i=0; inId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->idx = pOldItem->idx;
}
return pNew;
}
| expr.c | 204 |
SELECT | sqliteSelectDup(Select *p)
Select *sqliteSelectDup(Select *p){
Select *pNew;
if( p==0 ) return 0;
pNew = sqliteMallocRaw( sizeof(*p) );
if( pNew==0 ) return 0;
pNew->isDistinct = p->isDistinct;
pNew->pEList = sqliteExprListDup(p->pEList);
pNew->pSrc = sqliteSrcListDup(p->pSrc);
pNew->pWhere = sqliteExprDup(p->pWhere);
pNew->pGroupBy = sqliteExprListDup(p->pGroupBy);
pNew->pHaving = sqliteExprDup(p->pHaving);
pNew->pOrderBy = sqliteExprListDup(p->pOrderBy);
pNew->op = p->op;
pNew->pPrior = sqliteSelectDup(p->pPrior);
pNew->nLimit = p->nLimit;
pNew->nOffset = p->nOffset;
pNew->zSelect = 0;
pNew->iLimit = -1;
pNew->iOffset = -1;
return pNew;
}
| expr.c | 221 |
EXPRLIST | sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName)
ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
if( pList==0 ){
pList = sqliteMalloc( sizeof(ExprList) );
if( pList==0 ){
/* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
return 0;
}
assert( pList->nAlloc==0 );
}
if( pList->nAlloc<=pList->nExpr ){
pList->nAlloc = pList->nAlloc*2 + 4;
pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
if( pList->a==0 ){
/* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
pList->nExpr = pList->nAlloc = 0;
return pList;
}
}
assert( pList->a!=0 );
if( pExpr || pName ){
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
pItem->pExpr = pExpr;
if( pName ){
sqliteSetNString(&pItem->zName, pName->z, pName->n, 0);
sqliteDequote(pItem->zName);
}
}
return pList;
}
| expr.c | 244 |
VOID | sqliteExprListDelete(ExprList *pList)
void sqliteExprListDelete(ExprList *pList){
int i;
if( pList==0 ) return;
assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
assert( pList->nExpr<=pList->nAlloc );
for(i=0; inExpr; i++){
sqliteExprDelete(pList->a[i].pExpr);
sqliteFree(pList->a[i].zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
}
| expr.c | 279 |
INT | sqliteExprIsConstant(Expr *p)
int sqliteExprIsConstant(Expr *p){
switch( p->op ){
case TK_ID:
case TK_COLUMN:
case TK_DOT:
case TK_FUNCTION:
return 0;
case TK_NULL:
case TK_STRING:
case TK_INTEGER:
case TK_FLOAT:
case TK_VARIABLE:
return 1;
default: {
if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0;
if( p->pList ){
int i;
for(i=0; ipList->nExpr; i++){
if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0;
}
}
return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
}
}
return 0;
}
| expr.c | 295 |
INT | sqliteExprIsInteger(Expr *p, int *pValue)
int sqliteExprIsInteger(Expr *p, int *pValue){
switch( p->op ){
case TK_INTEGER: {
if( sqliteFitsIn32Bits(p->token.z) ){
*pValue = atoi(p->token.z);
return 1;
}
break;
}
case TK_STRING: {
const char *z = p->token.z;
int n = p->token.n;
if( n>0 && z[0]=='-' ){ z++; n--; }
while( n>0 && *z && isdigit(*z) ){ z++; n--; }
if( n==0 && sqliteFitsIn32Bits(p->token.z) ){
*pValue = atoi(p->token.z);
return 1;
}
break;
}
case TK_UPLUS: {
return sqliteExprIsInteger(p->pLeft, pValue);
}
case TK_UMINUS: {
int v;
if( sqliteExprIsInteger(p->pLeft, &v) ){
*pValue = -v;
return 1;
}
break;
}
default: break;
}
return 0;
}
| expr.c | 331 |
INT | sqliteIsRowid(const char *z)
int sqliteIsRowid(const char *z){
if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1;
if( sqliteStrICmp(z, "ROWID")==0 ) return 1;
if( sqliteStrICmp(z, "OID")==0 ) return 1;
return 0;
}
| expr.c | 373 |
STATIC INT | lookupName( Parse *pParse, Token *pDbToken, Token *pTableToken, Token *pColumnToken, SrcList *pSrcList, ExprList *pEList, Expr *pExpr )
static int lookupName(
Parse *pParse, /* The parsing context */
Token *pDbToken, /* Name of the database containing table, or NULL */
Token *pTableToken, /* Name of table containing column, or NULL */
Token *pColumnToken, /* Name of the column. */
SrcList *pSrcList, /* List of tables used to resolve column names */
ExprList *pEList, /* List of expressions used to resolve "AS" */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
char *zCol = 0; /* Name of the column. The "Z" */
int i, j; /* Loop counters */
int cnt = 0; /* Number of matching column names */
int cntTab = 0; /* Number of matching table names */
sqlite *db = pParse->db; /* The database */
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
if( pDbToken && pDbToken->z ){
zDb = sqliteStrNDup(pDbToken->z, pDbToken->n);
sqliteDequote(zDb);
}else{
zDb = 0;
}
if( pTableToken && pTableToken->z ){
zTab = sqliteStrNDup(pTableToken->z, pTableToken->n);
sqliteDequote(zTab);
}else{
assert( zDb==0 );
zTab = 0;
}
zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n);
sqliteDequote(zCol);
if( sqlite_malloc_failed ){
return 1; /* Leak memory (zDb and zTab) if malloc fails */
}
assert( zTab==0 || pEList==0 );
pExpr->iTable = -1;
for(i=0; inSrc; i++){
struct SrcList_item *pItem = &pSrcList->a[i];
Table *pTab = pItem->pTab;
Column *pCol;
if( pTab==0 ) continue;
assert( pTab->nCol>0 );
if( zTab ){
if( pItem->zAlias ){
char *zTabName = pItem->zAlias;
if( sqliteStrICmp(zTabName, zTab)!=0 ) continue;
}else{
char *zTabName = pTab->zName;
if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue;
if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
continue;
}
}
}
if( 0==(cntTab++) ){
pExpr->iTable = pItem->iCursor;
pExpr->iDb = pTab->iDb;
}
for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
if( sqliteStrICmp(pCol->zName, zCol)==0 ){
cnt++;
pExpr->iTable = pItem->iCursor;
pExpr->iDb = pTab->iDb;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
break;
}
}
}
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
*/
if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
TriggerStack *pTriggerStack = pParse->trigStack;
Table *pTab = 0;
if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){
pExpr->iTable = pTriggerStack->newIdx;
assert( pTriggerStack->pTab );
pTab = pTriggerStack->pTab;
}else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){
pExpr->iTable = pTriggerStack->oldIdx;
assert( pTriggerStack->pTab );
pTab = pTriggerStack->pTab;
}
if( pTab ){
int j;
Column *pCol = pTab->aCol;
pExpr->iDb = pTab->iDb;
cntTab++;
for(j=0; j < pTab->nCol; j++, pCol++) {
if( sqliteStrICmp(pCol->zName, zCol)==0 ){
cnt++;
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
break;
}
}
}
}
/*
** Perhaps the name is a reference to the ROWID
*/
if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){
cnt = 1;
pExpr->iColumn = -1;
pExpr->dataType = SQLITE_SO_NUM;
}
/*
** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
** might refer to an result-set alias. This happens, for example, when
** we are resolving names in the WHERE clause of the following command:
**
** SELECT a+b AS x FROM table WHERE x<10;
**
** In cases like this, replace pExpr with a copy of the expression that
** forms the result set entry ("a+b" in the example) and return immediately.
** Note that the expression in the result set should have already been
** resolved by the time the WHERE clause is resolved.
*/
if( cnt==0 && pEList!=0 ){
for(j=0; jnExpr; j++){
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
pExpr->op = TK_AS;
pExpr->iColumn = j;
pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
sqliteFree(zCol);
assert( zTab==0 && zDb==0 );
return 0;
}
}
}
/*
** If X and Y are NULL (in other words if only the column name Z is
** supplied) and the value of Z is enclosed in double-quotes, then
** Z is a string literal if it doesn't match any column names. In that
** case, we need to return right away and not make any changes to
** pExpr.
*/
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
sqliteFree(zCol);
return 0;
}
/*
** cnt==0 means there was not match. cnt>1 means there were two or
** more matches. Either way, we have an error.
*/
if( cnt!=1 ){
char *z = 0;
char *zErr;
zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s";
if( zDb ){
sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0);
}else if( zTab ){
sqliteSetString(&z, zTab, ".", zCol, 0);
}else{
z = sqliteStrDup(zCol);
}
sqliteErrorMsg(pParse, zErr, z);
sqliteFree(z);
}
/* Clean up and return
*/
sqliteFree(zDb);
sqliteFree(zTab);
sqliteFree(zCol);
sqliteExprDelete(pExpr->pLeft);
pExpr->pLeft = 0;
sqliteExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
sqliteAuthRead(pParse, pExpr, pSrcList);
return cnt!=1;
}
| expr.c | 383 |
INT | sqliteExprResolveIds( Parse *pParse, SrcList *pSrcList, ExprList *pEList, Expr *pExpr )
int sqliteExprResolveIds(
Parse *pParse, /* The parser context */
SrcList *pSrcList, /* List of tables used to resolve column names */
ExprList *pEList, /* List of expressions used to resolve "AS" */
Expr *pExpr /* The expression to be analyzed. */
){
int i;
if( pExpr==0 || pSrcList==0 ) return 0;
for(i=0; inSrc; i++){
assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab );
}
switch( pExpr->op ){
/* Double-quoted strings (ex: "abc") are used as identifiers if
** possible. Otherwise they remain as strings. Single-quoted
** strings (ex: 'abc') are always string literals.
*/
case TK_STRING: {
if( pExpr->token.z[0]=='\'' ) break;
/* Fall thru into the TK_ID case if this is a double-quoted string */
}
/* A lone identifier is the name of a columnd.
*/
case TK_ID: {
if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
return 1;
}
break;
}
/* A table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
*/
case TK_DOT: {
Token *pColumn;
Token *pTable;
Token *pDb;
Expr *pRight;
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
pDb = 0;
pTable = &pExpr->pLeft->token;
pColumn = &pRight->token;
}else{
assert( pRight->op==TK_DOT );
pDb = &pExpr->pLeft->token;
pTable = &pRight->pLeft->token;
pColumn = &pRight->pRight->token;
}
if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
return 1;
}
break;
}
case TK_IN: {
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into a temporary
** table. The cursor number of the temporary table has already
** been put in iTable by sqliteExprResolveInSelect().
*/
pExpr->iTable = pParse->nTab++;
sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
}else if( pExpr->pList ){
/* Case 2: expr IN (exprlist)
**
** Create a set to put the exprlist values in. The Set id is stored
** in iTable.
*/
int i, iSet;
for(i=0; ipList->nExpr; i++){
Expr *pE2 = pExpr->pList->a[i].pExpr;
if( !sqliteExprIsConstant(pE2) ){
sqliteErrorMsg(pParse,
"right-hand side of IN operator must be constant");
return 1;
}
if( sqliteExprCheck(pParse, pE2, 0, 0) ){
return 1;
}
}
iSet = pExpr->iTable = pParse->nSet++;
for(i=0; ipList->nExpr; i++){
Expr *pE2 = pExpr->pList->a[i].pExpr;
switch( pE2->op ){
case TK_FLOAT:
case TK_INTEGER:
case TK_STRING: {
int addr;
assert( pE2->token.z );
addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0,
pE2->token.z, pE2->token.n);
sqliteVdbeDequoteP3(v, addr);
break;
}
default: {
sqliteExprCode(pParse, pE2);
sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0);
break;
}
}
}
}
break;
}
case TK_SELECT: {
/* This has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
** of the memory cell in iColumn.
*/
pExpr->iColumn = pParse->nMem++;
if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){
return 1;
}
break;
}
/* For all else, just recursively walk the tree */
default: {
if( pExpr->pLeft
&& sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pRight
&& sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
return 1;
}
if( pExpr->pList ){
int i;
ExprList *pList = pExpr->pList;
for(i=0; inExpr; i++){
Expr *pArg = pList->a[i].pExpr;
if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){
return 1;
}
}
}
}
}
return 0;
}
| expr.c | 598 |
STATIC VOID | getFunctionName(Expr *pExpr, const char **pzName, int *pnName)
static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
switch( pExpr->op ){
case TK_FUNCTION: {
*pzName = pExpr->token.z;
*pnName = pExpr->token.n;
break;
}
case TK_LIKE: {
*pzName = "like";
*pnName = 4;
break;
}
case TK_GLOB: {
*pzName = "glob";
*pnName = 4;
break;
}
default: {
*pzName = "can't happen";
*pnName = 12;
break;
}
}
}
| expr.c | 781 |
INT | sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg)
int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
int nErr = 0;
if( pExpr==0 ) return 0;
switch( pExpr->op ){
case TK_GLOB:
case TK_LIKE:
case TK_FUNCTION: {
int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
int i;
int nId; /* Number of characters in function name */
const char *zId; /* The function name. */
FuncDef *pDef;
getFunctionName(pExpr, &zId, &nId);
pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0);
if( pDef==0 ){
pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0);
if( pDef==0 ){
no_such_func = 1;
}else{
wrong_num_args = 1;
}
}else{
is_agg = pDef->xFunc==0;
}
if( is_agg && !allowAgg ){
sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
nErr++;
is_agg = 0;
}else if( no_such_func ){
sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId);
nErr++;
}else if( wrong_num_args ){
sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()",
nId, zId);
nErr++;
}
if( is_agg ){
pExpr->op = TK_AGG_FUNCTION;
if( pIsAgg ) *pIsAgg = 1;
}
for(i=0; nErr==0 && ipList->a[i].pExpr,
allowAgg && !is_agg, pIsAgg);
}
if( pDef==0 ){
/* Already reported an error */
}else if( pDef->dataType>=0 ){
if( pDef->dataTypedataType =
sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr);
}else{
pExpr->dataType = SQLITE_SO_NUM;
}
}else if( pDef->dataType==SQLITE_ARGS ){
pDef->dataType = SQLITE_SO_TEXT;
for(i=0; ipList->a[i].pExpr)==SQLITE_SO_NUM ){
pExpr->dataType = SQLITE_SO_NUM;
break;
}
}
}else if( pDef->dataType==SQLITE_NUMERIC ){
pExpr->dataType = SQLITE_SO_NUM;
}else{
pExpr->dataType = SQLITE_SO_TEXT;
}
}
default: {
if( pExpr->pLeft ){
nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
}
if( nErr==0 && pExpr->pRight ){
nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
}
if( nErr==0 && pExpr->pList ){
int n = pExpr->pList->nExpr;
int i;
for(i=0; nErr==0 && ipList->a[i].pExpr;
nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg);
}
}
break;
}
}
return nErr;
}
| expr.c | 814 |
INT | sqliteExprType(Expr *p)
int sqliteExprType(Expr *p){
if( p==0 ) return SQLITE_SO_NUM;
while( p ) switch( p->op ){
case TK_PLUS:
case TK_MINUS:
case TK_STAR:
case TK_SLASH:
case TK_AND:
case TK_OR:
case TK_ISNULL:
case TK_NOTNULL:
case TK_NOT:
case TK_UMINUS:
case TK_UPLUS:
case TK_BITAND:
case TK_BITOR:
case TK_BITNOT:
case TK_LSHIFT:
case TK_RSHIFT:
case TK_REM:
case TK_INTEGER:
case TK_FLOAT:
case TK_IN:
case TK_BETWEEN:
case TK_GLOB:
case TK_LIKE:
return SQLITE_SO_NUM;
case TK_STRING:
case TK_NULL:
case TK_CONCAT:
case TK_VARIABLE:
return SQLITE_SO_TEXT;
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
case TK_EQ:
if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){
return SQLITE_SO_NUM;
}
p = p->pRight;
break;
case TK_AS:
p = p->pLeft;
break;
case TK_COLUMN:
case TK_FUNCTION:
case TK_AGG_FUNCTION:
return p->dataType;
case TK_SELECT:
assert( p->pSelect );
assert( p->pSelect->pEList );
assert( p->pSelect->pEList->nExpr>0 );
p = p->pSelect->pEList->a[0].pExpr;
break;
case TK_CASE: {
if( p->pRight && sqliteExprType(p->pRight)==SQLITE_SO_NUM ){
return SQLITE_SO_NUM;
}
if( p->pList ){
int i;
ExprList *pList = p->pList;
for(i=1; inExpr; i+=2){
if( sqliteExprType(pList->a[i].pExpr)==SQLITE_SO_NUM ){
return SQLITE_SO_NUM;
}
}
}
return SQLITE_SO_TEXT;
}
default:
assert( p->op==TK_ABORT ); /* Can't Happen */
break;
}
return SQLITE_SO_NUM;
}
| expr.c | 915 |
VOID | sqliteExprCode(Parse *pParse, Expr *pExpr)
void sqliteExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
if( v==0 || pExpr==0 ) return;
switch( pExpr->op ){
case TK_PLUS: op = OP_Add; break;
case TK_MINUS: op = OP_Subtract; break;
case TK_STAR: op = OP_Multiply; break;
case TK_SLASH: op = OP_Divide; break;
case TK_AND: op = OP_And; break;
case TK_OR: op = OP_Or; break;
case TK_LT: op = OP_Lt; break;
case TK_LE: op = OP_Le; break;
case TK_GT: op = OP_Gt; break;
case TK_GE: op = OP_Ge; break;
case TK_NE: op = OP_Ne; break;
case TK_EQ: op = OP_Eq; break;
case TK_ISNULL: op = OP_IsNull; break;
case TK_NOTNULL: op = OP_NotNull; break;
case TK_NOT: op = OP_Not; break;
case TK_UMINUS: op = OP_Negative; break;
case TK_BITAND: op = OP_BitAnd; break;
case TK_BITOR: op = OP_BitOr; break;
case TK_BITNOT: op = OP_BitNot; break;
case TK_LSHIFT: op = OP_ShiftLeft; break;
case TK_RSHIFT: op = OP_ShiftRight; break;
case TK_REM: op = OP_Remainder; break;
default: break;
}
switch( pExpr->op ){
case TK_COLUMN: {
if( pParse->useAgg ){
sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
}else if( pExpr->iColumn>=0 ){
sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
}else{
sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
}
break;
}
case TK_STRING:
case TK_FLOAT:
case TK_INTEGER: {
if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){
sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
}else{
sqliteVdbeAddOp(v, OP_String, 0, 0);
}
assert( pExpr->token.z );
sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
sqliteVdbeDequoteP3(v, -1);
break;
}
case TK_NULL: {
sqliteVdbeAddOp(v, OP_String, 0, 0);
break;
}
case TK_VARIABLE: {
sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
break;
}
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
case TK_EQ: {
if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
op += 6; /* Convert numeric opcodes to text opcodes */
}
/* Fall through into the next case */
}
case TK_AND:
case TK_OR:
case TK_PLUS:
case TK_STAR:
case TK_MINUS:
case TK_REM:
case TK_BITAND:
case TK_BITOR:
case TK_SLASH: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, 0, 0);
break;
}
case TK_LSHIFT:
case TK_RSHIFT: {
sqliteExprCode(pParse, pExpr->pRight);
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 0, 0);
break;
}
case TK_CONCAT: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, OP_Concat, 2, 0);
break;
}
case TK_UMINUS: {
assert( pExpr->pLeft );
if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
Token *p = &pExpr->pLeft->token;
char *z = sqliteMalloc( p->n + 2 );
sprintf(z, "-%.*s", p->n, p->z);
if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){
sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0);
}else{
sqliteVdbeAddOp(v, OP_String, 0, 0);
}
sqliteVdbeChangeP3(v, -1, z, p->n+1);
sqliteFree(z);
break;
}
/* Fall through into TK_NOT */
}
case TK_BITNOT:
case TK_NOT: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 0, 0);
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
int dest;
sqliteVdbeAddOp(v, OP_Integer, 1, 0);
sqliteExprCode(pParse, pExpr->pLeft);
dest = sqliteVdbeCurrentAddr(v) + 2;
sqliteVdbeAddOp(v, op, 1, dest);
sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
break;
}
case TK_AGG_FUNCTION: {
sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
break;
}
case TK_GLOB:
case TK_LIKE:
case TK_FUNCTION: {
ExprList *pList = pExpr->pList;
int nExpr = pList ? pList->nExpr : 0;
FuncDef *pDef;
int nId;
const char *zId;
getFunctionName(pExpr, &zId, &nId);
pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0);
assert( pDef!=0 );
nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes);
sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
break;
}
case TK_SELECT: {
sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
break;
}
case TK_IN: {
int addr;
sqliteVdbeAddOp(v, OP_Integer, 1, 0);
sqliteExprCode(pParse, pExpr->pLeft);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4);
sqliteVdbeAddOp(v, OP_Pop, 2, 0);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, addr+6);
if( pExpr->pSelect ){
sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6);
}else{
sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6);
}
sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
break;
}
case TK_BETWEEN: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
sqliteVdbeAddOp(v, OP_Ge, 0, 0);
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
sqliteVdbeAddOp(v, OP_Le, 0, 0);
sqliteVdbeAddOp(v, OP_And, 0, 0);
break;
}
case TK_UPLUS:
case TK_AS: {
sqliteExprCode(pParse, pExpr->pLeft);
break;
}
case TK_CASE: {
int expr_end_label;
int jumpInst;
int addr;
int nExpr;
int i;
assert(pExpr->pList);
assert((pExpr->pList->nExpr % 2) == 0);
assert(pExpr->pList->nExpr > 0);
nExpr = pExpr->pList->nExpr;
expr_end_label = sqliteVdbeMakeLabel(v);
if( pExpr->pLeft ){
sqliteExprCode(pParse, pExpr->pLeft);
}
for(i=0; ipList->a[i].pExpr);
if( pExpr->pLeft ){
sqliteVdbeAddOp(v, OP_Dup, 1, 1);
jumpInst = sqliteVdbeAddOp(v, OP_Ne, 1, 0);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
}else{
jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 1, 0);
}
sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr);
sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeChangeP2(v, jumpInst, addr);
}
if( pExpr->pLeft ){
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
}
if( pExpr->pRight ){
sqliteExprCode(pParse, pExpr->pRight);
}else{
sqliteVdbeAddOp(v, OP_String, 0, 0);
}
sqliteVdbeResolveLabel(v, expr_end_label);
break;
}
case TK_RAISE: {
if( !pParse->trigStack ){
sqliteErrorMsg(pParse,
"RAISE() may only be used within a trigger-program");
pParse->nErr++;
return;
}
if( pExpr->iColumn == OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail ){
sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
pExpr->token.z, pExpr->token.n);
sqliteVdbeDequoteP3(v, -1);
} else {
assert( pExpr->iColumn == OE_Ignore );
sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump,
"(IGNORE jump)", 0);
}
}
break;
}
}
| expr.c | 1007 |
INT | sqliteExprCodeExprList( Parse *pParse, ExprList *pList, int includeTypes )
int sqliteExprCodeExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int includeTypes /* TRUE to put datatypes on the stack too */
){
struct ExprList_item *pItem;
int i, n;
Vdbe *v;
if( pList==0 ) return 0;
v = sqliteGetVdbe(pParse);
n = pList->nExpr;
for(pItem=pList->a, i=0; ipExpr);
if( includeTypes ){
sqliteVdbeOp3(v, OP_String, 0, 0,
sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text",
P3_STATIC);
}
}
return includeTypes ? n*2 : n;
}
| expr.c | 1262 |
VOID | sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull)
void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
if( v==0 || pExpr==0 ) return;
switch( pExpr->op ){
case TK_LT: op = OP_Lt; break;
case TK_LE: op = OP_Le; break;
case TK_GT: op = OP_Gt; break;
case TK_GE: op = OP_Ge; break;
case TK_NE: op = OP_Ne; break;
case TK_EQ: op = OP_Eq; break;
case TK_ISNULL: op = OP_IsNull; break;
case TK_NOTNULL: op = OP_NotNull; break;
default: break;
}
switch( pExpr->op ){
case TK_AND: {
int d2 = sqliteVdbeMakeLabel(v);
sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull);
sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqliteVdbeResolveLabel(v, d2);
break;
}
case TK_OR: {
sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
break;
}
case TK_NOT: {
sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
break;
}
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
case TK_EQ: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
op += 6; /* Convert numeric opcodes to text opcodes */
}
sqliteVdbeAddOp(v, op, jumpIfNull, dest);
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 1, dest);
break;
}
case TK_IN: {
int addr;
sqliteExprCode(pParse, pExpr->pLeft);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
if( pExpr->pSelect ){
sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest);
}else{
sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest);
}
break;
}
case TK_BETWEEN: {
int addr;
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0);
sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest);
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
break;
}
default: {
sqliteExprCode(pParse, pExpr);
sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest);
break;
}
}
}
| expr.c | 1292 |
VOID | sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull)
void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
if( v==0 || pExpr==0 ) return;
switch( pExpr->op ){
case TK_LT: op = OP_Ge; break;
case TK_LE: op = OP_Gt; break;
case TK_GT: op = OP_Le; break;
case TK_GE: op = OP_Lt; break;
case TK_NE: op = OP_Eq; break;
case TK_EQ: op = OP_Ne; break;
case TK_ISNULL: op = OP_NotNull; break;
case TK_NOTNULL: op = OP_IsNull; break;
default: break;
}
switch( pExpr->op ){
case TK_AND: {
sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
break;
}
case TK_OR: {
int d2 = sqliteVdbeMakeLabel(v);
sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull);
sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqliteVdbeResolveLabel(v, d2);
break;
}
case TK_NOT: {
sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
break;
}
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_NE:
case TK_EQ: {
if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
/* Convert numeric comparison opcodes into text comparison opcodes.
** This step depends on the fact that the text comparision opcodes are
** always 6 greater than their corresponding numeric comparison
** opcodes.
*/
assert( OP_Eq+6 == OP_StrEq );
op += 6;
}
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
sqliteVdbeAddOp(v, op, jumpIfNull, dest);
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, op, 1, dest);
break;
}
case TK_IN: {
int addr;
sqliteExprCode(pParse, pExpr->pLeft);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
if( pExpr->pSelect ){
sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest);
}else{
sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest);
}
break;
}
case TK_BETWEEN: {
int addr;
sqliteExprCode(pParse, pExpr->pLeft);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
addr = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, dest);
sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);
break;
}
default: {
sqliteExprCode(pParse, pExpr);
sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
break;
}
}
}
| expr.c | 1387 |
INT | sqliteExprCompare(Expr *pA, Expr *pB)
int sqliteExprCompare(Expr *pA, Expr *pB){
int i;
if( pA==0 ){
return pB==0;
}else if( pB==0 ){
return 0;
}
if( pA->op!=pB->op ) return 0;
if( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0;
if( !sqliteExprCompare(pA->pRight, pB->pRight) ) return 0;
if( pA->pList ){
if( pB->pList==0 ) return 0;
if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;
for(i=0; ipList->nExpr; i++){
if( !sqliteExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){
return 0;
}
}
}else if( pB->pList ){
return 0;
}
if( pA->pSelect || pB->pSelect ) return 0;
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( pA->token.z ){
if( pB->token.z==0 ) return 0;
if( pB->token.n!=pA->token.n ) return 0;
if( sqliteStrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0;
}
return 1;
}
| expr.c | 1488 |
STATIC INT | appendAggInfo(Parse *pParse)
static int appendAggInfo(Parse *pParse){
if( (pParse->nAgg & 0x7)==0 ){
int amt = pParse->nAgg + 8;
AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
if( aAgg==0 ){
return -1;
}
pParse->aAgg = aAgg;
}
memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
return pParse->nAgg++;
}
| expr.c | 1523 |
INT | sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr)
int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
int i;
AggExpr *aAgg;
int nErr = 0;
if( pExpr==0 ) return 0;
switch( pExpr->op ){
case TK_COLUMN: {
aAgg = pParse->aAgg;
for(i=0; inAgg; i++){
if( aAgg[i].isAgg ) continue;
if( aAgg[i].pExpr->iTable==pExpr->iTable
&& aAgg[i].pExpr->iColumn==pExpr->iColumn ){
break;
}
}
if( i>=pParse->nAgg ){
i = appendAggInfo(pParse);
if( i<0 ) return 1;
pParse->aAgg[i].isAgg = 0;
pParse->aAgg[i].pExpr = pExpr;
}
pExpr->iAgg = i;
break;
}
case TK_AGG_FUNCTION: {
aAgg = pParse->aAgg;
for(i=0; inAgg; i++){
if( !aAgg[i].isAgg ) continue;
if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){
break;
}
}
if( i>=pParse->nAgg ){
i = appendAggInfo(pParse);
if( i<0 ) return 1;
pParse->aAgg[i].isAgg = 1;
pParse->aAgg[i].pExpr = pExpr;
pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db,
pExpr->token.z, pExpr->token.n,
pExpr->pList ? pExpr->pList->nExpr : 0, 0);
}
pExpr->iAgg = i;
break;
}
default: {
if( pExpr->pLeft ){
nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft);
}
if( nErr==0 && pExpr->pRight ){
nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight);
}
if( nErr==0 && pExpr->pList ){
int n = pExpr->pList->nExpr;
int i;
for(i=0; nErr==0 && ipList->a[i].pExpr);
}
}
break;
}
}
return nErr;
}
| expr.c | 1539 |
FUNCDEF | sqliteFindFunction( sqlite *db, const char *zName, int nName, int nArg, int createFlag )
FuncDef *sqliteFindFunction(
sqlite *db, /* An open database */
const char *zName, /* Name of the function. Not null-terminated */
int nName, /* Number of characters in the name */
int nArg, /* Number of arguments. -1 means any number */
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *pFirst, *p, *pMaybe;
pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName);
if( p && !createFlag && nArg<0 ){
while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; }
return p;
}
pMaybe = 0;
while( p && p->nArg!=nArg ){
if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p;
p = p->pNext;
}
if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){
return 0;
}
if( p==0 && pMaybe ){
assert( createFlag==0 );
return pMaybe;
}
if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){
p->nArg = nArg;
p->pNext = pFirst;
p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC;
sqliteHashInsert(&db->aFunc, zName, nName, (void*)p);
}
return p;
}
| expr.c | 1615 |
func.c |
Type | Function | Source | Line |
STATIC VOID | minmaxFunc(sqlite_func *context, int argc, const char **argv)
static void minmaxFunc(sqlite_func *context, int argc, const char **argv){
const char *zBest;
int i;
int (*xCompare)(const char*, const char*);
int mask; /* 0 for min() or 0xffffffff for max() */
if( argc==0 ) return;
mask = (int)sqlite_user_data(context);
zBest = argv[0];
if( zBest==0 ) return;
if( argv[1][0]=='n' ){
xCompare = sqliteCompare;
}else{
xCompare = strcmp;
}
for(i=2; ifunc.c | 28 | |
STATIC VOID | typeofFunc(sqlite_func *context, int argc, const char **argv)
static void typeofFunc(sqlite_func *context, int argc, const char **argv){
assert( argc==2 );
sqlite_set_result_string(context, argv[1], -1);
}
| func.c | 55 |
STATIC VOID | lengthFunc(sqlite_func *context, int argc, const char **argv)
static void lengthFunc(sqlite_func *context, int argc, const char **argv){
const char *z;
int len;
assert( argc==1 );
z = argv[0];
if( z==0 ) return;
#ifdef SQLITE_UTF8
for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
#else
len = strlen(z);
#endif
sqlite_set_result_int(context, len);
}
| func.c | 63 |
STATIC VOID | absFunc(sqlite_func *context, int argc, const char **argv)
static void absFunc(sqlite_func *context, int argc, const char **argv){
const char *z;
assert( argc==1 );
z = argv[0];
if( z==0 ) return;
if( z[0]=='-' && isdigit(z[1]) ) z++;
sqlite_set_result_string(context, z, -1);
}
| func.c | 81 |
STATIC VOID | substrFunc(sqlite_func *context, int argc, const char **argv)
static void substrFunc(sqlite_func *context, int argc, const char **argv){
const char *z;
#ifdef SQLITE_UTF8
const char *z2;
int i;
#endif
int p1, p2, len;
assert( argc==3 );
z = argv[0];
if( z==0 ) return;
p1 = atoi(argv[1]?argv[1]:0);
p2 = atoi(argv[2]?argv[2]:0);
#ifdef SQLITE_UTF8
for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; }
#else
len = strlen(z);
#endif
if( p1<0 ){
p1 += len;
if( p1<0 ){
p2 += p1;
p1 = 0;
}
}else if( p1>0 ){
p1--;
}
if( p1+p2>len ){
p2 = len-p1;
}
#ifdef SQLITE_UTF8
for(i=0; ifunc.c | 93 | |
STATIC VOID | roundFunc(sqlite_func *context, int argc, const char **argv)
static void roundFunc(sqlite_func *context, int argc, const char **argv){
int n;
double r;
char zBuf[100];
assert( argc==1 || argc==2 );
if( argv[0]==0 || (argc==2 && argv[1]==0) ) return;
n = argc==2 ? atoi(argv[1]) : 0;
if( n>30 ) n = 30;
if( n<0 ) n = 0;
r = sqliteAtoF(argv[0], 0);
sprintf(zBuf,"%.*f",n,r);
sqlite_set_result_string(context, zBuf, -1);
}
| func.c | 139 |
STATIC VOID | upperFunc(sqlite_func *context, int argc, const char **argv)
static void upperFunc(sqlite_func *context, int argc, const char **argv){
unsigned char *z;
int i;
if( argc<1 || argv[0]==0 ) return;
z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
if( z==0 ) return;
for(i=0; z[i]; i++){
if( islower(z[i]) ) z[i] = toupper(z[i]);
}
}
| func.c | 156 |
STATIC VOID | lowerFunc(sqlite_func *context, int argc, const char **argv)
static void lowerFunc(sqlite_func *context, int argc, const char **argv){
unsigned char *z;
int i;
if( argc<1 || argv[0]==0 ) return;
z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
if( z==0 ) return;
for(i=0; z[i]; i++){
if( isupper(z[i]) ) z[i] = tolower(z[i]);
}
}
| func.c | 169 |
STATIC VOID | ifnullFunc(sqlite_func *context, int argc, const char **argv)
static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
int i;
for(i=0; ifunc.c | 180 | |
STATIC VOID | randomFunc(sqlite_func *context, int argc, const char **argv)
static void randomFunc(sqlite_func *context, int argc, const char **argv){
int r;
sqliteRandomness(sizeof(r), &r);
sqlite_set_result_int(context, r);
}
| func.c | 195 |
STATIC VOID | last_insert_rowid(sqlite_func *context, int arg, const char **argv)
static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){
sqlite *db = sqlite_user_data(context);
sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
}
| func.c | 204 |
STATIC VOID | change_count(sqlite_func *context, int arg, const char **argv)
static void change_count(sqlite_func *context, int arg, const char **argv){
sqlite *db = sqlite_user_data(context);
sqlite_set_result_int(context, sqlite_changes(db));
}
| func.c | 213 |
STATIC VOID | last_statement_change_count(sqlite_func *context, int arg, const char **argv)
static void last_statement_change_count(sqlite_func *context, int arg,
const char **argv){
sqlite *db = sqlite_user_data(context);
sqlite_set_result_int(context, sqlite_last_statement_changes(db));
}
| func.c | 222 |
STATIC VOID | likeFunc(sqlite_func *context, int arg, const char **argv)
static void likeFunc(sqlite_func *context, int arg, const char **argv){
if( argv[0]==0 || argv[1]==0 ) return;
sqlite_set_result_int(context,
sqliteLikeCompare((const unsigned char*)argv[0],
(const unsigned char*)argv[1]));
}
| func.c | 232 |
STATIC VOID | globFunc(sqlite_func *context, int arg, const char **argv)
static void globFunc(sqlite_func *context, int arg, const char **argv){
if( argv[0]==0 || argv[1]==0 ) return;
sqlite_set_result_int(context,
sqliteGlobCompare((const unsigned char*)argv[0],
(const unsigned char*)argv[1]));
}
| func.c | 248 |
STATIC VOID | nullifFunc(sqlite_func *context, int argc, const char **argv)
static void nullifFunc(sqlite_func *context, int argc, const char **argv){
if( argv[0]!=0 && sqliteCompare(argv[0],argv[1])!=0 ){
sqlite_set_result_string(context, argv[0], -1);
}
}
| func.c | 264 |
STATIC VOID | versionFunc(sqlite_func *context, int argc, const char **argv)
static void versionFunc(sqlite_func *context, int argc, const char **argv){
sqlite_set_result_string(context, sqlite_version, -1);
}
| func.c | 275 |
STATIC VOID | quoteFunc(sqlite_func *context, int argc, const char **argv)
static void quoteFunc(sqlite_func *context, int argc, const char **argv){
if( argc<1 ) return;
if( argv[0]==0 ){
sqlite_set_result_string(context, "NULL", 4);
}else if( sqliteIsNumber(argv[0]) ){
sqlite_set_result_string(context, argv[0], -1);
}else{
int i,j,n;
char *z;
for(i=n=0; argv[0][i]; i++){ if( argv[0][i]=='\'' ) n++; }
z = sqliteMalloc( i+n+3 );
if( z==0 ) return;
z[0] = '\'';
for(i=0, j=1; argv[0][i]; i++){
z[j++] = argv[0][i];
if( argv[0][i]=='\'' ){
z[j++] = '\'';
}
}
z[j++] = '\'';
z[j] = 0;
sqlite_set_result_string(context, z, j);
sqliteFree(z);
}
}
| func.c | 283 |
STATIC VOID | soundexFunc(sqlite_func *context, int argc, const char **argv)
static void soundexFunc(sqlite_func *context, int argc, const char **argv){
char zResult[8];
const char *zIn;
int i, j;
static const unsigned char iCode[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
};
assert( argc==1 );
zIn = argv[0];
for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
if( zIn[i] ){
zResult[0] = toupper(zIn[i]);
for(j=1; j<4 && zIn[i]; i++){
int code = iCode[zIn[i]&0x7f];
if( code>0 ){
zResult[j++] = code + '0';
}
}
while( j<4 ){
zResult[j++] = '0';
}
zResult[j] = 0;
sqlite_set_result_string(context, zResult, 4);
}else{
sqlite_set_result_string(context, "?000", 4);
}
}
| func.c | 321 |
STATIC VOID | randStr(sqlite_func *context, int argc, const char **argv)
static void randStr(sqlite_func *context, int argc, const char **argv){
static const unsigned char zSrc[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
".-!,:*^+=_|?/<> ";
int iMin, iMax, n, r, i;
unsigned char zBuf[1000];
if( argc>=1 ){
iMin = atoi(argv[0]);
if( iMin<0 ) iMin = 0;
if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
}else{
iMin = 1;
}
if( argc>=2 ){
iMax = atoi(argv[1]);
if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
}else{
iMax = 50;
}
n = iMin;
if( iMax>iMin ){
sqliteRandomness(sizeof(r), &r);
r &= 0x7fffffff;
n += r%(iMax + 1 - iMin);
}
assert( nfunc.c | 361 | |
STATIC VOID | sumStep(sqlite_func *context, int argc, const char **argv)
static void sumStep(sqlite_func *context, int argc, const char **argv){
SumCtx *p;
if( argc<1 ) return;
p = sqlite_aggregate_context(context, sizeof(*p));
if( p && argv[0] ){
p->sum += sqliteAtoF(argv[0], 0);
p->cnt++;
}
}
| func.c | 413 |
STATIC VOID | sumFinalize(sqlite_func *context)
static void sumFinalize(sqlite_func *context){
SumCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
sqlite_set_result_double(context, p ? p->sum : 0.0);
}
| func.c | 425 |
STATIC VOID | avgFinalize(sqlite_func *context)
static void avgFinalize(sqlite_func *context){
SumCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
if( p && p->cnt>0 ){
sqlite_set_result_double(context, p->sum/(double)p->cnt);
}
}
/*
** 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 */
};
| func.c | 430 |
STATIC VOID | stdDevStep(sqlite_func *context, int argc, const char **argv)
static void stdDevStep(sqlite_func *context, int argc, const char **argv){
StdDevCtx *p;
double x;
if( argc<1 ) return;
p = sqlite_aggregate_context(context, sizeof(*p));
if( p && argv[0] ){
x = sqliteAtoF(argv[0], 0);
p->sum += x;
p->sum2 += x*x;
p->cnt++;
}
}
| func.c | 450 |
STATIC VOID | stdDevFinalize(sqlite_func *context)
static void stdDevFinalize(sqlite_func *context){
double rN = sqlite_aggregate_count(context);
StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
if( p && p->cnt>1 ){
double rCnt = cnt;
sqlite_set_result_double(context,
sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
}
}
#endif
/*
** The following structure keeps track of state information for the
** count() aggregate function.
*/
typedef struct CountCtx CountCtx;
struct CountCtx {
int n;
};
| func.c | 465 |
STATIC VOID | countStep(sqlite_func *context, int argc, const char **argv)
static void countStep(sqlite_func *context, int argc, const char **argv){
CountCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
if( (argc==0 || argv[0]) && p ){
p->n++;
}
}
| func.c | 485 |
STATIC VOID | countFinalize(sqlite_func *context)
static void countFinalize(sqlite_func *context){
CountCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
sqlite_set_result_int(context, p ? p->n : 0);
}
/*
** This function tracks state information for the min() and max()
** aggregate functions.
*/
typedef struct MinMaxCtx MinMaxCtx;
struct MinMaxCtx {
char *z; /* The best so far */
char zBuf[28]; /* Space that can be used for storage */
};
| func.c | 495 |
STATIC VOID | minmaxStep(sqlite_func *context, int argc, const char **argv)
static void minmaxStep(sqlite_func *context, int argc, const char **argv){
MinMaxCtx *p;
int (*xCompare)(const char*, const char*);
int mask; /* 0 for min() or 0xffffffff for max() */
assert( argc==2 );
if( argv[0]==0 ) return; /* Ignore NULL values */
if( argv[1][0]=='n' ){
xCompare = sqliteCompare;
}else{
xCompare = strcmp;
}
mask = (int)sqlite_user_data(context);
assert( mask==0 || mask==-1 );
p = sqlite_aggregate_context(context, sizeof(*p));
if( p==0 || argc<1 ) return;
if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
int len;
if( p->zBuf[0] ){
sqliteFree(p->z);
}
len = strlen(argv[0]);
if( len < sizeof(p->zBuf)-1 ){
p->z = &p->zBuf[1];
p->zBuf[0] = 0;
}else{
p->z = sqliteMalloc( len+1 );
p->zBuf[0] = 1;
if( p->z==0 ) return;
}
strcpy(p->z, argv[0]);
}
}
| func.c | 511 |
STATIC VOID | minMaxFinalize(sqlite_func *context)
static void minMaxFinalize(sqlite_func *context){
MinMaxCtx *p;
p = sqlite_aggregate_context(context, sizeof(*p));
if( p && p->z && p->zBuf[0]<2 ){
sqlite_set_result_string(context, p->z, strlen(p->z));
}
if( p && p->zBuf[0] ){
sqliteFree(p->z);
}
}
| func.c | 547 |
VOID | sqliteRegisterBuiltinFunctions(sqlite *db)
void sqliteRegisterBuiltinFunctions(sqlite *db){
static struct {
char *zName;
signed char nArg;
signed char dataType;
u8 argType; /* 0: none. 1: db 2: (-1) */
void (*xFunc)(sqlite_func*,int,const char**);
} aFuncs[] = {
{ "min", -1, SQLITE_ARGS, 0, minmaxFunc },
{ "min", 0, 0, 0, 0 },
{ "max", -1, SQLITE_ARGS, 2, minmaxFunc },
{ "max", 0, 0, 2, 0 },
{ "typeof", 1, SQLITE_TEXT, 0, typeofFunc },
{ "length", 1, SQLITE_NUMERIC, 0, lengthFunc },
{ "substr", 3, SQLITE_TEXT, 0, substrFunc },
{ "abs", 1, SQLITE_NUMERIC, 0, absFunc },
{ "round", 1, SQLITE_NUMERIC, 0, roundFunc },
{ "round", 2, SQLITE_NUMERIC, 0, roundFunc },
{ "upper", 1, SQLITE_TEXT, 0, upperFunc },
{ "lower", 1, SQLITE_TEXT, 0, lowerFunc },
{ "coalesce", -1, SQLITE_ARGS, 0, ifnullFunc },
{ "coalesce", 0, 0, 0, 0 },
{ "coalesce", 1, 0, 0, 0 },
{ "ifnull", 2, SQLITE_ARGS, 0, ifnullFunc },
{ "random", -1, SQLITE_NUMERIC, 0, randomFunc },
{ "like", 2, SQLITE_NUMERIC, 0, likeFunc },
{ "glob", 2, SQLITE_NUMERIC, 0, globFunc },
{ "nullif", 2, SQLITE_ARGS, 0, nullifFunc },
{ "sqlite_version",0,SQLITE_TEXT, 0, versionFunc},
{ "quote", 1, SQLITE_ARGS, 0, quoteFunc },
{ "last_insert_rowid", 0, SQLITE_NUMERIC, 1, last_insert_rowid },
{ "change_count", 0, SQLITE_NUMERIC, 1, change_count },
{ "last_statement_change_count",
0, SQLITE_NUMERIC, 1, last_statement_change_count },
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, SQLITE_TEXT, 0, soundexFunc},
#endif
#ifdef SQLITE_TEST
{ "randstr", 2, SQLITE_TEXT, 0, randStr },
#endif
};
static struct {
char *zName;
signed char nArg;
signed char dataType;
u8 argType;
void (*xStep)(sqlite_func*,int,const char**);
void (*xFinalize)(sqlite_func*);
} aAggs[] = {
{ "min", 1, 0, 0, minmaxStep, minMaxFinalize },
{ "max", 1, 0, 2, minmaxStep, minMaxFinalize },
{ "sum", 1, SQLITE_NUMERIC, 0, sumStep, sumFinalize },
{ "avg", 1, SQLITE_NUMERIC, 0, sumStep, avgFinalize },
{ "count", 0, SQLITE_NUMERIC, 0, countStep, countFinalize },
{ "count", 1, SQLITE_NUMERIC, 0, countStep, countFinalize },
#if 0
{ "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep, stdDevFinalize },
#endif
};
static const char *azTypeFuncs[] = { "min", "max", "typeof" };
int i;
for(i=0; iaFunc, azTypeFuncs[i], n);
while( p ){
p->includeTypes = 1;
p = p->pNext;
}
}
sqliteRegisterDateTimeFunctions(db);
}
| func.c | 558 |
hash.c |
Type | Function | Source | Line |
VOID | sqliteHashInit(Hash *new, int keyClass, int copyKey)
void sqliteHashInit(Hash *new, int keyClass, int copyKey){
assert( new!=0 );
assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
new->keyClass = keyClass;
new->copyKey = copyKey &&
(keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
new->first = 0;
new->count = 0;
new->htsize = 0;
new->ht = 0;
}
| hash.c | 20 |
VOID | sqliteHashClear(Hash *pH)
void sqliteHashClear(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;
}
| hash.c | 44 |
STATIC INT | intHash(const void *pKey, int nKey)
static int intHash(const void *pKey, int nKey){
return nKey ^ (nKey<<8) ^ (nKey>>8);
}
| hash.c | 68 |
STATIC INT | intCompare(const void *pKey1, int n1, const void *pKey2, int n2)
static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
return n2 - n1;
}
| hash.c | 74 |
STATIC INT | ptrHash(const void *pKey, int nKey)
static int ptrHash(const void *pKey, int nKey){
uptr x = Addr(pKey);
return x ^ (x<<8) ^ (x>>8);
}
| hash.c | 79 |
STATIC INT | ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2)
static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( pKey1==pKey2 ) return 0;
if( pKey1hash.c | 86 | |
STATIC INT | strHash(const void *pKey, int nKey)
static int strHash(const void *pKey, int nKey){
return sqliteHashNoCase((const char*)pKey, nKey);
}
| hash.c | 93 |
STATIC INT | strCompare(const void *pKey1, int n1, const void *pKey2, int n2)
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return n2-n1;
return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
| hash.c | 99 |
STATIC INT | binHash(const void *pKey, int nKey)
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;
}
| hash.c | 104 |
STATIC INT | binCompare(const void *pKey1, int n1, const void *pKey2, int n2)
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return n2-n1;
return memcmp(pKey1,pKey2,n1);
}
| hash.c | 115 |
STATIC INT (*HASHFUNCTION(INT KEYCLASS) | (const void*,int)
static int (*hashFunction(int keyClass))(const void*,int){
switch( keyClass ){
case SQLITE_HASH_INT: return &intHash;
/* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
case SQLITE_HASH_STRING: return &strHash;
case SQLITE_HASH_BINARY: return &binHash;;
default: break;
}
return 0;
}
| hash.c | 120 |
STATIC INT (*COMPAREFUNCTION(INT KEYCLASS) | (const void*,int,const void*,int)
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
switch( keyClass ){
case SQLITE_HASH_INT: return &intCompare;
/* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
case SQLITE_HASH_STRING: return &strCompare;
case SQLITE_HASH_BINARY: return &binCompare;
default: break;
}
return 0;
}
| hash.c | 143 |
STATIC VOID | rehash(Hash *pH, int new_size)
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 */
HashElem *x; /* Element being copied to new hash table */
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;
x = new_ht[h].chain;
if( x ){
elem->next = x;
elem->prev = x->prev;
if( x->prev ) x->prev->next = elem;
else pH->first = elem;
x->prev = elem;
}else{
elem->next = pH->first;
if( pH->first ) pH->first->prev = elem;
elem->prev = 0;
pH->first = elem;
}
new_ht[h].chain = elem;
new_ht[h].count++;
}
}
| hash.c | 161 |
STATIC HASHELEM | findElementGivenHash( const Hash *pH, const void *pKey, int nKey, int h )
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 ){
elem = pH->ht[h].chain;
count = pH->ht[h].count;
xCompare = compareFunction(pH->keyClass);
while( count-- && elem ){
if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
}
}
return 0;
}
| hash.c | 199 |
STATIC VOID | removeElementGivenHash( Hash *pH, HashElem* elem, int h )
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 */
){
if( elem->prev ){
elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
if( elem->next ){
elem->next->prev = elem->prev;
}
if( pH->ht[h].chain==elem ){
pH->ht[h].chain = elem->next;
}
pH->ht[h].count--;
if( pH->ht[h].count<=0 ){
pH->ht[h].chain = 0;
}
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
}
sqliteFree( elem );
pH->count--;
}
| hash.c | 227 |
VOID | sqliteHashFind(const Hash *pH, const void *pKey, int nKey)
void *sqliteHashFind(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;
}
| hash.c | 257 |
VOID | sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data)
void *sqliteHashInsert(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 & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
elem = pH->ht[h].chain;
if( elem ){
new_elem->next = elem;
new_elem->prev = elem->prev;
if( elem->prev ){ elem->prev->next = new_elem; }
else { pH->first = new_elem; }
elem->prev = new_elem;
}else{
new_elem->next = pH->first;
new_elem->prev = 0;
if( pH->first ){ pH->first->prev = new_elem; }
pH->first = new_elem;
}
pH->ht[h].count++;
pH->ht[h].chain = new_elem;
new_elem->data = data;
return 0;
}
| hash.c | 275 |
hbsqlit2.c |
Type | Function | Source | Line |
HB_FUNC | SQLITE_INFO(void)
HB_FUNC( SQLITE_INFO )
{
hb_reta( 3 );
hb_storc( ( char * ) SQLITE_VERSION , -1, 1 );
hb_storc( ( char * ) sqlite_libversion() , -1, 2 );
hb_storc( ( char * ) sqlite_libencoding(), -1, 3 );
}
| hbsqlit2.c | 51 |
HB_FUNC | SQLITE_OPEN(void)
HB_FUNC( SQLITE_OPEN )
{
if( hb_sqlite2_db )
sqlite_close( hb_sqlite2_db );
hb_sqlite2_db = ( sqlite * ) sqlite_open( hb_parcx( 1 ), 0, &hb_sqlite2_szErrMsg );
hb_retni( hb_sqlite2_db == NULL ? 1 : 0 ); /* error: 1 */
}
| hbsqlit2.c | 60 |
HB_FUNC | SQLITE_CLOSE(void)
HB_FUNC( SQLITE_CLOSE )
{
if( hb_sqlite2_db )
{
sqlite_close( hb_sqlite2_db );
hb_sqlite2_db = NULL;
}
}
| hbsqlit2.c | 71 |
HB_FUNC | SQLITE_EXECUTE(void)
HB_FUNC( SQLITE_EXECUTE )
{
if( hb_sqlite2_db )
hb_retni( sqlite_exec( hb_sqlite2_db, hb_parcx( 1 ), NULL, NULL, &hb_sqlite2_szErrMsg ) );
}
| hbsqlit2.c | 81 |
HB_FUNC | SQLITE_QUERY(void)
HB_FUNC( SQLITE_QUERY )
{
char * szSQLcom = hb_parcx( 1 );
if( hb_sqlite2_db && sqlite_exec( hb_sqlite2_db, szSQLcom, NULL, NULL, &hb_sqlite2_szErrMsg ) == SQLITE_OK )
{
int iResRows = 0;
int iResCols = 0;
int iRec;
int iField;
char * pErrmsg;
char ** pResStr;
PHB_ITEM paRows;
int i;
/* put here a routine to process results */
sqlite_get_table( hb_sqlite2_db, /* An open database */
szSQLcom, /* SQL to be executed */
&pResStr, /* Result written to a char *[] that this points to */
&iResRows, /* Number of result rows written here */
&iResCols, /* Number of result columns written here */
&pErrmsg /* Error msg written here */
);
/* global results */
hb_sqlite2_iDataRows = iResRows; /* set rows from last operation */
hb_sqlite2_iDataCols = iResCols; /* set cols from last operation */
/* quiero devolver un array bidimensional donde la cantidad de filas
es rows +1 (ó reccords +1 ) y las columnas los campos
la primer fila contiene los encabezados de los campos */
/* dimension rows array */
paRows = hb_itemArrayNew( iResRows + 1 );
for( iRec = 0, i = 0; iRec < iResRows + 1; iRec++ )
{
if( iResCols > 1 ) /* if it's a multidimensional array */
{
PHB_ITEM paCols = hb_itemArrayNew( iResCols );
/* for every field */
for( iField = 0; iField < iResCols; iField++ )
hb_arraySetC( paCols, iField + 1, pResStr[ i++ ] );
/* put data onto subarray of records */
hb_itemArrayPut( paRows, iRec + 1, paCols );
hb_itemRelease( paCols );
}
else /* is an unidimensional array */
hb_arraySetC( paRows, iRec + 1, pResStr[ i++ ] );
}
/* free memory allocated */
sqlite_free_table( pResStr );
hb_itemReturnRelease( paRows );
}
else
hb_reta( 0 );
}
| hbsqlit2.c | 88 |
HB_FUNC | SQLITE_SYSCOLUMNS(void)
HB_FUNC( SQLITE_SYSCOLUMNS )
{
if( hb_sqlite2_db )
{
struct Table * pTable = ( struct Table * ) sqliteFindTable( hb_sqlite2_db, ( const char * ) hb_parcx( 1 ), NULL );
if( pTable )
{
/* dimension rows array:
1 is table name
2 is field number
3 to n cols data */
PHB_ITEM paRows = hb_itemArrayNew( 2 + pTable->nCol );
int iField;
/* the Table structure itself */
hb_arraySetC( paRows, 1, pTable->zName ); /* save name of table */
hb_arraySetNL( paRows, 2, pTable->nCol ); /* save number of cols/fields */
for( iField = 0; iField < pTable->nCol; iField++ )
{
/* it's a multidimensional array */
/* four data columns name, default, type, isprimarykey per field */
PHB_ITEM paCols = hb_itemArrayNew( 4 );
hb_arraySetC( paCols, 1, pTable->aCol[ iField ].zName );
hb_arraySetC( paCols, 2, pTable->aCol[ iField ].zDflt );
hb_arraySetC( paCols, 3, pTable->aCol[ iField ].zType );
hb_arraySetL( paCols, 4, pTable->aCol[ iField ].isPrimKey );
/* put data onto subarray of records */
hb_itemArrayPut( paRows, 3 + iField, paCols );
hb_itemRelease( paCols );
}
hb_itemReturnRelease( paRows );
return;
}
}
hb_reta( 0 );
}
| hbsqlit2.c | 151 |
HB_FUNC | SQLITE_FIELDS(void)
HB_FUNC( SQLITE_FIELDS )
{
if( hb_sqlite2_db )
{
struct Table * pTable = ( struct Table * ) sqliteFindTable( hb_sqlite2_db, ( const char * ) hb_parcx( 1 ), NULL );
if( pTable )
{
int i;
/* the Table structure itself */
hb_reta( pTable->nCol );
for( i = 0; i < pTable->nCol; i++ )
hb_storc( pTable->aCol[ i ].zName, -1, 1 + i );
return;
}
}
hb_reta( 0 );
}
| hbsqlit2.c | 195 |
HB_FUNC | SQLITE_NUMOFTABLES(void)
HB_FUNC( SQLITE_NUMOFTABLES )
{
hb_retni( hb_sqlite2_db ? hb_sqlite2_db->nTable - 2 : 0 );
}
| hbsqlit2.c | 219 |
HB_FUNC | SQLITE_ERROR(void)
HB_FUNC( SQLITE_ERROR )
{
hb_retc( hb_sqlite2_szErrMsg );
}
| hbsqlit2.c | 225 |
HB_FUNC | SQLITE_GETROWS(void)
HB_FUNC( SQLITE_GETROWS )
{
hb_retni( hb_sqlite2_iDataRows );
}
| hbsqlit2.c | 231 |
HB_FUNC | SQLITE_GETCOLS(void)
HB_FUNC( SQLITE_GETCOLS )
{
hb_retni( hb_sqlite2_iDataCols );
}
| hbsqlit2.c | 237 |
insert.c |
Type | Function | Source | Line |
VOID | sqliteInsert( Parse *pParse, SrcList *pTabList, ExprList *pList, Select *pSelect, IdList *pColumn, int onError )
void sqliteInsert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
ExprList *pList, /* List of values to be inserted */
Select *pSelect, /* A SELECT statement to use as the data source */
IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError /* How to handle constraint errors */
){
Table *pTab; /* The table to insert into */
char *zTab; /* Name of the table into which we are inserting */
const char *zDb; /* Name of the database holding this table */
int i, j, idx; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
int base; /* VDBE Cursor number for pTab */
int iCont, iBreak; /* Beginning and end of the loop over srcTab */
sqlite *db; /* The main database structure */
int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
int useTempTable; /* Store SELECT results in intermediate table */
int srcTab; /* Data comes from this temporary cursor if >=0 */
int iSelectLoop; /* Address of code that implements the SELECT */
int iCleanup; /* Address of the cleanup code */
int iInsertBlock; /* Address of the subroutine used to insert data */
int iCntMem; /* Memory cell used for the row counter */
int isView; /* True if attempting to insert into a view */
int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
int before_triggers; /* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int newIdx = -1; /* Cursor for the NEW table */
if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
db = pParse->db;
/* Locate the table into which we will be inserting new information.
*/
assert( pTabList->nSrc==1 );
zTab = pTabList->a[0].zName;
if( zTab==0 ) goto insert_cleanup;
pTab = sqliteSrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
}
assert( pTab->iDbnDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
/* Ensure that:
* (a) the table is not read-only,
* (b) that if it is a view then ON INSERT triggers exist
*/
before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT,
TK_BEFORE, TK_ROW, 0);
after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT,
TK_AFTER, TK_ROW, 0);
row_triggers_exist = before_triggers || after_triggers;
isView = pTab->pSelect!=0;
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
goto insert_cleanup;
}
if( pTab==0 ) goto insert_cleanup;
/* If pTab is really a view, make sure it has been initialized.
*/
if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
goto insert_cleanup;
}
/* Allocate a VDBE
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) goto insert_cleanup;
sqliteBeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
/* if there are row triggers, allocate a temp table for new.* references. */
if( row_triggers_exist ){
newIdx = pParse->nTab++;
}
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates
** all the code to implement the SELECT statement and invoke a subroutine
** to process each row of the result. (Template 2.) If the SELECT
** statement uses the the table that is being inserted into, then the
** subroutine is also coded here. That subroutine stores the SELECT
** results in a temporary table. (Template 3.)
*/
if( pSelect ){
/* Data is coming from a SELECT. Generate code to implement that SELECT
*/
int rc, iInitCode;
iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
iSelectLoop = sqliteVdbeCurrentAddr(v);
iInsertBlock = sqliteVdbeMakeLabel(v);
rc = sqliteSelect(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0);
if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
iCleanup = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Goto, 0, iCleanup);
assert( pSelect->pEList );
nColumn = pSelect->pEList->nExpr;
/* Set useTempTable to TRUE if the result of the SELECT statement
** should be written into a temporary table. Set to FALSE if each
** row of the SELECT can be written directly into the result table.
**
** A temp table must be used if the table being updated is also one
** of the tables being read by the SELECT statement. Also use a
** temp table in the case of row triggers.
*/
if( row_triggers_exist ){
useTempTable = 1;
}else{
int addr = sqliteVdbeFindOp(v, OP_OpenRead, pTab->tnum);
useTempTable = 0;
if( addr>0 ){
VdbeOp *pOp = sqliteVdbeGetOp(v, addr-2);
if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
useTempTable = 1;
}
}
}
if( useTempTable ){
/* Generate the subroutine that SELECT calls to process each row of
** the result. Store the result in a temporary table
*/
srcTab = pParse->nTab++;
sqliteVdbeResolveLabel(v, iInsertBlock);
sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
sqliteVdbeAddOp(v, OP_NewRecno, srcTab, 0);
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, srcTab, 0);
sqliteVdbeAddOp(v, OP_Return, 0, 0);
/* The following code runs first because the GOTO at the very top
** of the program jumps to it. Create the temporary table, then jump
** back up and execute the SELECT code above.
*/
sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqliteVdbeResolveLabel(v, iCleanup);
}else{
sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
}
}else{
/* This is the case if the data for the INSERT is coming from a VALUES
** clause
*/
SrcList dummy;
assert( pList!=0 );
srcTab = -1;
useTempTable = 0;
assert( pList );
nColumn = pList->nExpr;
dummy.nSrc = 0;
for(i=0; ia[i].pExpr) ){
goto insert_cleanup;
}
if( sqliteExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){
goto insert_cleanup;
}
}
}
/* Make sure the number of columns in the source data matches the number
** of columns to be inserted into the table.
*/
if( pColumn==0 && nColumn!=pTab->nCol ){
sqliteErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
pTabList, 0, pTab->nCol, nColumn);
goto insert_cleanup;
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
sqliteErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
goto insert_cleanup;
}
/* If the INSERT statement included an IDLIST term, then make sure
** all elements of the IDLIST really are columns of the table and
** remember the column indices.
**
** If the table has an INTEGER PRIMARY KEY column and that column
** is named in the IDLIST, then record in the keyColumn variable
** the index into IDLIST of the primary key column. keyColumn is
** the index of the primary key as it appears in IDLIST, not as
** is appears in the original table. (The index of the primary
** key in the original table is pTab->iPKey.)
*/
if( pColumn ){
for(i=0; inId; i++){
pColumn->a[i].idx = -1;
}
for(i=0; inId; i++){
for(j=0; jnCol; j++){
if( sqliteStrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
pColumn->a[i].idx = j;
if( j==pTab->iPKey ){
keyColumn = i;
}
break;
}
}
if( j>=pTab->nCol ){
if( sqliteIsRowid(pColumn->a[i].zName) ){
keyColumn = i;
}else{
sqliteErrorMsg(pParse, "table %S has no column named %s",
pTabList, 0, pColumn->a[i].zName);
pParse->nErr++;
goto insert_cleanup;
}
}
}
}
/* If there is no IDLIST term but the table has an integer primary
** key, the set the keyColumn variable to the primary key column index
** in the original table definition.
*/
if( pColumn==0 ){
keyColumn = pTab->iPKey;
}
/* Open the temp table for FOR EACH ROW triggers
*/
if( row_triggers_exist ){
sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
}
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
iCntMem = pParse->nMem++;
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);
}
/* Open tables and indices if there are no row triggers */
if( !row_triggers_exist ){
base = pParse->nTab;
idx = sqliteOpenTableAndIndices(pParse, pTab, base);
pParse->nTab += idx;
}
/* If the data source is a temporary table, then we have to create
** a loop because there might be multiple rows of data. If the data
** source is a subroutine call from the SELECT statement, then we need
** to launch the SELECT statement processing.
*/
if( useTempTable ){
iBreak = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
iCont = sqliteVdbeCurrentAddr(v);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqliteVdbeResolveLabel(v, iInsertBlock);
}
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqliteVdbeMakeLabel(v);
if( before_triggers ){
/* build the NEW.* reference row. Note that if there is an INTEGER
** PRIMARY KEY into which a NULL is being inserted, that NULL will be
** translated into a unique ID for the row. But on a BEFORE trigger,
** we do not know what the unique ID will be (because the insert has
** not happened yet) so we substitute a rowid of -1
*/
if( keyColumn<0 ){
sqliteVdbeAddOp(v, OP_Integer, -1, 0);
}else if( useTempTable ){
sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
}else{
sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Integer, -1, 0);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
}
/* Create the new column data
*/
for(i=0; inCol; i++){
if( pColumn==0 ){
j = i;
}else{
for(j=0; jnId; j++){
if( pColumn->a[j].idx==i ) break;
}
}
if( pColumn && j>=pColumn->nId ){
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
}else if( useTempTable ){
sqliteVdbeAddOp(v, OP_Column, srcTab, j);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
}else{
sqliteExprCode(pParse, pList->a[j].pExpr);
}
}
sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
/* Fire BEFORE or INSTEAD OF triggers */
if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab,
newIdx, -1, onError, endOfLoop) ){
goto insert_cleanup;
}
}
/* If any triggers exists, the opening of tables and indices is deferred
** until now.
*/
if( row_triggers_exist && !isView ){
base = pParse->nTab;
idx = sqliteOpenTableAndIndices(pParse, pTab, base);
pParse->nTab += idx;
}
/* Push the record number for the new entry onto the stack. The
** record number is a randomly generate integer created by NewRecno
** except when the table has an INTEGER PRIMARY KEY column, in which
** case the record number is the same as that column.
*/
if( !isView ){
if( keyColumn>=0 ){
if( useTempTable ){
sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
}else{
sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
}
/* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
** to generate a unique primary key value.
*/
sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
}
/* Push onto the stack, data for all columns of the new entry, beginning
** with the first column.
*/
for(i=0; inCol; i++){
if( i==pTab->iPKey ){
/* The value of the INTEGER PRIMARY KEY column is always a NULL.
** Whenever this column is read, the record number will be substituted
** in its place. So will fill this column with a NULL to avoid
** taking up data space with information that will never be used. */
sqliteVdbeAddOp(v, OP_String, 0, 0);
continue;
}
if( pColumn==0 ){
j = i;
}else{
for(j=0; jnId; j++){
if( pColumn->a[j].idx==i ) break;
}
}
if( pColumn && j>=pColumn->nId ){
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
}else if( useTempTable ){
sqliteVdbeAddOp(v, OP_Column, srcTab, j);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1);
}else{
sqliteExprCode(pParse, pList->a[j].pExpr);
}
}
/* Generate code to check constraints and generate index keys and
** do the insertion.
*/
sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop);
sqliteCompleteInsertion(pParse, pTab, base, 0,0,0,
after_triggers ? newIdx : -1);
}
/* Update the count of rows that are inserted
*/
if( (db->flags & SQLITE_CountRows)!=0 ){
sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0);
}
if( row_triggers_exist ){
/* Close all tables opened */
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
}
}
/* Code AFTER triggers */
if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,
onError, endOfLoop) ){
goto insert_cleanup;
}
}
/* The bottom of the loop, if the data source is a SELECT statement
*/
sqliteVdbeResolveLabel(v, endOfLoop);
if( useTempTable ){
sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
sqliteVdbeResolveLabel(v, iBreak);
sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
}else if( pSelect ){
sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
sqliteVdbeAddOp(v, OP_Return, 0, 0);
sqliteVdbeResolveLabel(v, iCleanup);
}
if( !row_triggers_exist ){
/* Close all tables opened */
sqliteVdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
}
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows inserted.
*/
if( db->flags & SQLITE_CountRows ){
sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC);
sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
}
insert_cleanup:
sqliteSrcListDelete(pTabList);
if( pList ) sqliteExprListDelete(pList);
if( pSelect ) sqliteSelectDelete(pSelect);
sqliteIdListDelete(pColumn);
}
| insert.c | 19 |
VOID | sqliteGenerateConstraintChecks( Parse *pParse, Table *pTab, int base, char *aIdxUsed, int recnoChng, int isUpdate, int overrideError, int ignoreDest )
void sqliteGenerateConstraintChecks(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int overrideError, /* Override onError to this if not OE_Default */
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
){
int i;
Vdbe *v;
int nCol;
int onError;
int addr;
int extra;
int iCur;
Index *pIdx;
int seenReplace = 0;
int jumpInst1, jumpInst2;
int contAddr;
int hasTwoRecnos = (isUpdate && recnoChng);
v = sqliteGetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
/* Test all NOT NULL constraints.
*/
for(i=0; iiPKey ){
continue;
}
onError = pTab->aCol[i].notNull;
if( onError==OE_None ) continue;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( pParse->db->onError!=OE_Default ){
onError = pParse->db->onError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
onError = OE_Abort;
}
sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0);
switch( onError ){
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
char *zMsg = 0;
sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,
" may not be NULL", (char*)0);
sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
break;
}
case OE_Ignore: {
sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
case OE_Replace: {
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
sqliteVdbeAddOp(v, OP_Push, nCol-i, 0);
break;
}
default: assert(0);
}
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
}
/* Test all CHECK constraints
*/
/**** TBD ****/
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
** of the new record does not previously exist. Except, if this
** is an UPDATE and the primary key is not changing, that is OK.
*/
if( recnoChng ){
onError = pTab->keyConf;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( pParse->db->onError!=OE_Default ){
onError = pParse->db->onError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
if( isUpdate ){
sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
}
sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
switch( onError ){
default: {
onError = OE_Abort;
/* Fall thru into the next case */
}
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
"PRIMARY KEY must be unique", P3_STATIC);
break;
}
case OE_Replace: {
sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
}
seenReplace = 1;
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
}
contAddr = sqliteVdbeCurrentAddr(v);
sqliteVdbeChangeP2(v, jumpInst2, contAddr);
if( isUpdate ){
sqliteVdbeChangeP2(v, jumpInst1, contAddr);
sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
}
}
/* Test all UNIQUE constraints by creating entries for each UNIQUE
** index and making sure that duplicate entries do not already exist.
** Add the new records to the indices as we go.
*/
extra = -1;
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */
extra++;
/* Create a key for accessing the index entry */
sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1);
for(i=0; inColumn; i++){
int idx = pIdx->aiColumn[i];
if( idx==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
}else{
sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
}
}
jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( pParse->db->onError!=OE_Default ){
onError = pParse->db->onError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
if( seenReplace ){
if( onError==OE_Ignore ) onError = OE_Replace;
else if( onError==OE_Fail ) onError = OE_Abort;
}
/* Check to see if the new index entry will be unique */
sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
/* Generate code that executes if the new index entry is not unique */
switch( onError ){
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
int j, n1, n2;
char zErrMsg[200];
strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column ");
n1 = strlen(zErrMsg);
for(j=0; jnColumn && n1aCol[pIdx->aiColumn[j]].zName;
n2 = strlen(zCol);
if( j>0 ){
strcpy(&zErrMsg[n1], ", ");
n1 += 2;
}
if( n1+n2>sizeof(zErrMsg)-30 ){
strcpy(&zErrMsg[n1], "...");
n1 += 3;
break;
}else{
strcpy(&zErrMsg[n1], zCol);
n1 += n2;
}
}
strcpy(&zErrMsg[n1],
pIdx->nColumn>1 ? " are not unique" : " is not unique");
sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
case OE_Replace: {
sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
}
seenReplace = 1;
break;
}
default: assert(0);
}
contAddr = sqliteVdbeCurrentAddr(v);
#if NULL_DISTINCT_FOR_UNIQUE
sqliteVdbeChangeP2(v, jumpInst1, contAddr);
#endif
sqliteVdbeChangeP2(v, jumpInst2, contAddr);
}
}
| insert.c | 541 |
VOID | sqliteCompleteInsertion( Parse *pParse, Table *pTab, int base, char *aIdxUsed, int recnoChng, int isUpdate, int newIdx )
void sqliteCompleteInsertion(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx /* Index of NEW table for triggers. -1 if none */
){
int i;
Vdbe *v;
int nIdx;
Index *pIdx;
v = sqliteGetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
for(i=nIdx-1; i>=0; i--){
if( aIdxUsed && aIdxUsed[i]==0 ) continue;
sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0);
}
sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
if( newIdx>=0 ){
sqliteVdbeAddOp(v, OP_Dup, 1, 0);
sqliteVdbeAddOp(v, OP_Dup, 1, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
}
sqliteVdbeAddOp(v, OP_PutIntKey, base,
(pParse->trigStack?0:OPFLAG_NCHANGE) |
(isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
if( isUpdate && recnoChng ){
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
}
}
| insert.c | 853 |
INT | sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base)
int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){
int i;
Index *pIdx;
Vdbe *v = sqliteGetVdbe(pParse);
assert( v!=0 );
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC);
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);
}
return i;
}
| insert.c | 899 |
main.c |
Type | Function | Source | Line |
STATIC VOID | corruptSchema(InitData *pData, const char *zExtra)
static void corruptSchema(InitData *pData, const char *zExtra){
sqliteSetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
| main.c | 32 |
STATIC INT | sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName)
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
int nErr = 0;
assert( argc==5 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[0]==0 ){
corruptSchema(pData, 0);
return 1;
}
switch( argv[0][0] ){
case 'v':
case 'i':
case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
sqlite *db = pData->db;
if( argv[2]==0 || argv[4]==0 ){
corruptSchema(pData, 0);
return 1;
}
if( argv[3] && argv[3][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
*/
char *zErr;
assert( db->init.busy );
db->init.iDb = atoi(argv[4]);
assert( db->init.iDb>=0 && db->init.iDbnDb );
db->init.newTnum = atoi(argv[2]);
if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
corruptSchema(pData, zErr);
sqlite_freemem(zErr);
}
db->init.iDb = 0;
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
** constraint for a CREATE TABLE. The index should have already
** been created when we processed the CREATE TABLE. All we have
** to do here is record the root page number for that index.
*/
int iDb;
Index *pIndex;
iDb = atoi(argv[4]);
assert( iDb>=0 && iDbnDb );
pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
if( pIndex==0 || pIndex->tnum!=0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
*/
/* Do Nothing */;
}else{
pIndex->tnum = atoi(argv[2]);
}
}
break;
}
default: {
/* This can not happen! */
nErr = 1;
assert( nErr==0 );
}
}
return nErr;
}
| main.c | 41 |
STATIC INT | upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed)
static
int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){
InitData *pData = (InitData*)pInit;
int rc;
Table *pTab;
Trigger *pTrig;
char *zErr = 0;
pTab = sqliteFindTable(pData->db, argv[0], 0);
assert( pTab!=0 );
assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
if( pTab ){
pTrig = pTab->pTrigger;
pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */
}
rc = sqlite_exec_printf(pData->db,
"CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "
"DELETE FROM '%q'; "
"INSERT INTO '%q' SELECT * FROM sqlite_x; "
"DROP TABLE sqlite_x;",
0, 0, &zErr, argv[0], argv[0], argv[0]);
if( zErr ){
if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg);
*pData->pzErrMsg = zErr;
}
/* If an error occurred in the SQL above, then the transaction will
** rollback which will delete the internal symbol tables. This will
** cause the structure that pTab points to be deleted. In case that
** happened, we need to refetch pTab.
*/
pTab = sqliteFindTable(pData->db, argv[0], 0);
if( pTab ){
assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
pTab->pTrigger = pTrig; /* Re-enable triggers */
}
return rc!=SQLITE_OK;
}
| main.c | 126 |
STATIC INT | sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg)
static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
int rc;
BtCursor *curMain;
int size;
Table *pTab;
char const *azArg[6];
char zDbNum[30];
int meta[SQLITE_N_BTREE_META];
InitData initData;
char const *zMasterSchema;
char const *zMasterName;
char *zSql = 0;
/*
** The master database table has a structure like this
*/
static char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
static char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
assert( iDb>=0 && iDbnDb );
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
** initialised. zMasterName is the name of the master table.
*/
if( iDb==1 ){
zMasterSchema = temp_master_schema;
zMasterName = TEMP_MASTER_NAME;
}else{
zMasterSchema = master_schema;
zMasterName = MASTER_NAME;
}
/* Construct the schema table.
*/
sqliteSafetyOff(db);
azArg[0] = "table";
azArg[1] = zMasterName;
azArg[2] = "2";
azArg[3] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[4] = zDbNum;
azArg[5] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
sqliteInitCallback(&initData, 5, (char **)azArg, 0);
pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}else{
return SQLITE_NOMEM;
}
sqliteSafetyOn(db);
/* Create a cursor to hold the database open
*/
if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
if( rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
return rc;
}
/* Get the database meta information
*/
rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
if( rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
sqliteBtreeCloseCursor(curMain);
return rc;
}
db->aDb[iDb].schema_cookie = meta[1];
if( iDb==0 ){
db->next_cookie = meta[1];
db->file_format = meta[2];
size = meta[3];
if( size==0 ){ size = MAX_PAGES; }
db->cache_size = size;
db->safety_level = meta[4];
if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){
db->temp_store = meta[6];
}
if( db->safety_level==0 ) db->safety_level = 2;
/*
** file_format==1 Version 2.1.0.
** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY.
** file_format==3 Version 2.6.0. Fix empty-string index bug.
** file_format==4 Version 2.7.0. Add support for separate numeric and
** text datatypes.
*/
if( db->file_format==0 ){
/* This happens if the database was initially empty */
db->file_format = 4;
}else if( db->file_format>4 ){
sqliteBtreeCloseCursor(curMain);
sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
}else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
assert( db->file_format>=4 );
if( meta[2]==0 ){
sqliteSetString(pzErrMsg, "cannot attach empty database: ",
db->aDb[iDb].zName, (char*)0);
}else{
sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
"database: ", db->aDb[iDb].zName, (char*)0);
}
sqliteBtreeClose(db->aDb[iDb].pBt);
db->aDb[iDb].pBt = 0;
return SQLITE_FORMAT;
}
sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
sqliteSafetyOff(db);
/* The following SQL will read the schema from the master tables.
** The first version works with SQLite file formats 2 or greater.
** The second version is for format 1 files.
**
** Beginning with file format 2, the rowid for new table entries
** (including entries in sqlite_master) is an increasing integer.
** So for file format 2 and later, we can play back sqlite_master
** and all the CREATE statements will appear in the right order.
** But with file format 1, table entries were random and so we
** have to make sure the CREATE TABLEs occur before their corresponding
** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
** CREATE TRIGGER in file format 1 because those constructs did
** not exist then.)
*/
if( db->file_format>=2 ){
sqliteSetString(&zSql,
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
}else{
sqliteSetString(&zSql,
"SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
db->aDb[iDb].zName, "\".", zMasterName,
" WHERE type IN ('table', 'index')"
" ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
}
rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
sqliteFree(zSql);
sqliteSafetyOn(db);
sqliteBtreeCloseCursor(curMain);
if( sqlite_malloc_failed ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
sqliteResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqliteResetInternalSchema(db, iDb);
}
return rc;
}
| main.c | 179 |
INT | sqliteInit(sqlite *db, char **pzErrMsg)
int sqliteInit(sqlite *db, char **pzErrMsg){
int i, rc;
if( db->init.busy ) return SQLITE_OK;
assert( (db->flags & SQLITE_Initialized)==0 );
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && inDb; i++){
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
rc = sqliteInitOne(db, i, pzErrMsg);
if( rc ){
sqliteResetInternalSchema(db, i);
}
}
/* Once all the other databases have been initialised, load the schema
** for the TEMP database. This is loaded last, as the TEMP database
** schema may contain references to objects in other databases.
*/
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqliteInitOne(db, 1, pzErrMsg);
if( rc ){
sqliteResetInternalSchema(db, 1);
}
}
db->init.busy = 0;
if( rc==SQLITE_OK ){
db->flags |= SQLITE_Initialized;
sqliteCommitInternalChanges(db);
}
/* If the database is in formats 1 or 2, then upgrade it to
** version 3. This will reconstruct all indices. If the
** upgrade fails for any reason (ex: out of disk space, database
** is read only, interrupt received, etc.) then fail the init.
*/
if( rc==SQLITE_OK && db->file_format<3 ){
char *zErr = 0;
InitData initData;
int meta[SQLITE_N_BTREE_META];
db->magic = SQLITE_MAGIC_OPEN;
initData.db = db;
initData.pzErrMsg = &zErr;
db->file_format = 3;
rc = sqlite_exec(db,
"BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
upgrade_3_callback,
&initData,
&zErr);
if( rc==SQLITE_OK ){
sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
meta[2] = 4;
sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
sqlite_exec(db, "COMMIT", 0, 0, 0);
}
if( rc!=SQLITE_OK ){
sqliteSetString(pzErrMsg,
"unable to upgrade database to the version 2.6 format",
zErr ? ": " : 0, zErr, (char*)0);
}
sqlite_freemem(zErr);
}
if( rc!=SQLITE_OK ){
db->flags &= ~SQLITE_Initialized;
}
return rc;
}
/*
** The version of the library
*/
const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
const char sqlite_version[] = SQLITE_VERSION;
/*
** Does the library expect data to be encoded as UTF-8 or iso8859? The
** following global constant always lets us know.
*/
#ifdef SQLITE_UTF8
const char sqlite_encoding[] = "UTF-8";
#else
const char sqlite_encoding[] = "iso8859";
| main.c | 366 |
SQLITE | sqlite_open(const char *zFilename, int mode, char **pzErrMsg)
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
sqlite *db;
int rc, i;
/* Allocate the sqlite data structure */
db = sqliteMalloc( sizeof(sqlite) );
if( pzErrMsg ) *pzErrMsg = 0;
if( db==0 ) goto no_mem_on_open;
db->onError = OE_Default;
db->priorNewRowid = 0;
db->magic = SQLITE_MAGIC_BUSY;
db->nDb = 2;
db->aDb = db->aDbStatic;
/* db->flags |= SQLITE_ShortColNames; */
sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
for(i=0; inDb; i++){
sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
}
/* Open the backend database driver */
if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
db->temp_store = 2;
}
rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
switch( rc ){
default: {
sqliteSetString(pzErrMsg, "unable to open database: ",
zFilename, (char*)0);
}
}
sqliteFree(db);
sqliteStrRealloc(pzErrMsg);
return 0;
}
db->aDb[0].zName = "main";
db->aDb[1].zName = "temp";
/* Attempt to read the schema */
sqliteRegisterBuiltinFunctions(db);
rc = sqliteInit(db, pzErrMsg);
db->magic = SQLITE_MAGIC_OPEN;
if( sqlite_malloc_failed ){
sqlite_close(db);
goto no_mem_on_open;
}else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
sqlite_close(db);
sqliteStrRealloc(pzErrMsg);
return 0;
}else if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = 0;
}
/* Return a pointer to the newly opened database structure */
return db;
no_mem_on_open:
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
sqliteStrRealloc(pzErrMsg);
return 0;
}
| main.c | 466 |
INT | sqlite_last_insert_rowid(sqlite *db)
int sqlite_last_insert_rowid(sqlite *db){
return db->lastRowid;
}
| main.c | 541 |
INT | sqlite_changes(sqlite *db)
int sqlite_changes(sqlite *db){
return db->nChange;
}
| main.c | 548 |
INT | sqlite_last_statement_changes(sqlite *db)
int sqlite_last_statement_changes(sqlite *db){
return db->lsChange;
}
| main.c | 555 |
VOID | sqlite_close(sqlite *db)
void sqlite_close(sqlite *db){
HashElem *i;
int j;
db->want_to_close = 1;
if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
/* printf("DID NOT CLOSE\n"); fflush(stdout); */
return;
}
db->magic = SQLITE_MAGIC_CLOSED;
for(j=0; jnDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
sqliteBtreeClose(pDb->pBt);
pDb->pBt = 0;
}
}
sqliteResetInternalSchema(db, 0);
assert( db->nDb<=2 );
assert( db->aDb==db->aDbStatic );
for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
FuncDef *pFunc, *pNext;
for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
pNext = pFunc->pNext;
sqliteFree(pFunc);
}
}
sqliteHashClear(&db->aFunc);
sqliteFree(db);
}
| main.c | 565 |
VOID | sqliteRollbackAll(sqlite *db)
void sqliteRollbackAll(sqlite *db){
int i;
for(i=0; inDb; i++){
if( db->aDb[i].pBt ){
sqliteBtreeRollback(db->aDb[i].pBt);
db->aDb[i].inTrans = 0;
}
}
sqliteResetInternalSchema(db, 0);
/* sqliteRollbackInternalChanges(db); */
}
| main.c | 598 |
INT | sqlite_exec( sqlite *db, const char *zSql, sqlite_callback xCallback, void *pArg, char **pzErrMsg )
int sqlite_exec(
sqlite *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
sqlite_callback xCallback, /* Invoke this callback routine */
void *pArg, /* First argument to xCallback() */
char **pzErrMsg /* Write error messages here */
){
int rc = SQLITE_OK;
const char *zLeftover;
sqlite_vm *pVm;
int nRetry = 0;
int nChange = 0;
int nCallback;
if( zSql==0 ) return SQLITE_OK;
while( rc==SQLITE_OK && zSql[0] ){
pVm = 0;
rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg);
if( rc!=SQLITE_OK ){
assert( pVm==0 || sqlite_malloc_failed );
return rc;
}
if( pVm==0 ){
/* This happens if the zSql input contained only whitespace */
break;
}
db->nChange += nChange;
nCallback = 0;
while(1){
int nArg;
char **azArg, **azCol;
rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol);
if( rc==SQLITE_ROW ){
if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){
sqlite_finalize(pVm, 0);
return SQLITE_ABORT;
}
nCallback++;
}else{
if( rc==SQLITE_DONE && nCallback==0
&& (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){
xCallback(pArg, nArg, azArg, azCol);
}
rc = sqlite_finalize(pVm, pzErrMsg);
if( rc==SQLITE_SCHEMA && nRetry<2 ){
nRetry++;
rc = SQLITE_OK;
break;
}
if( db->pVdbe==0 ){
nChange = db->nChange;
}
nRetry = 0;
zSql = zLeftover;
while( isspace(zSql[0]) ) zSql++;
break;
}
}
}
return rc;
}
| main.c | 613 |
INT | sqlite_compile( sqlite *db, const char *zSql, const char **pzTail, sqlite_vm **ppVm, char **pzErrMsg )
int sqlite_compile(
sqlite *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
const char **pzTail, /* OUT: Next statement after the first */
sqlite_vm **ppVm, /* OUT: The virtual machine */
char **pzErrMsg /* OUT: Write error messages here */
){
Parse sParse;
if( pzErrMsg ) *pzErrMsg = 0;
if( sqliteSafetyOn(db) ) goto exec_misuse;
if( !db->init.busy ){
if( (db->flags & SQLITE_Initialized)==0 ){
int rc, cnt = 1;
while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
&& db->xBusyCallback
&& db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
if( rc!=SQLITE_OK ){
sqliteStrRealloc(pzErrMsg);
sqliteSafetyOff(db);
return rc;
}
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = 0;
}
}
if( db->file_format<3 ){
sqliteSafetyOff(db);
sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
return SQLITE_ERROR;
}
}
assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
if( db->pVdbe==0 ){ db->nChange = 0; }
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sqliteRunParser(&sParse, zSql, pzErrMsg);
if( db->xTrace && !db->init.busy ){
/* Trace only the statment that was compiled.
** Make a copy of that part of the SQL string since zSQL is const
** and we must pass a zero terminated string to the trace function
** The copy is unnecessary if the tail pointer is pointing at the
** beginnig or end of the SQL string.
*/
if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);
if( tmpSql ){
db->xTrace(db->pTraceArg, tmpSql);
free(tmpSql);
}else{
/* If a memory error occurred during the copy,
** trace entire SQL string and fall through to the
** sqlite_malloc_failed test to report the error.
*/
db->xTrace(db->pTraceArg, zSql);
}
}else{
db->xTrace(db->pTraceArg, zSql);
}
}
if( sqlite_malloc_failed ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
sParse.rc = SQLITE_NOMEM;
sqliteRollbackAll(db);
sqliteResetInternalSchema(db, 0);
db->flags &= ~SQLITE_InTrans;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0);
}
sqliteStrRealloc(pzErrMsg);
if( sParse.rc==SQLITE_SCHEMA ){
sqliteResetInternalSchema(db, 0);
}
assert( ppVm );
*ppVm = (sqlite_vm*)sParse.pVdbe;
if( pzTail ) *pzTail = sParse.zTail;
if( sqliteSafetyOff(db) ) goto exec_misuse;
return sParse.rc;
exec_misuse:
if( pzErrMsg ){
*pzErrMsg = 0;
sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
sqliteStrRealloc(pzErrMsg);
}
return SQLITE_MISUSE;
}
| main.c | 686 |
INT | sqlite_finalize( sqlite_vm *pVm, char **pzErrMsg )
int sqlite_finalize(
sqlite_vm *pVm, /* The virtual machine to be destroyed */
char **pzErrMsg /* OUT: Write error messages here */
){
int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg);
sqliteStrRealloc(pzErrMsg);
return rc;
}
| main.c | 783 |
INT | sqlite_reset( sqlite_vm *pVm, char **pzErrMsg )
int sqlite_reset(
sqlite_vm *pVm, /* The virtual machine to be destroyed */
char **pzErrMsg /* OUT: Write error messages here */
){
int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0);
sqliteStrRealloc(pzErrMsg);
return rc;
}
| main.c | 803 |
CONST CHAR | sqlite_error_string(int rc)
const char *sqlite_error_string(int rc){
const char *z;
switch( rc ){
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database is locked"; break;
case SQLITE_LOCKED: z = "database table is locked"; break;
case SQLITE_NOMEM: z = "out of memory"; break;
case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_NOTFOUND: z = "table or record not found"; break;
case SQLITE_FULL: z = "database is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
case SQLITE_EMPTY: z = "table contains no data"; break;
case SQLITE_SCHEMA: z = "database schema has changed"; break;
case SQLITE_TOOBIG: z = "too much data for one table row"; break;
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
case SQLITE_MISUSE: z = "library routine called out of sequence";break;
case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
case SQLITE_RANGE: z = "bind index out of range"; break;
case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
default: z = "unknown error"; break;
}
return z;
}
| main.c | 820 |
STATIC INT | sqliteDefaultBusyCallback( void *Timeout, const char *NotUsed, int count )
static int sqliteDefaultBusyCallback(
void *Timeout, /* Maximum amount of time to wait */
const char *NotUsed, /* The name of the table that is busy */
int count /* Number of times table has been busy */
){
#if SQLITE_MIN_SLEEP_MS==1
static const char delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100};
static const short int totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
int timeout = (int)(long)Timeout;
int delay, prior;
if( count <= NDELAY ){
delay = delays[count-1];
prior = totals[count-1];
}else{
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
}
if( prior + delay > timeout ){
delay = timeout - prior;
if( delay<=0 ) return 0;
}
sqliteOsSleep(delay);
return 1;
#else
int timeout = (int)(long)Timeout;
if( (count+1)*1000 > timeout ){
return 0;
}
sqliteOsSleep(1000);
return 1;
#endif
}
| main.c | 859 |
VOID SQLITE_BUSY_HANDLER( SQLITE *DB, INT (*XBUSY | (void*,const char*,int), void *pArg )
void sqlite_busy_handler(
sqlite *db,
int (*xBusy)(void*,const char*,int),
void *pArg
){
db->xBusyCallback = xBusy;
db->pBusyArg = pArg;
}
| main.c | 902 |
VOID SQLITE_PROGRESS_HANDLER( SQLITE *DB, INT NOPS, INT (*XPROGRESS | (void*), void *pArg )
void sqlite_progress_handler(
sqlite *db,
int nOps,
int (*xProgress)(void*),
void *pArg
){
if( nOps>0 ){
db->xProgress = xProgress;
db->nProgressOps = nOps;
db->pProgressArg = pArg;
}else{
db->xProgress = 0;
db->nProgressOps = 0;
db->pProgressArg = 0;
}
}
| main.c | 916 |
VOID | sqlite_busy_timeout(sqlite *db, int ms)
void sqlite_busy_timeout(sqlite *db, int ms){
if( ms>0 ){
sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
}else{
sqlite_busy_handler(db, 0, 0);
}
}
| main.c | 940 |
VOID | sqlite_interrupt(sqlite *db)
void sqlite_interrupt(sqlite *db){
db->flags |= SQLITE_Interrupt;
}
/*
** Windows systems should call this routine to free memory that
** is returned in the in the errmsg parameter of sqlite_open() when
** SQLite is a DLL. For some reason, it does not work to call free()
** directly.
**
** Note that we need to call free() not sqliteFree() here, since every
** string that is exported from SQLite should have already passed through
** sqliteStrRealloc().
*/
void sqlite_freemem(void *p){ free(p); }
/*
** Windows systems need functions to call to return the sqlite_version
** and sqlite_encoding strings since they are unable to access constants
** within DLLs.
*/
const char *sqlite_libversion(void){ return sqlite_version; }
const char *sqlite_libencoding(void){ return sqlite_encoding; }
| main.c | 952 |
} INT SQLITE_CREATE_FUNCTION( SQLITE *DB, CONST CHAR *ZNAME, INT NARG, VOID (*XFUNC | (sqlite_func*,int,const char**), void *pUserData )
int sqlite_create_function(
sqlite *db, /* Add the function to this database connection */
const char *zName, /* Name of the function to add */
int nArg, /* Number of arguments */
void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */
void *pUserData /* User data */
){
FuncDef *p;
int nName;
if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
if( nArg<-1 || nArg>127 ) return 1;
nName = strlen(zName);
if( nName>255 ) return 1;
p = sqliteFindFunction(db, zName, nName, nArg, 1);
if( p==0 ) return 1;
p->xFunc = xFunc;
p->xStep = 0;
p->xFinalize = 0;
p->pUserData = pUserData;
return 0;
}
| main.c | 979 |
INT SQLITE_CREATE_AGGREGATE( SQLITE *DB, CONST CHAR *ZNAME, INT NARG, VOID (*XSTEP)(SQLITE_FUNC*,INT,CONST CHAR**), VOID (*XFINALIZE | (sqlite_func*), void *pUserData )
int sqlite_create_aggregate(
sqlite *db, /* Add the function to this database connection */
const char *zName, /* Name of the function to add */
int nArg, /* Number of arguments */
void (*xStep)(sqlite_func*,int,const char**), /* The step function */
void (*xFinalize)(sqlite_func*), /* The finalizer */
void *pUserData /* User data */
){
FuncDef *p;
int nName;
if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
if( nArg<-1 || nArg>127 ) return 1;
nName = strlen(zName);
if( nName>255 ) return 1;
p = sqliteFindFunction(db, zName, nName, nArg, 1);
if( p==0 ) return 1;
p->xFunc = 0;
p->xStep = xStep;
p->xFinalize = xFinalize;
p->pUserData = pUserData;
return 0;
}
| main.c | 1014 |
INT | sqlite_function_type(sqlite *db, const char *zName, int dataType)
int sqlite_function_type(sqlite *db, const char *zName, int dataType){
FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName));
while( p ){
p->dataType = dataType;
p = p->pNext;
}
return SQLITE_OK;
}
| main.c | 1037 |
VOID *SQLITE_TRACE(SQLITE *DB, VOID (*XTRACE | (void*,const char*), void *pArg)
void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){
void *pOld = db->pTraceArg;
db->xTrace = xTrace;
db->pTraceArg = pArg;
return pOld;
}
| main.c | 1051 |
VOID *SQLITE_COMMIT_HOOK( SQLITE *DB, INT (*XCALLBACK | (void*), void *pArg )
void *sqlite_commit_hook(
sqlite *db, /* Attach the hook to this database */
int (*xCallback)(void*), /* Function to invoke on each commit */
void *pArg /* Argument to the function */
){
void *pOld = db->pCommitArg;
db->xCommitCallback = xCallback;
db->pCommitArg = pArg;
return pOld;
}
| main.c | 1066 |
INT | sqliteBtreeFactory( const sqlite *db, const char *zFilename, int omitJournal, int nCache, Btree **ppBtree)
int sqliteBtreeFactory(
const sqlite *db, /* Main database when opening aux otherwise 0 */
const char *zFilename, /* Name of the file containing the BTree database */
int omitJournal, /* if TRUE then do not journal this file */
int nCache, /* How many pages in the page cache */
Btree **ppBtree){ /* Pointer to new Btree object written here */
assert( ppBtree != 0);
#ifndef SQLITE_OMIT_INMEMORYDB
if( zFilename==0 ){
if (TEMP_STORE == 0) {
/* Always use file based temporary DB */
return sqliteBtreeOpen(0, omitJournal, nCache, ppBtree);
} else if (TEMP_STORE == 1 || TEMP_STORE == 2) {
/* Switch depending on compile-time and/or runtime settings. */
int location = db->temp_store==0 ? TEMP_STORE : db->temp_store;
if (location == 1) {
return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
} else {
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}
} else {
/* Always use in-core DB */
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}
}else if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
return sqliteRbtreeOpen(0, 0, 0, ppBtree);
}else
#endif
{
return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
}
}
| main.c | 1084 |
os.c |
Type | Function | Source | Line |
__INLINE__ UNSIGNED LONG LONG INT | hwtime(void)
__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 SEEK(X) last_page=(X)
#define TRACE1(X) fprintf(stderr,X)
#define TRACE2(X,Y) fprintf(stderr,X,Y)
#define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z)
#define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
#else
#define TIMER_START
#define TIMER_END
#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)
#endif
#if OS_UNIX
/*
** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996)
** section 6.5.2.2 lines 483 through 490 specify that when a process
** sets or clears a lock, that operation overrides any prior locks set
** by the same process. It does not explicitly say so, but this implies
** that it overrides locks set by the same process using a different
** file descriptor. Consider this test case:
**
** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
**
** Suppose ./file1 and ./file2 are really the same file (because
** one is a hard or symbolic link to the other) then if you set
** an exclusive lock on fd1, then try to get an exclusive lock
** on fd2, it works. I would have expected the second lock to
** fail since there was already a lock on the file due to fd1.
** But not so. Since both locks came from the same process, the
** second overrides the first, even though they were on different
** file descriptors opened on different file names.
**
** Bummer. If you ask me, this is broken. Badly broken. It means
** that we cannot use POSIX locks to synchronize file access among
** competing threads of the same process. POSIX locks will work fine
** to synchronize access for threads in separate processes, but not
** threads within the same process.
**
** To work around the problem, SQLite has to manage file locks internally
** on its own. Whenever a new database is opened, we have to find the
** specific inode of the database file (the inode is determined by the
** st_dev and st_ino fields of the stat structure that fstat() fills in)
** and check for locks already existing on that inode. When locks are
** created or removed, we have to look at our own internal record of the
** locks to see if another thread has previously set a lock on that same
** inode.
**
** The OsFile structure for POSIX is no longer just an integer file
** descriptor. It is now a structure that holds the integer file
** descriptor and a pointer to a structure that describes the internal
** locks on the corresponding inode. There is one locking structure
** per inode, so if the same inode is opened twice, both OsFile structures
** point to the same locking structure. The locking structure keeps
** a reference count (so we will know when to delete it) and a "cnt"
** field that tells us its internal lock status. cnt==0 means the
** file is unlocked. cnt==-1 means the file has an exclusive lock.
** cnt>0 means there are cnt shared locks on the file.
**
** Any attempt to lock or unlock a file first checks the locking
** structure. The fcntl() system call is only invoked to set a
** POSIX lock if the internal lock structure transitions between
** a locked and an unlocked state.
**
** 2004-Jan-11:
** More recent discoveries about POSIX advisory locks. (The more
** I discover, the more I realize the a POSIX advisory locks are
** an abomination.)
**
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released. To work around this problem, each OsFile structure contains
** a pointer to an openCnt structure. There is one openCnt structure
** per open inode, which means that multiple OsFiles can point to a single
** openCnt. When an attempt is made to close an OsFile, if there are
** other OsFiles open on the same inode that are holding locks, the call
** to close() the file descriptor is deferred until all of the locks clear.
** The openCnt structure keeps a list of file descriptors that need to
** be closed and that list is walked (and cleared) when the last lock
** clears.
**
** First, under Linux threads, because each thread has a separate
** process ID, lock operations in one thread do not override locks
** to the same file in other threads. Linux threads behave like
** separate processes in this respect. But, if you close a file
** descriptor in linux threads, all locks are cleared, even locks
** on other threads and even though the other threads have different
** process IDs. Linux threads is inconsistent in this respect.
** (I'm beginning to think that linux threads is an abomination too.)
** The consequence of this all is that the hash table for the lockInfo
** structure has to include the process id as part of its key because
** locks in different threads are treated as distinct. But the
** openCnt structure should not include the process id in its
** key because close() clears lock on all threads, not just the current
** thread. Were it not for this goofiness in linux threads, we could
** combine the lockInfo and openCnt structures into a single structure.
*/
/*
** An instance of the following structure serves as the key used
** to locate a particular lockInfo structure given its inode. Note
** that we have to include the process ID as part of the key. On some
** threading implementations (ex: linux), each thread has a separate
** process ID.
*/
struct lockKey {
dev_t dev; /* Device number */
ino_t ino; /* Inode number */
pid_t pid; /* Process ID */
};
/*
** An instance of the following structure is allocated for each open
** inode on each thread with a different process ID. (Threads have
** different process IDs on linux, but not on most other unixes.)
**
** A single inode can have multiple file descriptors, so each OsFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of OsFiles pointing to it.
*/
struct lockInfo {
struct lockKey key; /* The lookup key */
int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */
int nRef; /* Number of pointers to this structure */
};
/*
** An instance of the following structure serves as the key used
** to locate a particular openCnt structure given its inode. This
** is the same as the lockKey except that the process ID is omitted.
*/
struct openKey {
dev_t dev; /* Device number */
ino_t ino; /* Inode number */
};
/*
** An instance of the following structure is allocated for each open
** inode. This structure keeps track of the number of locks on that
** inode. If a close is attempted against an inode that is holding
** locks, the close is deferred until all locks clear by adding the
** file descriptor to be closed to the pending list.
*/
struct openCnt {
struct openKey key; /* The lookup key */
int nRef; /* Number of pointers to this structure */
int nLock; /* Number of outstanding locks */
int nPending; /* Number of pending close() operations */
int *aPending; /* Malloced space holding fd's awaiting a close() */
};
/*
** These hash table maps inodes and process IDs 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 };
| os.c | 87 |
STATIC VOID | releaseLockInfo(struct lockInfo *pLock)
static void releaseLockInfo(struct lockInfo *pLock){
pLock->nRef--;
if( pLock->nRef==0 ){
sqliteHashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
sqliteFree(pLock);
}
}
| os.c | 262 |
STATIC VOID | releaseOpenCnt(struct openCnt *pOpen)
static void releaseOpenCnt(struct openCnt *pOpen){
pOpen->nRef--;
if( pOpen->nRef==0 ){
sqliteHashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
sqliteFree(pOpen->aPending);
sqliteFree(pOpen);
}
}
| os.c | 273 |
INT | findLockInfo( int fd, struct lockInfo **ppLock, struct openCnt **ppOpen )
int findLockInfo(
int fd, /* The file descriptor used in the key */
struct lockInfo **ppLock, /* Return the lockInfo structure here */
struct openCnt **ppOpen /* Return the openCnt structure here */
){
int rc;
struct lockKey key1;
struct openKey key2;
struct stat statbuf;
struct lockInfo *pLock;
struct openCnt *pOpen;
rc = fstat(fd, &statbuf);
if( rc!=0 ) return 1;
memset(&key1, 0, sizeof(key1));
key1.dev = statbuf.st_dev;
key1.ino = statbuf.st_ino;
key1.pid = getpid();
memset(&key2, 0, sizeof(key2));
key2.dev = statbuf.st_dev;
key2.ino = statbuf.st_ino;
pLock = (struct lockInfo*)sqliteHashFind(&lockHash, &key1, sizeof(key1));
if( pLock==0 ){
struct lockInfo *pOld;
pLock = sqliteMallocRaw( sizeof(*pLock) );
if( pLock==0 ) return 1;
pLock->key = key1;
pLock->nRef = 1;
pLock->cnt = 0;
pOld = sqliteHashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
if( pOld!=0 ){
assert( pOld==pLock );
sqliteFree(pLock);
return 1;
}
}else{
pLock->nRef++;
}
*ppLock = pLock;
pOpen = (struct openCnt*)sqliteHashFind(&openHash, &key2, sizeof(key2));
if( pOpen==0 ){
struct openCnt *pOld;
pOpen = sqliteMallocRaw( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
return 1;
}
pOpen->key = key2;
pOpen->nRef = 1;
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
pOld = sqliteHashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
if( pOld!=0 ){
assert( pOld==pOpen );
sqliteFree(pOpen);
releaseLockInfo(pLock);
return 1;
}
}else{
pOpen->nRef++;
}
*ppOpen = pOpen;
return 0;
}
#endif /** POSIX advisory lock work-around **/
/*
** 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 sqlite_io_error_pending = 0;
#define SimulateIOError(A) \
if( sqlite_io_error_pending ) \
if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; }
| os.c | 285 |
} STATIC VOID | local_ioerr()
static void local_ioerr(){
sqlite_io_error_pending = 0; /* Really just a place to set a breakpoint */
}
#else
#define SimulateIOError(A)
#endif
/*
** When testing, keep a count of the number of open files.
*/
#ifdef SQLITE_TEST
int sqlite_open_file_count = 0;
| os.c | 369 |
INT | sqliteOsDelete(const char *zFilename)
int sqliteOsDelete(const char *zFilename){
#if OS_UNIX
unlink(zFilename);
#endif
#if OS_WIN
DeleteFile(zFilename);
#endif
#if OS_MAC
unlink(zFilename);
#endif
return SQLITE_OK;
}
| os.c | 387 |
INT | sqliteOsFileExists(const char *zFilename)
int sqliteOsFileExists(const char *zFilename){
#if OS_UNIX
return access(zFilename, 0)==0;
#endif
#if OS_WIN
return GetFileAttributes(zFilename) != 0xffffffff;
#endif
#if OS_MAC
return access(zFilename, 0)==0;
#endif
}
| os.c | 403 |
INT | sqliteOsFileRename(const char *zOldName, const char *zNewName)
int sqliteOsFileRename(const char *zOldName, const char *zNewName){
#if OS_UNIX
if( link(zOldName, zNewName) ){
return SQLITE_ERROR;
}
unlink(zOldName);
return SQLITE_OK;
#endif
#if OS_WIN
if( !MoveFile(zOldName, zNewName) ){
return SQLITE_ERROR;
}
return SQLITE_OK;
#endif
#if OS_MAC
/**** FIX ME ***/
return SQLITE_ERROR;
#endif
}
| os.c | 420 |
INT | sqliteOsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly )
int sqliteOsOpenReadWrite(
const char *zFilename,
OsFile *id,
int *pReadonly
){
#if OS_UNIX
int rc;
id->dirfd = -1;
id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
if( id->fd<0 ){
#ifdef EISDIR
if( errno==EISDIR ){
return SQLITE_CANTOPEN;
}
#endif
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->fd<0 ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
sqliteOsEnterMutex();
rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
sqliteOsLeaveMutex();
if( rc ){
close(id->fd);
return SQLITE_NOMEM;
}
id->locked = 0;
TRACE3("OPEN %-3d %s\n", id->fd, zFilename);
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_WIN
HANDLE h = CreateFile(zFilename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
h = CreateFile(zFilename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
id->h = h;
id->locked = 0;
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_MAC
FSSpec fsSpec;
# ifdef _LARGE_FILE
HFSUniStr255 dfName;
FSRef fsRef;
if( __path2fss(zFilename, &fsSpec) != noErr ){
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
return SQLITE_CANTOPEN;
}
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
return SQLITE_CANTOPEN;
FSGetDataForkName(&dfName);
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
fsRdWrShPerm, &(id->refNum)) != noErr ){
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
fsRdWrPerm, &(id->refNum)) != noErr ){
if (FSOpenFork(&fsRef, dfName.length, dfName.unicode,
fsRdPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
else
*pReadonly = 1;
} else
*pReadonly = 0;
} else
*pReadonly = 0;
# else
__path2fss(zFilename, &fsSpec);
if( !sqliteOsFileExists(zFilename) ){
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
return SQLITE_CANTOPEN;
}
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
else
*pReadonly = 1;
} else
*pReadonly = 0;
} else
*pReadonly = 0;
# endif
if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
id->refNumRF = -1;
}
id->locked = 0;
id->delOnClose = 0;
OpenCounter(+1);
return SQLITE_OK;
#endif
}
| os.c | 444 |
INT | sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag)
int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
#if OS_UNIX
int rc;
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
id->dirfd = -1;
id->fd = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
if( id->fd<0 ){
return SQLITE_CANTOPEN;
}
sqliteOsEnterMutex();
rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
sqliteOsLeaveMutex();
if( rc ){
close(id->fd);
unlink(zFilename);
return SQLITE_NOMEM;
}
id->locked = 0;
if( delFlag ){
unlink(zFilename);
}
TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename);
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_WIN
HANDLE h;
int fileflags;
if( delFlag ){
fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_DELETE_ON_CLOSE;
}else{
fileflags = FILE_FLAG_RANDOM_ACCESS;
}
h = CreateFile(zFilename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
fileflags,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
id->h = h;
id->locked = 0;
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_MAC
FSSpec fsSpec;
# ifdef _LARGE_FILE
HFSUniStr255 dfName;
FSRef fsRef;
__path2fss(zFilename, &fsSpec);
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
return SQLITE_CANTOPEN;
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
return SQLITE_CANTOPEN;
FSGetDataForkName(&dfName);
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
fsRdWrPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
# else
__path2fss(zFilename, &fsSpec);
if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
return SQLITE_CANTOPEN;
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
# endif
id->refNumRF = -1;
id->locked = 0;
id->delOnClose = delFlag;
if (delFlag)
id->pathToDel = sqliteOsFullPathname(zFilename);
OpenCounter(+1);
return SQLITE_OK;
#endif
}
| os.c | 575 |
INT | sqliteOsOpenReadOnly(const char *zFilename, OsFile *id)
int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
#if OS_UNIX
int rc;
id->dirfd = -1;
id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->fd<0 ){
return SQLITE_CANTOPEN;
}
sqliteOsEnterMutex();
rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
sqliteOsLeaveMutex();
if( rc ){
close(id->fd);
return SQLITE_NOMEM;
}
id->locked = 0;
TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename);
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_WIN
HANDLE h = CreateFile(zFilename,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
id->h = h;
id->locked = 0;
OpenCounter(+1);
return SQLITE_OK;
#endif
#if OS_MAC
FSSpec fsSpec;
# ifdef _LARGE_FILE
HFSUniStr255 dfName;
FSRef fsRef;
if( __path2fss(zFilename, &fsSpec) != noErr )
return SQLITE_CANTOPEN;
if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
return SQLITE_CANTOPEN;
FSGetDataForkName(&dfName);
if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
fsRdPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
# else
__path2fss(zFilename, &fsSpec);
if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
return SQLITE_CANTOPEN;
# endif
if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
id->refNumRF = -1;
}
id->locked = 0;
id->delOnClose = 0;
OpenCounter(+1);
return SQLITE_OK;
#endif
}
| os.c | 673 |
INT | sqliteOsOpenDirectory( const char *zDirname, OsFile *id )
int sqliteOsOpenDirectory(
const char *zDirname,
OsFile *id
){
#if OS_UNIX
if( id->fd<0 ){
/* Do not open the directory if the corresponding file is not already
** open. */
return SQLITE_CANTOPEN;
}
assert( id->dirfd<0 );
id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644);
if( id->dirfd<0 ){
return SQLITE_CANTOPEN;
}
TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname);
#endif
return SQLITE_OK;
}
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
*/
const char *sqlite_temp_directory = 0;
| os.c | 745 |
INT | sqliteOsTempFileName(char *zBuf)
int sqliteOsTempFileName(char *zBuf){
#if OS_UNIX
static const char *azDirs[] = {
0,
"/var/tmp",
"/usr/tmp",
"/tmp",
".",
};
static unsigned char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
int i, j;
struct stat buf;
const char *zDir = ".";
azDirs[0] = sqlite_temp_directory;
for(i=0; i0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
zDir = zTempPath;
}else{
zDir = sqlite_temp_directory;
}
for(;;){
sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir);
j = strlen(zBuf);
sqliteRandomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
if( !sqliteOsFileExists(zBuf) ) break;
}
#endif
#if OS_MAC
static char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
int i, j;
char *zDir;
char zTempPath[SQLITE_TEMPNAME_SIZE];
char zdirName[32];
CInfoPBRec infoRec;
Str31 dirName;
memset(&infoRec, 0, sizeof(infoRec));
memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
if( sqlite_temp_directory!=0 ){
zDir = sqlite_temp_directory;
}else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
&(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
infoRec.dirInfo.ioNamePtr = dirName;
do{
infoRec.dirInfo.ioFDirIndex = -1;
infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
if( PBGetCatInfoSync(&infoRec) == noErr ){
CopyPascalStringToC(dirName, zdirName);
i = strlen(zdirName);
memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
strcpy(zTempPath, zdirName);
zTempPath[i] = ':';
}else{
*zTempPath = 0;
break;
}
} while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
zDir = zTempPath;
}
if( zDir[0]==0 ){
getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
zDir = zTempPath;
}
for(;;){
sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir);
j = strlen(zBuf);
sqliteRandomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
if( !sqliteOsFileExists(zBuf) ) break;
}
#endif
return SQLITE_OK;
}
| os.c | 788 |
INT | sqliteOsClose(OsFile *id)
int sqliteOsClose(OsFile *id){
#if OS_UNIX
sqliteOsUnlock(id);
if( id->dirfd>=0 ) close(id->dirfd);
id->dirfd = -1;
sqliteOsEnterMutex();
if( id->pOpen->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pOpen->aPending. It will be automatically closed when
** the last lock is cleared.
*/
int *aNew;
struct openCnt *pOpen = id->pOpen;
pOpen->nPending++;
aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
pOpen->aPending = aNew;
pOpen->aPending[pOpen->nPending-1] = id->fd;
}
}else{
/* There are no outstanding locks so we can close the file immediately */
close(id->fd);
}
releaseLockInfo(id->pLock);
releaseOpenCnt(id->pOpen);
sqliteOsLeaveMutex();
TRACE2("CLOSE %-3d\n", id->fd);
OpenCounter(-1);
return SQLITE_OK;
#endif
#if OS_WIN
CloseHandle(id->h);
OpenCounter(-1);
return SQLITE_OK;
#endif
#if OS_MAC
if( id->refNumRF!=-1 )
FSClose(id->refNumRF);
# ifdef _LARGE_FILE
FSCloseFork(id->refNum);
# else
FSClose(id->refNum);
# endif
if( id->delOnClose ){
unlink(id->pathToDel);
sqliteFree(id->pathToDel);
}
OpenCounter(-1);
return SQLITE_OK;
#endif
}
| os.c | 906 |
INT | sqliteOsRead(OsFile *id, void *pBuf, int amt)
int sqliteOsRead(OsFile *id, void *pBuf, int amt){
#if OS_UNIX
int got;
SimulateIOError(SQLITE_IOERR);
TIMER_START;
got = read(id->fd, pBuf, amt);
TIMER_END;
TRACE4("READ %-3d %7d %d\n", id->fd, last_page, elapse);
SEEK(0);
/* if( got<0 ) got = 0; */
if( got==amt ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
#endif
#if OS_WIN
DWORD got;
SimulateIOError(SQLITE_IOERR);
TRACE2("READ %d\n", last_page);
if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
got = 0;
}
if( got==(DWORD)amt ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
#endif
#if OS_MAC
int got;
SimulateIOError(SQLITE_IOERR);
TRACE2("READ %d\n", last_page);
# ifdef _LARGE_FILE
FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);
# else
got = amt;
FSRead(id->refNum, &got, pBuf);
# endif
if( got==amt ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
#endif
}
| os.c | 964 |
INT | sqliteOsWrite(OsFile *id, const void *pBuf, int amt)
int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
#if OS_UNIX
int wrote = 0;
SimulateIOError(SQLITE_IOERR);
TIMER_START;
while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
TIMER_END;
TRACE4("WRITE %-3d %7d %d\n", id->fd, last_page, elapse);
SEEK(0);
if( amt>0 ){
return SQLITE_FULL;
}
return SQLITE_OK;
#endif
#if OS_WIN
int rc;
DWORD wrote;
SimulateIOError(SQLITE_IOERR);
TRACE2("WRITE %d\n", last_page);
while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
if( !rc || amt>(int)wrote ){
return SQLITE_FULL;
}
return SQLITE_OK;
#endif
#if OS_MAC
OSErr oserr;
int wrote = 0;
SimulateIOError(SQLITE_IOERR);
TRACE2("WRITE %d\n", last_page);
while( amt>0 ){
# ifdef _LARGE_FILE
oserr = FSWriteFork(id->refNum, fsAtMark, 0,
(ByteCount)amt, pBuf, (ByteCount*)&wrote);
# else
wrote = amt;
oserr = FSWrite(id->refNum, &wrote, pBuf);
# endif
if( wrote == 0 || oserr != noErr)
break;
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
if( oserr != noErr || amt>wrote ){
return SQLITE_FULL;
}
return SQLITE_OK;
#endif
}
| os.c | 1016 |
INT | sqliteOsSeek(OsFile *id, off_t offset)
int sqliteOsSeek(OsFile *id, off_t offset){
SEEK(offset/1024 + 1);
#if OS_UNIX
lseek(id->fd, offset, SEEK_SET);
return SQLITE_OK;
#endif
#if OS_WIN
{
LONG upperBits = offset>>32;
LONG lowerBits = offset & 0xffffffff;
DWORD rc;
rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
/* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */
}
return SQLITE_OK;
#endif
#if OS_MAC
{
off_t curSize;
if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){
return SQLITE_IOERR;
}
if( offset >= curSize ){
if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){
return SQLITE_IOERR;
}
}
# ifdef _LARGE_FILE
if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){
# else
if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){
# endif
return SQLITE_IOERR;
}else{
return SQLITE_OK;
}
}
#endif
}
#ifdef SQLITE_NOSYNC
# define fsync(X) 0
#endif
/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
** entry for the journal might not exist after we reboot. The next
** SQLite to access the file will not know that the journal exists (because
** the directory entry for the journal was never created) and the transaction
** will not roll back - possibly leading to database corruption.
*/
int sqliteOsSync(OsFile *id){
#if OS_UNIX
SimulateIOError(SQLITE_IOERR);
TRACE2("SYNC %-3d\n", id->fd);
if( fsync(id->fd) ){
return SQLITE_IOERR;
}else{
if( id->dirfd>=0 ){
TRACE2("DIRSYNC %-3d\n", id->dirfd);
fsync(id->dirfd);
close(id->dirfd); /* Only need to sync once, so close the directory */
id->dirfd = -1; /* when we are done. */
}
return SQLITE_OK;
}
#endif
#if OS_WIN
if( FlushFileBuffers(id->h) ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
#endif
#if OS_MAC
# ifdef _LARGE_FILE
if( FSFlushFork(id->refNum) != noErr ){
# else
ParamBlockRec params;
memset(¶ms, 0, sizeof(ParamBlockRec));
params.ioParam.ioRefNum = id->refNum;
if( PBFlushFileSync(¶ms) != noErr ){
# endif
return SQLITE_IOERR;
}else{
return SQLITE_OK;
}
#endif
}
/*
** Truncate an open file to a specified size
*/
int sqliteOsTruncate(OsFile *id, off_t nByte){
SimulateIOError(SQLITE_IOERR);
#if OS_UNIX
return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
{
LONG upperBits = nByte>>32;
SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
SetEndOfFile(id->h);
}
return SQLITE_OK;
#endif
#if OS_MAC
# ifdef _LARGE_FILE
if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){
# else
if( SetEOF(id->refNum, nByte) != noErr ){
# endif
return SQLITE_IOERR;
}else{
return SQLITE_OK;
}
#endif
}
/*
** Determine the current size of a file in bytes
*/
int sqliteOsFileSize(OsFile *id, off_t *pSize){
#if OS_UNIX
struct stat buf;
SimulateIOError(SQLITE_IOERR);
if( fstat(id->fd, &buf)!=0 ){
return SQLITE_IOERR;
}
*pSize = buf.st_size;
return SQLITE_OK;
#endif
#if OS_WIN
DWORD upperBits, lowerBits;
SimulateIOError(SQLITE_IOERR);
lowerBits = GetFileSize(id->h, &upperBits);
*pSize = (((off_t)upperBits)<<32) + lowerBits;
return SQLITE_OK;
#endif
#if OS_MAC
# ifdef _LARGE_FILE
if( FSGetForkSize(id->refNum, pSize) != noErr){
# else
if( GetEOF(id->refNum, pSize) != noErr ){
# endif
return SQLITE_IOERR;
}else{
return SQLITE_OK;
}
#endif
}
#if OS_WIN
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
int isNT(void){
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
if( osType==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return osType==2;
}
#endif
/*
** Windows file locking notes: [similar issues apply to MacOS]
**
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
** those functions are not available. So we use only LockFile() and
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
** (This is a design error on the part of Windows, but there is nothing
** we can do about that.) So the region used for locking is at the
** end of the file where it is unlikely to ever interfere with an
** actual read attempt.
**
** A database read lock is obtained by locking a single randomly-chosen
** byte out of a specific range of bytes. The lock byte is obtained at
** random so two separate readers can probably access the file at the
** same time, unless they are unlucky and choose the same lock byte.
** A database write lock is obtained by locking all bytes in the range.
** There can only be one writer.
**
** A lock is obtained on the first byte of the lock range before acquiring
** either a read lock or a write lock. This prevents two processes from
** attempting to get a lock at a same time. The semantics of
** sqliteOsReadLock() require that if there is already a write lock, that
** lock is converted into a read lock atomically. The lock on the first
** byte allows us to drop the old write lock and get the read lock without
** another process jumping into the middle and messing us up. The same
** argument applies to sqliteOsWriteLock().
**
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
** which means we can use reader/writer locks. When reader writer locks
** are used, the lock is placed on the same range of bytes that is used
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
** will support two or more Win95 readers or two or more WinNT readers.
** But a single Win95 reader will lock out all WinNT readers and a single
** WinNT reader will lock out all other Win95 readers.
**
** Note: On MacOS we use the resource fork for locking.
**
** The following #defines specify the range of bytes used for locking.
** N_LOCKBYTE is the number of bytes available for doing the locking.
** The first byte used to hold the lock while the lock is changing does
** not count toward this number. FIRST_LOCKBYTE is the address of
** the first byte in the range of bytes used for locking.
*/
#define N_LOCKBYTE 10239
#if OS_MAC
# define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE)
#else
# define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
#endif
/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
** If the file was read locked, then this acquires a new read lock.
**
** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqliteOsReadLock(OsFile *id){
#if OS_UNIX
int rc;
sqliteOsEnterMutex();
if( id->pLock->cnt>0 ){
if( !id->locked ){
id->pLock->cnt++;
id->locked = 1;
id->pOpen->nLock++;
}
rc = SQLITE_OK;
}else if( id->locked || id->pLock->cnt==0 ){
struct flock lock;
int s;
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
s = fcntl(id->fd, F_SETLK, &lock);
if( s!=0 ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
rc = SQLITE_OK;
if( !id->locked ){
id->pOpen->nLock++;
id->locked = 1;
}
id->pLock->cnt = 1;
}
}else{
rc = SQLITE_BUSY;
}
sqliteOsLeaveMutex();
return rc;
#endif
#if OS_WIN
int rc;
if( id->locked>0 ){
rc = SQLITE_OK;
}else{
int lk;
int res;
int cnt = 100;
sqliteRandomness(sizeof(lk), &lk);
lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
Sleep(1);
}
if( res ){
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
if( isNT() ){
OVERLAPPED ovlp;
ovlp.Offset = FIRST_LOCKBYTE+1;
ovlp.OffsetHigh = 0;
ovlp.hEvent = 0;
res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,
0, N_LOCKBYTE, 0, &ovlp);
}else{
res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
}
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
}
if( res ){
id->locked = lk;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
#if OS_MAC
int rc;
if( id->locked>0 || id->refNumRF == -1 ){
rc = SQLITE_OK;
}else{
int lk;
OSErr res;
int cnt = 5;
ParamBlockRec params;
sqliteRandomness(sizeof(lk), &lk);
lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
memset(¶ms, 0, sizeof(params));
params.ioParam.ioRefNum = id->refNumRF;
params.ioParam.ioPosMode = fsFromStart;
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
params.ioParam.ioReqCount = 1;
while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
UInt32 finalTicks;
Delay(1, &finalTicks); /* 1/60 sec */
}
if( res == noErr ){
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
params.ioParam.ioReqCount = N_LOCKBYTE;
PBUnlockRangeSync(¶ms);
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;
params.ioParam.ioReqCount = 1;
res = PBLockRangeSync(¶ms);
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
params.ioParam.ioReqCount = 1;
PBUnlockRangeSync(¶ms);
}
if( res == noErr ){
id->locked = lk;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
}
/*
** Change the lock status to be an exclusive or write lock. Return
** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqliteOsWriteLock(OsFile *id){
#if OS_UNIX
int rc;
sqliteOsEnterMutex();
if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){
struct flock lock;
int s;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
s = fcntl(id->fd, F_SETLK, &lock);
if( s!=0 ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
rc = SQLITE_OK;
if( !id->locked ){
id->pOpen->nLock++;
id->locked = 1;
}
id->pLock->cnt = -1;
}
}else{
rc = SQLITE_BUSY;
}
sqliteOsLeaveMutex();
return rc;
#endif
#if OS_WIN
int rc;
if( id->locked<0 ){
rc = SQLITE_OK;
}else{
int res;
int cnt = 100;
while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
Sleep(1);
}
if( res ){
if( id->locked>0 ){
if( isNT() ){
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
}else{
res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
}
}
if( res ){
res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
}else{
res = 0;
}
UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
}
if( res ){
id->locked = -1;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
#if OS_MAC
int rc;
if( id->locked<0 || id->refNumRF == -1 ){
rc = SQLITE_OK;
}else{
OSErr res;
int cnt = 5;
ParamBlockRec params;
memset(¶ms, 0, sizeof(params));
params.ioParam.ioRefNum = id->refNumRF;
params.ioParam.ioPosMode = fsFromStart;
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
params.ioParam.ioReqCount = 1;
while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){
UInt32 finalTicks;
Delay(1, &finalTicks); /* 1/60 sec */
}
if( res == noErr ){
params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;
params.ioParam.ioReqCount = 1;
if( id->locked==0
|| PBUnlockRangeSync(¶ms)==noErr ){
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
params.ioParam.ioReqCount = N_LOCKBYTE;
res = PBLockRangeSync(¶ms);
}else{
res = afpRangeNotLocked;
}
params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
params.ioParam.ioReqCount = 1;
PBUnlockRangeSync(¶ms);
}
if( res == noErr ){
id->locked = -1;
rc = SQLITE_OK;
}else{
rc = SQLITE_BUSY;
}
}
return rc;
#endif
}
/*
** Unlock the given file descriptor. If the file descriptor was
** not previously locked, then this routine is a no-op. If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an SQLITE_NOLFS is returned.
*/
int sqliteOsUnlock(OsFile *id){
#if OS_UNIX
int rc;
if( !id->locked ) return SQLITE_OK;
sqliteOsEnterMutex();
assert( id->pLock->cnt!=0 );
if( id->pLock->cnt>1 ){
id->pLock->cnt--;
rc = SQLITE_OK;
}else{
struct flock lock;
int s;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
s = fcntl(id->fd, F_SETLK, &lock);
if( s!=0 ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
rc = SQLITE_OK;
id->pLock->cnt = 0;
}
}
if( rc==SQLITE_OK ){
/* Decrement the count of locks against this same file. When the
** count reaches zero, close any other file descriptors whose close
** was deferred because of outstanding locks.
*/
struct openCnt *pOpen = id->pOpen;
pOpen->nLock--;
assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 && pOpen->nPending>0 ){
int i;
for(i=0; inPending; i++){
close(pOpen->aPending[i]);
}
sqliteFree(pOpen->aPending);
pOpen->nPending = 0;
pOpen->aPending = 0;
}
}
sqliteOsLeaveMutex();
id->locked = 0;
return rc;
#endif
#if OS_WIN
int rc;
if( id->locked==0 ){
rc = SQLITE_OK;
}else if( isNT() || id->locked<0 ){
UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
rc = SQLITE_OK;
id->locked = 0;
}else{
UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
rc = SQLITE_OK;
id->locked = 0;
}
return rc;
#endif
#if OS_MAC
int rc;
ParamBlockRec params;
memset(¶ms, 0, sizeof(params));
params.ioParam.ioRefNum = id->refNumRF;
params.ioParam.ioPosMode = fsFromStart;
if( id->locked==0 || id->refNumRF == -1 ){
rc = SQLITE_OK;
}else if( id->locked<0 ){
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
params.ioParam.ioReqCount = N_LOCKBYTE;
PBUnlockRangeSync(¶ms);
rc = SQLITE_OK;
id->locked = 0;
}else{
params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;
params.ioParam.ioReqCount = 1;
PBUnlockRangeSync(¶ms);
rc = SQLITE_OK;
id->locked = 0;
}
return rc;
#endif
}
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
** supply a sufficiently large buffer.
*/
int sqliteOsRandomSeed(char *zBuf){
/* We have to initialize zBuf to prevent valgrind from reporting
** errors. The reports issued by valgrind are incorrect - we would
** prefer that the randomness be increased by making use of the
** uninitialized space in zBuf - but valgrind errors tend to worry
** some users. Rather than argue, it seems easier just to initialize
** the whole array and silence valgrind, even if that means less randomness
** in the random seed.
**
** When testing, initializing zBuf[] to zero is all we do. That means
** that we always use the same random number sequence.* This makes the
** tests repeatable.
*/
memset(zBuf, 0, 256);
#if OS_UNIX && !defined(SQLITE_TEST)
{
int pid;
time((time_t*)zBuf);
pid = getpid();
memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
}
#endif
#if OS_WIN && !defined(SQLITE_TEST)
GetSystemTime((LPSYSTEMTIME)zBuf);
#endif
#if OS_MAC
{
int pid;
Microseconds((UnsignedWide*)zBuf);
pid = getpid();
memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));
}
#endif
return SQLITE_OK;
}
/*
** Sleep for a little while. Return the amount of time slept.
*/
int sqliteOsSleep(int ms){
#if OS_UNIX
#if defined(HAVE_USLEEP) && HAVE_USLEEP
usleep(ms*1000);
return ms;
#else
sleep((ms+999)/1000);
return 1000*((ms+999)/1000);
#endif
#endif
#if OS_WIN
Sleep(ms);
return ms;
#endif
#if OS_MAC
UInt32 finalTicks;
UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */
Delay(ticks, &finalTicks);
return (int)((ticks*50)/3);
#endif
}
/*
** Static variables used for thread synchronization
*/
static int inMutex = 0;
#ifdef SQLITE_UNIX_THREADS
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
#ifdef SQLITE_W32_THREADS
static CRITICAL_SECTION cs;
#endif
#ifdef SQLITE_MACOS_MULTITASKING
static MPCriticalRegionID criticalRegion;
#endif
/*
** The following pair of routine implement mutual exclusion for
** multi-threaded processes. Only a single thread is allowed to
** executed code that is surrounded by EnterMutex() and LeaveMutex().
**
** SQLite uses only a single Mutex. There is not much critical
** code and what little there is executes quickly and without blocking.
*/
void sqliteOsEnterMutex(){
#ifdef SQLITE_UNIX_THREADS
pthread_mutex_lock(&mutex);
#endif
#ifdef SQLITE_W32_THREADS
static int isInit = 0;
while( !isInit ){
static long lock = 0;
if( InterlockedIncrement(&lock)==1 ){
InitializeCriticalSection(&cs);
isInit = 1;
}else{
Sleep(1);
}
}
EnterCriticalSection(&cs);
#endif
#ifdef SQLITE_MACOS_MULTITASKING
static volatile int notInit = 1;
if( notInit ){
if( notInit == 2 ) /* as close as you can get to thread safe init */
MPYield();
else{
notInit = 2;
MPCreateCriticalRegion(&criticalRegion);
notInit = 0;
}
}
MPEnterCriticalRegion(criticalRegion, kDurationForever);
#endif
assert( !inMutex );
inMutex = 1;
}
void sqliteOsLeaveMutex(){
assert( inMutex );
inMutex = 0;
#ifdef SQLITE_UNIX_THREADS
pthread_mutex_unlock(&mutex);
#endif
#ifdef SQLITE_W32_THREADS
LeaveCriticalSection(&cs);
#endif
#ifdef SQLITE_MACOS_MULTITASKING
MPExitCriticalRegion(criticalRegion);
#endif
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqliteOsFullPathname(const char *zRelative){
#if OS_UNIX
char *zFull = 0;
if( zRelative[0]=='/' ){
sqliteSetString(&zFull, zRelative, (char*)0);
}else{
char zBuf[5000];
sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
(char*)0);
}
return zFull;
#endif
#if OS_WIN
char *zNotUsed;
char *zFull;
int nByte;
nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
return zFull;
#endif
#if OS_MAC
char *zFull = 0;
if( zRelative[0]==':' ){
char zBuf[_MAX_PATH+1];
sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]),
(char*)0);
}else{
if( strchr(zRelative, ':') ){
sqliteSetString(&zFull, zRelative, (char*)0);
}else{
char zBuf[_MAX_PATH+1];
sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0);
}
}
return zFull;
#endif
}
/*
** The following variable, if set to a non-zero value, becomes the result
** returned from sqliteOsCurrentTime(). This is used for testing.
*/
#ifdef SQLITE_TEST
int sqlite_current_time = 0;
#endif
/*
** Find the current time (in Universal Coordinated Time). Write the
** current time and date as a Julian Day number into *prNow and
** return 0. Return 1 if the time and date cannot be found.
*/
int sqliteOsCurrentTime(double *prNow){
#if OS_UNIX
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
#endif
#if OS_WIN
FILETIME ft;
/* FILETIME structure is a 64-bit value representing the number of
100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
*/
double now;
GetSystemTimeAsFileTime( &ft );
now = ((double)ft.dwHighDateTime) * 4294967296.0;
*prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
#endif
#ifdef SQLITE_TEST
if( sqlite_current_time ){
*prNow = sqlite_current_time/86400.0 + 2440587.5;
}
#endif
return 0;
}
| os.c | 1076 |
pager.c |
Type | Function | Source | Line |
STATIC VOID | pager_refinfo(PgHdr *p)
static void pager_refinfo(PgHdr *p){
static int cnt = 0;
if( !pager_refinfo_enable ) return;
printf(
"REFCNT: %4d addr=0x%08x nRef=%d\n",
p->pgno, (int)PGHDR_TO_DATA(p), p->nRef
);
cnt++; /* Something to set a breakpoint on */
}
| pager.c | 292 |
STATIC INT | read32bits(int format, OsFile *fd, u32 *pRes)
static int read32bits(int format, OsFile *fd, u32 *pRes){
u32 res;
int rc;
rc = sqliteOsRead(fd, &res, sizeof(res));
if( rc==SQLITE_OK && format>JOURNAL_FORMAT_1 ){
unsigned char ac[4];
memcpy(ac, &res, 4);
res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
}
*pRes = res;
return rc;
}
| pager.c | 306 |
STATIC INT | write32bits(OsFile *fd, u32 val)
static int write32bits(OsFile *fd, u32 val){
unsigned char ac[4];
if( journal_format<=1 ){
return sqliteOsWrite(fd, &val, 4);
}
ac[0] = (val>>24) & 0xff;
ac[1] = (val>>16) & 0xff;
ac[2] = (val>>8) & 0xff;
ac[3] = val & 0xff;
return sqliteOsWrite(fd, ac, 4);
}
| pager.c | 328 |
STATIC VOID | store32bits(u32 val, PgHdr *p, int offset)
static void store32bits(u32 val, PgHdr *p, int offset){
unsigned char *ac;
ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];
if( journal_format<=1 ){
memcpy(ac, &val, 4);
}else{
ac[0] = (val>>24) & 0xff;
ac[1] = (val>>16) & 0xff;
ac[2] = (val>>8) & 0xff;
ac[3] = val & 0xff;
}
}
| pager.c | 349 |
STATIC INT | pager_errcode(Pager *pPager)
static int pager_errcode(Pager *pPager){
int rc = SQLITE_OK;
if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR;
if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM;
if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
return rc;
}
| pager.c | 370 |
STATIC VOID | page_add_to_ckpt_list(PgHdr *pPg)
static void page_add_to_ckpt_list(PgHdr *pPg){
Pager *pPager = pPg->pPager;
if( pPg->inCkpt ) return;
assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 );
pPg->pPrevCkpt = 0;
if( pPager->pCkpt ){
pPager->pCkpt->pPrevCkpt = pPg;
}
pPg->pNextCkpt = pPager->pCkpt;
pPager->pCkpt = pPg;
pPg->inCkpt = 1;
}
| pager.c | 384 |
STATIC VOID | page_remove_from_ckpt_list(PgHdr *pPg)
static void page_remove_from_ckpt_list(PgHdr *pPg){
if( !pPg->inCkpt ) return;
if( pPg->pPrevCkpt ){
assert( pPg->pPrevCkpt->pNextCkpt==pPg );
pPg->pPrevCkpt->pNextCkpt = pPg->pNextCkpt;
}else{
assert( pPg->pPager->pCkpt==pPg );
pPg->pPager->pCkpt = pPg->pNextCkpt;
}
if( pPg->pNextCkpt ){
assert( pPg->pNextCkpt->pPrevCkpt==pPg );
pPg->pNextCkpt->pPrevCkpt = pPg->pPrevCkpt;
}
pPg->pNextCkpt = 0;
pPg->pPrevCkpt = 0;
pPg->inCkpt = 0;
}
| pager.c | 405 |
STATIC PGHDR | pager_lookup(Pager *pPager, Pgno pgno)
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *p = pPager->aHash[pager_hash(pgno)];
while( p && p->pgno!=pgno ){
p = p->pNextHash;
}
return p;
}
| pager.c | 423 |
STATIC VOID | pager_reset(Pager *pPager)
static void pager_reset(Pager *pPager){
PgHdr *pPg, *pNext;
for(pPg=pPager->pAll; pPg; pPg=pNext){
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
pPager->pFirst = 0;
pPager->pFirstSynced = 0;
pPager->pLast = 0;
pPager->pAll = 0;
memset(pPager->aHash, 0, sizeof(pPager->aHash));
pPager->nPage = 0;
if( pPager->state>=SQLITE_WRITELOCK ){
sqlitepager_rollback(pPager);
}
sqliteOsUnlock(&pPager->fd);
pPager->state = SQLITE_UNLOCK;
pPager->dbSize = -1;
pPager->nRef = 0;
assert( pPager->journalOpen==0 );
}
| pager.c | 435 |
STATIC INT | pager_unwritelock(Pager *pPager)
static int pager_unwritelock(Pager *pPager){
int rc;
PgHdr *pPg;
if( pPager->stateckptOpen ){
sqliteOsClose(&pPager->cpfd);
pPager->ckptOpen = 0;
}
if( pPager->journalOpen ){
sqliteOsClose(&pPager->jfd);
pPager->journalOpen = 0;
sqliteOsDelete(pPager->zJournal);
sqliteFree( pPager->aInJournal );
pPager->aInJournal = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->inJournal = 0;
pPg->dirty = 0;
pPg->needSync = 0;
}
}else{
assert( pPager->dirtyFile==0 || pPager->useJournal==0 );
}
rc = sqliteOsReadLock(&pPager->fd);
if( rc==SQLITE_OK ){
pPager->state = SQLITE_READLOCK;
}else{
/* This can only happen if a process does a BEGIN, then forks and the
** child process does the COMMIT. Because of the semantics of unix
** file locking, the unlock will fail.
*/
pPager->state = SQLITE_UNLOCK;
}
return rc;
}
| pager.c | 463 |
STATIC U32 | pager_cksum(Pager *pPager, Pgno pgno, const char *aData)
static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){
u32 cksum = pPager->cksumInit + pgno;
return cksum;
}
| pager.c | 509 |
STATIC INT | pager_playback_one_page(Pager *pPager, OsFile *jfd, int format)
static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){
int rc;
PgHdr *pPg; /* An existing page in the cache */
PageRecord pgRec;
u32 cksum;
rc = read32bits(format, jfd, &pgRec.pgno);
if( rc!=SQLITE_OK ) return rc;
rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData));
if( rc!=SQLITE_OK ) return rc;
/* Sanity checking on the page. This is more important that I originally
** thought. If a power failure occurs while the journal is being written,
** it could cause invalid data to be written into the journal. We need to
** detect this invalid data (with high probability) and ignore it.
*/
if( pgRec.pgno==0 ){
return SQLITE_DONE;
}
if( pgRec.pgno>(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
if( format>=JOURNAL_FORMAT_3 ){
rc = read32bits(format, jfd, &cksum);
if( rc ) return rc;
if( pager_cksum(pPager, pgRec.pgno, pgRec.aData)!=cksum ){
return SQLITE_DONE;
}
}
/* Playback the page. Update the in-memory copy of the page
** at the same time, if there is one.
*/
pPg = pager_lookup(pPager, pgRec.pgno);
TRACE2("PLAYBACK %d\n", pgRec.pgno);
sqliteOsSeek(&pPager->fd, (pgRec.pgno-1)*(off_t)SQLITE_PAGE_SIZE);
rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
if( pPg ){
/* No page should ever be rolled back that is in use, except for page
** 1 which is held in use in order to keep the lock on the database
** active.
*/
assert( pPg->nRef==0 || pPg->pgno==1 );
memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
pPg->dirty = 0;
pPg->needSync = 0;
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
}
return rc;
}
| pager.c | 521 |
STATIC INT | pager_playback(Pager *pPager, int useJournalSize)
static int pager_playback(Pager *pPager, int useJournalSize){
off_t szJ; /* Size of the journal file in bytes */
int nRec; /* Number of Records in the journal */
int i; /* Loop counter */
Pgno mxPg = 0; /* Size of the original file in pages */
int format; /* Format of the journal file. */
unsigned char aMagic[sizeof(aJournalMagic1)];
int rc;
/* Figure out how many records are in the journal. Abort early if
** the journal is empty.
*/
assert( pPager->journalOpen );
sqliteOsSeek(&pPager->jfd, 0);
rc = sqliteOsFileSize(&pPager->jfd, &szJ);
if( rc!=SQLITE_OK ){
goto end_playback;
}
/* If the journal file is too small to contain a complete header,
** it must mean that the process that created the journal was just
** beginning to write the journal file when it died. In that case,
** the database file should have still been completely unchanged.
** Nothing needs to be rolled back. We can safely ignore this journal.
*/
if( szJ < sizeof(aMagic)+sizeof(Pgno) ){
goto end_playback;
}
/* Read the beginning of the journal and truncate the
** database file back to its original size.
*/
rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic));
if( rc!=SQLITE_OK ){
rc = SQLITE_PROTOCOL;
goto end_playback;
}
if( memcmp(aMagic, aJournalMagic3, sizeof(aMagic))==0 ){
format = JOURNAL_FORMAT_3;
}else if( memcmp(aMagic, aJournalMagic2, sizeof(aMagic))==0 ){
format = JOURNAL_FORMAT_2;
}else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){
format = JOURNAL_FORMAT_1;
}else{
rc = SQLITE_PROTOCOL;
goto end_playback;
}
if( format>=JOURNAL_FORMAT_3 ){
if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){
/* Ignore the journal if it is too small to contain a complete
** header. We already did this test once above, but at the prior
** test, we did not know the journal format and so we had to assume
** the smallest possible header. Now we know the header is bigger
** than the minimum so we test again.
*/
goto end_playback;
}
rc = read32bits(format, &pPager->jfd, (u32*)&nRec);
if( rc ) goto end_playback;
rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
if( rc ) goto end_playback;
if( nRec==0xffffffff || useJournalSize ){
nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
}
}else{
nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2);
assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ );
}
rc = read32bits(format, &pPager->jfd, &mxPg);
if( rc!=SQLITE_OK ){
goto end_playback;
}
assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg);
if( rc!=SQLITE_OK ){
goto end_playback;
}
pPager->dbSize = mxPg;
/* Copy original pages out of the journal and back into the database file.
*/
for(i=0; ijfd, format);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
break;
}
}
/* Pages that have been written to the journal but never synced
** where not restored by the loop above. We have to restore those
** pages by reading them back from the original database.
*/
if( rc==SQLITE_OK ){
PgHdr *pPg;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
char zBuf[SQLITE_PAGE_SIZE];
if( !pPg->dirty ) continue;
if( (int)pPg->pgno <= pPager->origDbSize ){
sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
TRACE2("REFETCH %d\n", pPg->pgno);
CODEC(pPager, zBuf, pPg->pgno, 2);
if( rc ) break;
}else{
memset(zBuf, 0, SQLITE_PAGE_SIZE);
}
if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
}
pPg->needSync = 0;
pPg->dirty = 0;
}
}
end_playback:
if( rc!=SQLITE_OK ){
pager_unwritelock(pPager);
pPager->errMask |= PAGER_ERR_CORRUPT;
rc = SQLITE_CORRUPT;
}else{
rc = pager_unwritelock(pPager);
}
return rc;
}
| pager.c | 580 |
STATIC INT | pager_ckpt_playback(Pager *pPager)
static int pager_ckpt_playback(Pager *pPager){
off_t szJ; /* Size of the full journal */
int nRec; /* Number of Records */
int i; /* Loop counter */
int rc;
/* Truncate the database back to its original size.
*/
rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize);
pPager->dbSize = pPager->ckptSize;
/* Figure out how many records are in the checkpoint journal.
*/
assert( pPager->ckptInUse && pPager->journalOpen );
sqliteOsSeek(&pPager->cpfd, 0);
nRec = pPager->ckptNRec;
/* Copy original pages out of the checkpoint journal and back into the
** database file. Note that the checkpoint journal always uses format
** 2 instead of format 3 since it does not need to be concerned with
** power failures corrupting the journal and can thus omit the checksums.
*/
for(i=nRec-1; i>=0; i--){
rc = pager_playback_one_page(pPager, &pPager->cpfd, 2);
assert( rc!=SQLITE_DONE );
if( rc!=SQLITE_OK ) goto end_ckpt_playback;
}
/* Figure out how many pages need to be copied out of the transaction
** journal.
*/
rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize);
if( rc!=SQLITE_OK ){
goto end_ckpt_playback;
}
rc = sqliteOsFileSize(&pPager->jfd, &szJ);
if( rc!=SQLITE_OK ){
goto end_ckpt_playback;
}
nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format);
for(i=nRec-1; i>=0; i--){
rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format);
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_DONE );
goto end_ckpt_playback;
}
}
end_ckpt_playback:
if( rc!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_CORRUPT;
rc = SQLITE_CORRUPT;
}
return rc;
}
| pager.c | 761 |
VOID | sqlitepager_set_cachesize(Pager *pPager, int mxPage)
void sqlitepager_set_cachesize(Pager *pPager, int mxPage){
if( mxPage>=0 ){
pPager->noSync = pPager->tempFile;
if( pPager->noSync==0 ) pPager->needSync = 0;
}else{
pPager->noSync = 1;
mxPage = -mxPage;
}
if( mxPage>10 ){
pPager->mxPage = mxPage;
}
}
| pager.c | 831 |
VOID | sqlitepager_set_safety_level(Pager *pPager, int level)
void sqlitepager_set_safety_level(Pager *pPager, int level){
pPager->noSync = level==1 || pPager->tempFile;
pPager->fullSync = level==3 && !pPager->tempFile;
if( pPager->noSync==0 ) pPager->needSync = 0;
}
| pager.c | 854 |
STATIC INT | sqlitepager_opentemp(char *zFile, OsFile *fd)
static int sqlitepager_opentemp(char *zFile, OsFile *fd){
int cnt = 8;
int rc;
do{
cnt--;
sqliteOsTempFileName(zFile);
rc = sqliteOsOpenExclusive(zFile, fd, 1);
}while( cnt>0 && rc!=SQLITE_OK );
return rc;
}
| pager.c | 886 |
INT | sqlitepager_open( Pager **ppPager, const char *zFilename, int mxPage, int nExtra, int useJournal )
int sqlitepager_open(
Pager **ppPager, /* Return the Pager structure here */
const char *zFilename, /* Name of the database file to open */
int mxPage, /* Max number of in-memory cache pages */
int nExtra, /* Extra bytes append to each in-memory page */
int useJournal /* TRUE to use a rollback journal on this file */
){
Pager *pPager;
char *zFullPathname;
int nameLen;
OsFile fd;
int rc, i;
int tempFile;
int readOnly = 0;
char zTemp[SQLITE_TEMPNAME_SIZE];
*ppPager = 0;
if( sqlite_malloc_failed ){
return SQLITE_NOMEM;
}
if( zFilename && zFilename[0] ){
zFullPathname = sqliteOsFullPathname(zFilename);
rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly);
tempFile = 0;
}else{
rc = sqlitepager_opentemp(zTemp, &fd);
zFilename = zTemp;
zFullPathname = sqliteOsFullPathname(zFilename);
tempFile = 1;
}
if( sqlite_malloc_failed ){
return SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ){
sqliteFree(zFullPathname);
return SQLITE_CANTOPEN;
}
nameLen = strlen(zFullPathname);
pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
if( pPager==0 ){
sqliteOsClose(&fd);
sqliteFree(zFullPathname);
return SQLITE_NOMEM;
}
SET_PAGER(pPager);
pPager->zFilename = (char*)&pPager[1];
pPager->zDirectory = &pPager->zFilename[nameLen+1];
pPager->zJournal = &pPager->zDirectory[nameLen+1];
strcpy(pPager->zFilename, zFullPathname);
strcpy(pPager->zDirectory, zFullPathname);
for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){}
if( i>0 ) pPager->zDirectory[i-1] = 0;
strcpy(pPager->zJournal, zFullPathname);
sqliteFree(zFullPathname);
strcpy(&pPager->zJournal[nameLen], "-journal");
pPager->fd = fd;
pPager->journalOpen = 0;
pPager->useJournal = useJournal;
pPager->ckptOpen = 0;
pPager->ckptInUse = 0;
pPager->nRef = 0;
pPager->dbSize = -1;
pPager->ckptSize = 0;
pPager->ckptJSize = 0;
pPager->nPage = 0;
pPager->mxPage = mxPage>5 ? mxPage : 10;
pPager->state = SQLITE_UNLOCK;
pPager->errMask = 0;
pPager->tempFile = tempFile;
pPager->readOnly = readOnly;
pPager->needSync = 0;
pPager->noSync = pPager->tempFile || !useJournal;
pPager->pFirst = 0;
pPager->pFirstSynced = 0;
pPager->pLast = 0;
pPager->nExtra = nExtra;
memset(pPager->aHash, 0, sizeof(pPager->aHash));
*ppPager = pPager;
return SQLITE_OK;
}
| pager.c | 906 |
VOID SQLITEPAGER_SET_DESTRUCTOR(PAGER *PPAGER, VOID (*XDESC | (void*))
void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
pPager->xDestructor = xDesc;
}
| pager.c | 997 |
INT | sqlitepager_pagecount(Pager *pPager)
int sqlitepager_pagecount(Pager *pPager){
off_t n;
assert( pPager!=0 );
if( pPager->dbSize>=0 ){
return pPager->dbSize;
}
if( sqliteOsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_DISK;
return 0;
}
n /= SQLITE_PAGE_SIZE;
if( pPager->state!=SQLITE_UNLOCK ){
pPager->dbSize = n;
}
return n;
}
/*
** Forward declaration
*/
static int syncJournal(Pager*);
| pager.c | 1009 |
INT | sqlitepager_truncate(Pager *pPager, Pgno nPage)
int sqlitepager_truncate(Pager *pPager, Pgno nPage){
int rc;
if( pPager->dbSize<0 ){
sqlitepager_pagecount(pPager);
}
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
return rc;
}
if( nPage>=(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
syncJournal(pPager);
rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
if( rc==SQLITE_OK ){
pPager->dbSize = nPage;
}
return rc;
}
| pager.c | 1035 |
INT | sqlitepager_close(Pager *pPager)
int sqlitepager_close(Pager *pPager){
PgHdr *pPg, *pNext;
switch( pPager->state ){
case SQLITE_WRITELOCK: {
sqlitepager_rollback(pPager);
sqliteOsUnlock(&pPager->fd);
assert( pPager->journalOpen==0 );
break;
}
case SQLITE_READLOCK: {
sqliteOsUnlock(&pPager->fd);
break;
}
default: {
/* Do nothing */
break;
}
}
for(pPg=pPager->pAll; pPg; pPg=pNext){
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
sqliteOsClose(&pPager->fd);
assert( pPager->journalOpen==0 );
/* Temp files are automatically deleted by the OS
** if( pPager->tempFile ){
** sqliteOsDelete(pPager->zFilename);
** }
*/
CLR_PAGER(pPager);
if( pPager->zFilename!=(char*)&pPager[1] ){
assert( 0 ); /* Cannot happen */
sqliteFree(pPager->zFilename);
sqliteFree(pPager->zJournal);
sqliteFree(pPager->zDirectory);
}
sqliteFree(pPager);
return SQLITE_OK;
}
| pager.c | 1058 |
PGNO | sqlitepager_pagenumber(void *pData)
Pgno sqlitepager_pagenumber(void *pData){
PgHdr *p = DATA_TO_PGHDR(pData);
return p->pgno;
}
| pager.c | 1107 |
STATIC VOID | _page_ref(PgHdr *pPg)
static void _page_ref(PgHdr *pPg){
if( pPg->nRef==0 ){
/* The page is currently on the freelist. Remove it. */
if( pPg==pPg->pPager->pFirstSynced ){
PgHdr *p = pPg->pNextFree;
while( p && p->needSync ){ p = p->pNextFree; }
pPg->pPager->pFirstSynced = p;
}
if( pPg->pPrevFree ){
pPg->pPrevFree->pNextFree = pPg->pNextFree;
}else{
pPg->pPager->pFirst = pPg->pNextFree;
}
if( pPg->pNextFree ){
pPg->pNextFree->pPrevFree = pPg->pPrevFree;
}else{
pPg->pPager->pLast = pPg->pPrevFree;
}
pPg->pPager->nRef++;
}
pPg->nRef++;
REFINFO(pPg);
}
| pager.c | 1121 |
INT | sqlitepager_ref(void *pData)
int sqlitepager_ref(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
page_ref(pPg);
return SQLITE_OK;
}
| pager.c | 1145 |
STATIC INT | syncJournal(Pager *pPager)
static int syncJournal(Pager *pPager){
PgHdr *pPg;
int rc = SQLITE_OK;
/* Sync the journal before modifying the main database
** (assuming there is a journal and it needs to be synced.)
*/
if( pPager->needSync ){
if( !pPager->tempFile ){
assert( pPager->journalOpen );
/* assert( !pPager->noSync ); // noSync might be set if synchronous
** was turned off after the transaction was started. Ticket #615 */
#ifndef NDEBUG
{
/* Make sure the pPager->nRec counter we are keeping agrees
** with the nRec computed from the size of the journal file.
*/
off_t hdrSz, pgSz, jSz;
hdrSz = JOURNAL_HDR_SZ(journal_format);
pgSz = JOURNAL_PG_SZ(journal_format);
rc = sqliteOsFileSize(&pPager->jfd, &jSz);
if( rc!=0 ) return rc;
assert( pPager->nRec*pgSz+hdrSz==jSz );
}
#endif
if( journal_format>=3 ){
/* Write the nRec value into the journal file header */
off_t szJ;
if( pPager->fullSync ){
TRACE1("SYNC\n");
rc = sqliteOsSync(&pPager->jfd);
if( rc!=0 ) return rc;
}
sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1));
rc = write32bits(&pPager->jfd, pPager->nRec);
if( rc ) return rc;
szJ = JOURNAL_HDR_SZ(journal_format) +
pPager->nRec*JOURNAL_PG_SZ(journal_format);
sqliteOsSeek(&pPager->jfd, szJ);
}
TRACE1("SYNC\n");
rc = sqliteOsSync(&pPager->jfd);
if( rc!=0 ) return rc;
pPager->journalStarted = 1;
}
pPager->needSync = 0;
/* Erase the needSync flag from every page.
*/
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->needSync = 0;
}
pPager->pFirstSynced = pPager->pFirst;
}
#ifndef NDEBUG
/* If the Pager.needSync flag is clear then the PgHdr.needSync
** flag must also be clear for all pages. Verify that this
** invariant is true.
*/
else{
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
assert( pPg->needSync==0 );
}
assert( pPager->pFirstSynced==pPager->pFirst );
}
#endif
return rc;
}
| pager.c | 1155 |
STATIC INT | pager_write_pagelist(PgHdr *pList)
static int pager_write_pagelist(PgHdr *pList){
Pager *pPager;
int rc;
if( pList==0 ) return SQLITE_OK;
pPager = pList->pPager;
while( pList ){
assert( pList->dirty );
sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE);
CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
TRACE2("STORE %d\n", pList->pgno);
rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE);
CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
if( rc ) return rc;
pList->dirty = 0;
pList = pList->pDirty;
}
return SQLITE_OK;
}
| pager.c | 1246 |
STATIC PGHDR | pager_get_all_dirty_pages(Pager *pPager)
static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
PgHdr *p, *pList;
pList = 0;
for(p=pPager->pAll; p; p=p->pNextAll){
if( p->dirty ){
p->pDirty = pList;
pList = p;
}
}
return pList;
}
| pager.c | 1271 |
INT | sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage)
int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
PgHdr *pPg;
int rc;
/* Make sure we have not hit any critical errors.
*/
assert( pPager!=0 );
assert( pgno!=0 );
*ppPage = 0;
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return pager_errcode(pPager);
}
/* If this is the first page accessed, then get a read lock
** on the database file.
*/
if( pPager->nRef==0 ){
rc = sqliteOsReadLock(&pPager->fd);
if( rc!=SQLITE_OK ){
return rc;
}
pPager->state = SQLITE_READLOCK;
/* If a journal file exists, try to play it back.
*/
if( pPager->useJournal && sqliteOsFileExists(pPager->zJournal) ){
int rc;
/* Get a write lock on the database
*/
rc = sqliteOsWriteLock(&pPager->fd);
if( rc!=SQLITE_OK ){
if( sqliteOsUnlock(&pPager->fd)!=SQLITE_OK ){
/* This should never happen! */
rc = SQLITE_INTERNAL;
}
return rc;
}
pPager->state = SQLITE_WRITELOCK;
/* Open the journal for reading only. Return SQLITE_BUSY if
** we are unable to open the journal file.
**
** The journal file does not need to be locked itself. The
** journal file is never open unless the main database file holds
** a write lock, so there is never any chance of two or more
** processes opening the journal at the same time.
*/
rc = sqliteOsOpenReadOnly(pPager->zJournal, &pPager->jfd);
if( rc!=SQLITE_OK ){
rc = sqliteOsUnlock(&pPager->fd);
assert( rc==SQLITE_OK );
return SQLITE_BUSY;
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
/* Playback and delete the journal. Drop the database write
** lock and reacquire the read lock.
*/
rc = pager_playback(pPager, 0);
if( rc!=SQLITE_OK ){
return rc;
}
}
pPg = 0;
}else{
/* Search for page in cache */
pPg = pager_lookup(pPager, pgno);
}
if( pPg==0 ){
/* The requested page is not in the page cache. */
int h;
pPager->nMiss++;
if( pPager->nPagemxPage || pPager->pFirst==0 ){
/* Create a new page */
pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE
+ sizeof(u32) + pPager->nExtra );
if( pPg==0 ){
pager_unwritelock(pPager);
pPager->errMask |= PAGER_ERR_MEM;
return SQLITE_NOMEM;
}
memset(pPg, 0, sizeof(*pPg));
pPg->pPager = pPager;
pPg->pNextAll = pPager->pAll;
if( pPager->pAll ){
pPager->pAll->pPrevAll = pPg;
}
pPg->pPrevAll = 0;
pPager->pAll = pPg;
pPager->nPage++;
}else{
/* Find a page to recycle. Try to locate a page that does not
** require us to do an fsync() on the journal.
*/
pPg = pPager->pFirstSynced;
/* If we could not find a page that does not require an fsync()
** on the journal file then fsync the journal file. This is a
** very slow operation, so we work hard to avoid it. But sometimes
** it can't be helped.
*/
if( pPg==0 ){
int rc = syncJournal(pPager);
if( rc!=0 ){
sqlitepager_rollback(pPager);
return SQLITE_IOERR;
}
pPg = pPager->pFirst;
}
assert( pPg->nRef==0 );
/* Write the page to the database file if it is dirty.
*/
if( pPg->dirty ){
assert( pPg->needSync==0 );
pPg->pDirty = 0;
rc = pager_write_pagelist( pPg );
if( rc!=SQLITE_OK ){
sqlitepager_rollback(pPager);
return SQLITE_IOERR;
}
}
assert( pPg->dirty==0 );
/* If the page we are recycling is marked as alwaysRollback, then
** set the global alwaysRollback flag, thus disabling the
** sqlite_dont_rollback() optimization for the rest of this transaction.
** It is necessary to do this because the page marked alwaysRollback
** might be reloaded at a later time but at that point we won't remember
** that is was marked alwaysRollback. This means that all pages must
** be marked as alwaysRollback from here on out.
*/
if( pPg->alwaysRollback ){
pPager->alwaysRollback = 1;
}
/* Unlink the old page from the free list and the hash table
*/
if( pPg==pPager->pFirstSynced ){
PgHdr *p = pPg->pNextFree;
while( p && p->needSync ){ p = p->pNextFree; }
pPager->pFirstSynced = p;
}
if( pPg->pPrevFree ){
pPg->pPrevFree->pNextFree = pPg->pNextFree;
}else{
assert( pPager->pFirst==pPg );
pPager->pFirst = pPg->pNextFree;
}
if( pPg->pNextFree ){
pPg->pNextFree->pPrevFree = pPg->pPrevFree;
}else{
assert( pPager->pLast==pPg );
pPager->pLast = pPg->pPrevFree;
}
pPg->pNextFree = pPg->pPrevFree = 0;
if( pPg->pNextHash ){
pPg->pNextHash->pPrevHash = pPg->pPrevHash;
}
if( pPg->pPrevHash ){
pPg->pPrevHash->pNextHash = pPg->pNextHash;
}else{
h = pager_hash(pPg->pgno);
assert( pPager->aHash[h]==pPg );
pPager->aHash[h] = pPg->pNextHash;
}
pPg->pNextHash = pPg->pPrevHash = 0;
pPager->nOvfl++;
}
pPg->pgno = pgno;
if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
sqliteCheckMemory(pPager->aInJournal, pgno/8);
assert( pPager->journalOpen );
pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0;
pPg->needSync = 0;
}else{
pPg->inJournal = 0;
pPg->needSync = 0;
}
if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize
&& (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){
page_add_to_ckpt_list(pPg);
}else{
page_remove_from_ckpt_list(pPg);
}
pPg->dirty = 0;
pPg->nRef = 1;
REFINFO(pPg);
pPager->nRef++;
h = pager_hash(pgno);
pPg->pNextHash = pPager->aHash[h];
pPager->aHash[h] = pPg;
if( pPg->pNextHash ){
assert( pPg->pNextHash->pPrevHash==0 );
pPg->pNextHash->pPrevHash = pPg;
}
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
}
if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
if( pPager->errMask!=0 ){
sqlitepager_unref(PGHDR_TO_DATA(pPg));
rc = pager_errcode(pPager);
return rc;
}
if( pPager->dbSize<(int)pgno ){
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
}else{
int rc;
sqliteOsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE);
rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
TRACE2("FETCH %d\n", pPg->pgno);
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
if( rc!=SQLITE_OK ){
off_t fileSize;
if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
|| fileSize>=pgno*SQLITE_PAGE_SIZE ){
sqlitepager_unref(PGHDR_TO_DATA(pPg));
return rc;
}else{
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
}
}
}
}else{
/* The requested page is in the page cache. */
pPager->nHit++;
page_ref(pPg);
}
*ppPage = PGHDR_TO_DATA(pPg);
return SQLITE_OK;
}
| pager.c | 1288 |
VOID | sqlitepager_lookup(Pager *pPager, Pgno pgno)
void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
PgHdr *pPg;
assert( pPager!=0 );
assert( pgno!=0 );
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return 0;
}
/* if( pPager->nRef==0 ){
** return 0;
** }
*/
pPg = pager_lookup(pPager, pgno);
if( pPg==0 ) return 0;
page_ref(pPg);
return PGHDR_TO_DATA(pPg);
}
| pager.c | 1546 |
INT | sqlitepager_unref(void *pData)
int sqlitepager_unref(void *pData){
PgHdr *pPg;
/* Decrement the reference count for this page
*/
pPg = DATA_TO_PGHDR(pData);
assert( pPg->nRef>0 );
pPg->nRef--;
REFINFO(pPg);
/* When the number of references to a page reach 0, call the
** destructor and add the page to the freelist.
*/
if( pPg->nRef==0 ){
Pager *pPager;
pPager = pPg->pPager;
pPg->pNextFree = 0;
pPg->pPrevFree = pPager->pLast;
pPager->pLast = pPg;
if( pPg->pPrevFree ){
pPg->pPrevFree->pNextFree = pPg;
}else{
pPager->pFirst = pPg;
}
if( pPg->needSync==0 && pPager->pFirstSynced==0 ){
pPager->pFirstSynced = pPg;
}
if( pPager->xDestructor ){
pPager->xDestructor(pData);
}
/* When all pages reach the freelist, drop the read lock from
** the database file.
*/
pPager->nRef--;
assert( pPager->nRef>=0 );
if( pPager->nRef==0 ){
pager_reset(pPager);
}
}
return SQLITE_OK;
}
| pager.c | 1575 |
STATIC INT | pager_open_journal(Pager *pPager)
static int pager_open_journal(Pager *pPager){
int rc;
assert( pPager->state==SQLITE_WRITELOCK );
assert( pPager->journalOpen==0 );
assert( pPager->useJournal );
sqlitepager_pagecount(pPager);
pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
if( pPager->aInJournal==0 ){
sqliteOsReadLock(&pPager->fd);
pPager->state = SQLITE_READLOCK;
return SQLITE_NOMEM;
}
rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
if( rc!=SQLITE_OK ){
sqliteFree(pPager->aInJournal);
pPager->aInJournal = 0;
sqliteOsReadLock(&pPager->fd);
pPager->state = SQLITE_READLOCK;
return SQLITE_CANTOPEN;
}
sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd);
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
pPager->alwaysRollback = 0;
pPager->nRec = 0;
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
return rc;
}
pPager->origDbSize = pPager->dbSize;
if( journal_format==JOURNAL_FORMAT_3 ){
rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3));
if( rc==SQLITE_OK ){
rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0);
}
if( rc==SQLITE_OK ){
sqliteRandomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
rc = write32bits(&pPager->jfd, pPager->cksumInit);
}
}else if( journal_format==JOURNAL_FORMAT_2 ){
rc = sqliteOsWrite(&pPager->jfd, aJournalMagic2, sizeof(aJournalMagic2));
}else{
assert( journal_format==JOURNAL_FORMAT_1 );
rc = sqliteOsWrite(&pPager->jfd, aJournalMagic1, sizeof(aJournalMagic1));
}
if( rc==SQLITE_OK ){
rc = write32bits(&pPager->jfd, pPager->dbSize);
}
if( pPager->ckptAutoopen && rc==SQLITE_OK ){
rc = sqlitepager_ckpt_begin(pPager);
}
if( rc!=SQLITE_OK ){
rc = pager_unwritelock(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
}
return rc;
}
| pager.c | 1626 |
INT | sqlitepager_begin(void *pData)
int sqlitepager_begin(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
assert( pPg->nRef>0 );
assert( pPager->state!=SQLITE_UNLOCK );
if( pPager->state==SQLITE_READLOCK ){
assert( pPager->aInJournal==0 );
rc = sqliteOsWriteLock(&pPager->fd);
if( rc!=SQLITE_OK ){
return rc;
}
pPager->state = SQLITE_WRITELOCK;
pPager->dirtyFile = 0;
TRACE1("TRANSACTION\n");
if( pPager->useJournal && !pPager->tempFile ){
rc = pager_open_journal(pPager);
}
}
return rc;
}
| pager.c | 1694 |
INT | sqlitepager_write(void *pData)
int sqlitepager_write(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
/* Check for errors
*/
if( pPager->errMask ){
return pager_errcode(pPager);
}
if( pPager->readOnly ){
return SQLITE_PERM;
}
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
pPg->dirty = 1;
if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){
pPager->dirtyFile = 1;
return SQLITE_OK;
}
/* If we get this far, it means that the page needs to be
** written to the transaction journal or the ckeckpoint journal
** or both.
**
** First check to see that the transaction journal exists and
** create it if it does not.
*/
assert( pPager->state!=SQLITE_UNLOCK );
rc = sqlitepager_begin(pData);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pPager->state==SQLITE_WRITELOCK );
if( !pPager->journalOpen && pPager->useJournal ){
rc = pager_open_journal(pPager);
if( rc!=SQLITE_OK ) return rc;
}
assert( pPager->journalOpen || !pPager->useJournal );
pPager->dirtyFile = 1;
/* The transaction journal now exists and we have a write lock on the
** main database file. Write the current page to the transaction
** journal if it is not there already.
*/
if( !pPg->inJournal && pPager->useJournal ){
if( (int)pPg->pgno <= pPager->origDbSize ){
int szPg;
u32 saved;
if( journal_format>=JOURNAL_FORMAT_3 ){
u32 cksum = pager_cksum(pPager, pPg->pgno, pData);
saved = *(u32*)PGHDR_TO_EXTRA(pPg);
store32bits(cksum, pPg, SQLITE_PAGE_SIZE);
szPg = SQLITE_PAGE_SIZE+8;
}else{
szPg = SQLITE_PAGE_SIZE+4;
}
store32bits(pPg->pgno, pPg, -4);
CODEC(pPager, pData, pPg->pgno, 7);
rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync);
CODEC(pPager, pData, pPg->pgno, 0);
if( journal_format>=JOURNAL_FORMAT_3 ){
*(u32*)PGHDR_TO_EXTRA(pPg) = saved;
}
if( rc!=SQLITE_OK ){
sqlitepager_rollback(pPager);
pPager->errMask |= PAGER_ERR_FULL;
return rc;
}
pPager->nRec++;
assert( pPager->aInJournal!=0 );
pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
pPg->needSync = !pPager->noSync;
pPg->inJournal = 1;
if( pPager->ckptInUse ){
pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
page_add_to_ckpt_list(pPg);
}
}else{
pPg->needSync = !pPager->journalStarted && !pPager->noSync;
TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync);
}
if( pPg->needSync ){
pPager->needSync = 1;
}
}
/* If the checkpoint journal is open and the page is not in it,
** then write the current page to the checkpoint journal. Note that
** the checkpoint journal always uses the simplier format 2 that lacks
** checksums. The header is also omitted from the checkpoint journal.
*/
if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
store32bits(pPg->pgno, pPg, -4);
CODEC(pPager, pData, pPg->pgno, 7);
rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4);
TRACE2("CKPT-JOURNAL %d\n", pPg->pgno);
CODEC(pPager, pData, pPg->pgno, 0);
if( rc!=SQLITE_OK ){
sqlitepager_rollback(pPager);
pPager->errMask |= PAGER_ERR_FULL;
return rc;
}
pPager->ckptNRec++;
assert( pPager->aInCkpt!=0 );
pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
page_add_to_ckpt_list(pPg);
}
/* Update the database size and return.
*/
if( pPager->dbSize<(int)pPg->pgno ){
pPager->dbSize = pPg->pgno;
}
return rc;
}
| pager.c | 1736 |
INT | sqlitepager_iswriteable(void *pData)
int sqlitepager_iswriteable(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
return pPg->dirty;
}
| pager.c | 1874 |
INT | sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData)
int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
void *pPage;
int rc;
rc = sqlitepager_get(pPager, pgno, &pPage);
if( rc==SQLITE_OK ){
rc = sqlitepager_write(pPage);
if( rc==SQLITE_OK ){
memcpy(pPage, pData, SQLITE_PAGE_SIZE);
}
sqlitepager_unref(pPage);
}
return rc;
}
| pager.c | 1884 |
VOID | sqlitepager_dont_write(Pager *pPager, Pgno pgno)
void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
PgHdr *pPg;
pPg = pager_lookup(pPager, pgno);
pPg->alwaysRollback = 1;
if( pPg && pPg->dirty ){
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){
/* If this pages is the last page in the file and the file has grown
** during the current transaction, then do NOT mark the page as clean.
** When the database file grows, we must make sure that the last page
** gets written at least once so that the disk file will be the correct
** size. If you do not write this page and the size of the file
** on the disk ends up being too small, that can lead to database
** corruption during the next transaction.
*/
}else{
TRACE2("DONT_WRITE %d\n", pgno);
pPg->dirty = 0;
}
}
}
| pager.c | 1903 |
VOID | sqlitepager_dont_rollback(void *pData)
void sqlitepager_dont_rollback(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
Pager *pPager = pPg->pPager;
if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return;
if( pPg->alwaysRollback || pPager->alwaysRollback ) return;
if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
assert( pPager->aInJournal!=0 );
pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
pPg->inJournal = 1;
if( pPager->ckptInUse ){
pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
page_add_to_ckpt_list(pPg);
}
TRACE2("DONT_ROLLBACK %d\n", pPg->pgno);
}
if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
assert( pPager->aInCkpt!=0 );
pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
page_add_to_ckpt_list(pPg);
}
}
| pager.c | 1949 |
INT | sqlitepager_commit(Pager *pPager)
int sqlitepager_commit(Pager *pPager){
int rc;
PgHdr *pPg;
if( pPager->errMask==PAGER_ERR_FULL ){
rc = sqlitepager_rollback(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
return rc;
}
if( pPager->errMask!=0 ){
rc = pager_errcode(pPager);
return rc;
}
if( pPager->state!=SQLITE_WRITELOCK ){
return SQLITE_ERROR;
}
TRACE1("COMMIT\n");
if( pPager->dirtyFile==0 ){
/* Exit early (without doing the time-consuming sqliteOsSync() calls)
** if there have been no changes to the database file. */
assert( pPager->needSync==0 );
rc = pager_unwritelock(pPager);
pPager->dbSize = -1;
return rc;
}
assert( pPager->journalOpen );
rc = syncJournal(pPager);
if( rc!=SQLITE_OK ){
goto commit_abort;
}
pPg = pager_get_all_dirty_pages(pPager);
if( pPg ){
rc = pager_write_pagelist(pPg);
if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){
goto commit_abort;
}
}
rc = pager_unwritelock(pPager);
pPager->dbSize = -1;
return rc;
/* Jump here if anything goes wrong during the commit process.
*/
commit_abort:
rc = sqlitepager_rollback(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
return rc;
}
| pager.c | 1979 |
INT | sqlitepager_rollback(Pager *pPager)
int sqlitepager_rollback(Pager *pPager){
int rc;
TRACE1("ROLLBACK\n");
if( !pPager->dirtyFile || !pPager->journalOpen ){
rc = pager_unwritelock(pPager);
pPager->dbSize = -1;
return rc;
}
if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
if( pPager->state>=SQLITE_WRITELOCK ){
pager_playback(pPager, 1);
}
return pager_errcode(pPager);
}
if( pPager->state!=SQLITE_WRITELOCK ){
return SQLITE_OK;
}
rc = pager_playback(pPager, 1);
if( rc!=SQLITE_OK ){
rc = SQLITE_CORRUPT;
pPager->errMask |= PAGER_ERR_CORRUPT;
}
pPager->dbSize = -1;
return rc;
}
| pager.c | 2039 |
INT | sqlitepager_isreadonly(Pager *pPager)
int sqlitepager_isreadonly(Pager *pPager){
return pPager->readOnly;
}
| pager.c | 2078 |
INT | sqlitepager_stats(Pager *pPager)
int *sqlitepager_stats(Pager *pPager){
static int a[9];
a[0] = pPager->nRef;
a[1] = pPager->nPage;
a[2] = pPager->mxPage;
a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errMask;
a[6] = pPager->nHit;
a[7] = pPager->nMiss;
a[8] = pPager->nOvfl;
return a;
}
| pager.c | 2086 |
INT | sqlitepager_ckpt_begin(Pager *pPager)
int sqlitepager_ckpt_begin(Pager *pPager){
int rc;
char zTemp[SQLITE_TEMPNAME_SIZE];
if( !pPager->journalOpen ){
pPager->ckptAutoopen = 1;
return SQLITE_OK;
}
assert( pPager->journalOpen );
assert( !pPager->ckptInUse );
pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 );
if( pPager->aInCkpt==0 ){
sqliteOsReadLock(&pPager->fd);
return SQLITE_NOMEM;
}
#ifndef NDEBUG
rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
if( rc ) goto ckpt_begin_failed;
assert( pPager->ckptJSize ==
pPager->nRec*JOURNAL_PG_SZ(journal_format)+JOURNAL_HDR_SZ(journal_format) );
#endif
pPager->ckptJSize = pPager->nRec*JOURNAL_PG_SZ(journal_format)
+ JOURNAL_HDR_SZ(journal_format);
pPager->ckptSize = pPager->dbSize;
if( !pPager->ckptOpen ){
rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
if( rc ) goto ckpt_begin_failed;
pPager->ckptOpen = 1;
pPager->ckptNRec = 0;
}
pPager->ckptInUse = 1;
return SQLITE_OK;
ckpt_begin_failed:
if( pPager->aInCkpt ){
sqliteFree(pPager->aInCkpt);
pPager->aInCkpt = 0;
}
return rc;
}
| pager.c | 2103 |
INT | sqlitepager_ckpt_commit(Pager *pPager)
int sqlitepager_ckpt_commit(Pager *pPager){
if( pPager->ckptInUse ){
PgHdr *pPg, *pNext;
sqliteOsSeek(&pPager->cpfd, 0);
/* sqliteOsTruncate(&pPager->cpfd, 0); */
pPager->ckptNRec = 0;
pPager->ckptInUse = 0;
sqliteFree( pPager->aInCkpt );
pPager->aInCkpt = 0;
for(pPg=pPager->pCkpt; pPg; pPg=pNext){
pNext = pPg->pNextCkpt;
assert( pPg->inCkpt );
pPg->inCkpt = 0;
pPg->pPrevCkpt = pPg->pNextCkpt = 0;
}
pPager->pCkpt = 0;
}
pPager->ckptAutoopen = 0;
return SQLITE_OK;
}
| pager.c | 2150 |
INT | sqlitepager_ckpt_rollback(Pager *pPager)
int sqlitepager_ckpt_rollback(Pager *pPager){
int rc;
if( pPager->ckptInUse ){
rc = pager_ckpt_playback(pPager);
sqlitepager_ckpt_commit(pPager);
}else{
rc = SQLITE_OK;
}
pPager->ckptAutoopen = 0;
return rc;
}
| pager.c | 2174 |
CONST CHAR | sqlitepager_filename(Pager *pPager)
const char *sqlitepager_filename(Pager *pPager){
return pPager->zFilename;
}
| pager.c | 2189 |
VOID SQLITEPAGER_SET_CODEC( PAGER *PPAGER, VOID (*XCODEC | (void*,void*,Pgno,int), void *pCodecArg )
void sqlitepager_set_codec(
Pager *pPager,
void (*xCodec)(void*,void*,Pgno,int),
void *pCodecArg
){
pPager->xCodec = xCodec;
pPager->pCodecArg = pCodecArg;
}
| pager.c | 2196 |
VOID | sqlitepager_refdump(Pager *pPager)
void sqlitepager_refdump(Pager *pPager){
PgHdr *pPg;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
if( pPg->nRef<=0 ) continue;
printf("PAGE %3d addr=0x%08x nRef=%d\n",
pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef);
}
}
| pager.c | 2209 |
parse.c |
Type | Function | Source | Line |
VOID | sqliteParserTrace(FILE *TraceFILE, char *zTracePrompt)
void sqliteParserTrace(FILE *TraceFILE, char *zTracePrompt){
yyTraceFILE = TraceFILE;
yyTracePrompt = zTracePrompt;
if( yyTraceFILE==0 ) yyTracePrompt = 0;
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
static const char *yyTokenName[] = {
"$", "END_OF_FILE", "ILLEGAL", "SPACE",
"UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN",
"AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN",
"TRANSACTION", "COMMIT", "END", "ROLLBACK",
"CREATE", "TABLE", "TEMP", "LP",
"RP", "AS", "COMMA", "ID",
"ABORT", "AFTER", "ASC", "ATTACH",
"BEFORE", "CASCADE", "CLUSTER", "CONFLICT",
"COPY", "DATABASE", "DEFERRED", "DELIMITERS",
"DESC", "DETACH", "EACH", "FAIL",
"FOR", "GLOB", "IGNORE", "IMMEDIATE",
"INITIALLY", "INSTEAD", "LIKE", "MATCH",
"KEY", "OF", "OFFSET", "PRAGMA",
"RAISE", "REPLACE", "RESTRICT", "ROW",
"STATEMENT", "TRIGGER", "VACUUM", "VIEW",
"OR", "AND", "NOT", "EQ",
"NE", "ISNULL", "NOTNULL", "IS",
"BETWEEN", "IN", "GT", "GE",
"LT", "LE", "BITAND", "BITOR",
"LSHIFT", "RSHIFT", "PLUS", "MINUS",
"STAR", "SLASH", "REM", "CONCAT",
"UMINUS", "UPLUS", "BITNOT", "STRING",
"JOIN_KW", "INTEGER", "CONSTRAINT", "DEFAULT",
"FLOAT", "NULL", "PRIMARY", "UNIQUE",
"CHECK", "REFERENCES", "COLLATE", "ON",
"DELETE", "UPDATE", "INSERT", "SET",
"DEFERRABLE", "FOREIGN", "DROP", "UNION",
"ALL", "INTERSECT", "EXCEPT", "SELECT",
"DISTINCT", "DOT", "FROM", "JOIN",
"USING", "ORDER", "BY", "GROUP",
"HAVING", "LIMIT", "WHERE", "INTO",
"VALUES", "VARIABLE", "CASE", "WHEN",
"THEN", "ELSE", "INDEX", "error",
"input", "cmdlist", "ecmd", "explain",
"cmdx", "cmd", "trans_opt", "onconf",
"nm", "create_table", "create_table_args", "temp",
"columnlist", "conslist_opt", "select", "column",
"columnid", "type", "carglist", "id",
"ids", "typename", "signed", "carg",
"ccons", "sortorder", "expr", "idxlist_opt",
"refargs", "defer_subclause", "refarg", "refact",
"init_deferred_pred_opt", "conslist", "tcons", "idxlist",
"defer_subclause_opt", "orconf", "resolvetype", "oneselect",
"multiselect_op", "distinct", "selcollist", "from",
"where_opt", "groupby_opt", "having_opt", "orderby_opt",
"limit_opt", "sclp", "as", "seltablist",
"stl_prefix", "joinop", "dbnm", "on_opt",
"using_opt", "seltablist_paren", "joinop2", "sortlist",
"sortitem", "collate", "exprlist", "setlist",
"insert_cmd", "inscollist_opt", "itemlist", "inscollist",
"likeop", "case_operand", "case_exprlist", "case_else",
"expritem", "uniqueflag", "idxitem", "plus_num",
"minus_num", "plus_opt", "number", "trigger_decl",
"trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
"when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
};
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *yyRuleName[] = {
/* 0 */ "input ::= cmdlist",
/* 1 */ "cmdlist ::= cmdlist ecmd",
/* 2 */ "cmdlist ::= ecmd",
/* 3 */ "ecmd ::= explain cmdx SEMI",
/* 4 */ "ecmd ::= SEMI",
/* 5 */ "cmdx ::= cmd",
/* 6 */ "explain ::= EXPLAIN",
/* 7 */ "explain ::=",
/* 8 */ "cmd ::= BEGIN trans_opt onconf",
/* 9 */ "trans_opt ::=",
/* 10 */ "trans_opt ::= TRANSACTION",
/* 11 */ "trans_opt ::= TRANSACTION nm",
/* 12 */ "cmd ::= COMMIT trans_opt",
/* 13 */ "cmd ::= END trans_opt",
/* 14 */ "cmd ::= ROLLBACK trans_opt",
/* 15 */ "cmd ::= create_table create_table_args",
/* 16 */ "create_table ::= CREATE temp TABLE nm",
/* 17 */ "temp ::= TEMP",
/* 18 */ "temp ::=",
/* 19 */ "create_table_args ::= LP columnlist conslist_opt RP",
/* 20 */ "create_table_args ::= AS select",
/* 21 */ "columnlist ::= columnlist COMMA column",
/* 22 */ "columnlist ::= column",
/* 23 */ "column ::= columnid type carglist",
/* 24 */ "columnid ::= nm",
/* 25 */ "id ::= ID",
/* 26 */ "ids ::= ID",
/* 27 */ "ids ::= STRING",
/* 28 */ "nm ::= ID",
/* 29 */ "nm ::= STRING",
/* 30 */ "nm ::= JOIN_KW",
/* 31 */ "type ::=",
/* 32 */ "type ::= typename",
/* 33 */ "type ::= typename LP signed RP",
/* 34 */ "type ::= typename LP signed COMMA signed RP",
/* 35 */ "typename ::= ids",
/* 36 */ "typename ::= typename ids",
/* 37 */ "signed ::= INTEGER",
/* 38 */ "signed ::= PLUS INTEGER",
/* 39 */ "signed ::= MINUS INTEGER",
/* 40 */ "carglist ::= carglist carg",
/* 41 */ "carglist ::=",
/* 42 */ "carg ::= CONSTRAINT nm ccons",
/* 43 */ "carg ::= ccons",
/* 44 */ "carg ::= DEFAULT STRING",
/* 45 */ "carg ::= DEFAULT ID",
/* 46 */ "carg ::= DEFAULT INTEGER",
/* 47 */ "carg ::= DEFAULT PLUS INTEGER",
/* 48 */ "carg ::= DEFAULT MINUS INTEGER",
/* 49 */ "carg ::= DEFAULT FLOAT",
/* 50 */ "carg ::= DEFAULT PLUS FLOAT",
/* 51 */ "carg ::= DEFAULT MINUS FLOAT",
/* 52 */ "carg ::= DEFAULT NULL",
/* 53 */ "ccons ::= NULL onconf",
/* 54 */ "ccons ::= NOT NULL onconf",
/* 55 */ "ccons ::= PRIMARY KEY sortorder onconf",
/* 56 */ "ccons ::= UNIQUE onconf",
/* 57 */ "ccons ::= CHECK LP expr RP onconf",
/* 58 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
/* 59 */ "ccons ::= defer_subclause",
/* 60 */ "ccons ::= COLLATE id",
/* 61 */ "refargs ::=",
/* 62 */ "refargs ::= refargs refarg",
/* 63 */ "refarg ::= MATCH nm",
/* 64 */ "refarg ::= ON DELETE refact",
/* 65 */ "refarg ::= ON UPDATE refact",
/* 66 */ "refarg ::= ON INSERT refact",
/* 67 */ "refact ::= SET NULL",
/* 68 */ "refact ::= SET DEFAULT",
/* 69 */ "refact ::= CASCADE",
/* 70 */ "refact ::= RESTRICT",
/* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
/* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
/* 73 */ "init_deferred_pred_opt ::=",
/* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
/* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
/* 76 */ "conslist_opt ::=",
/* 77 */ "conslist_opt ::= COMMA conslist",
/* 78 */ "conslist ::= conslist COMMA tcons",
/* 79 */ "conslist ::= conslist tcons",
/* 80 */ "conslist ::= tcons",
/* 81 */ "tcons ::= CONSTRAINT nm",
/* 82 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf",
/* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf",
/* 84 */ "tcons ::= CHECK expr onconf",
/* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
/* 86 */ "defer_subclause_opt ::=",
/* 87 */ "defer_subclause_opt ::= defer_subclause",
/* 88 */ "onconf ::=",
/* 89 */ "onconf ::= ON CONFLICT resolvetype",
/* 90 */ "orconf ::=",
/* 91 */ "orconf ::= OR resolvetype",
/* 92 */ "resolvetype ::= ROLLBACK",
/* 93 */ "resolvetype ::= ABORT",
/* 94 */ "resolvetype ::= FAIL",
/* 95 */ "resolvetype ::= IGNORE",
/* 96 */ "resolvetype ::= REPLACE",
/* 97 */ "cmd ::= DROP TABLE nm",
/* 98 */ "cmd ::= CREATE temp VIEW nm AS select",
/* 99 */ "cmd ::= DROP VIEW nm",
/* 100 */ "cmd ::= select",
/* 101 */ "select ::= oneselect",
/* 102 */ "select ::= select multiselect_op oneselect",
/* 103 */ "multiselect_op ::= UNION",
/* 104 */ "multiselect_op ::= UNION ALL",
/* 105 */ "multiselect_op ::= INTERSECT",
/* 106 */ "multiselect_op ::= EXCEPT",
/* 107 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
/* 108 */ "distinct ::= DISTINCT",
/* 109 */ "distinct ::= ALL",
/* 110 */ "distinct ::=",
/* 111 */ "sclp ::= selcollist COMMA",
/* 112 */ "sclp ::=",
/* 113 */ "selcollist ::= sclp expr as",
/* 114 */ "selcollist ::= sclp STAR",
/* 115 */ "selcollist ::= sclp nm DOT STAR",
/* 116 */ "as ::= AS nm",
/* 117 */ "as ::= ids",
/* 118 */ "as ::=",
/* 119 */ "from ::=",
/* 120 */ "from ::= FROM seltablist",
/* 121 */ "stl_prefix ::= seltablist joinop",
/* 122 */ "stl_prefix ::=",
/* 123 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
/* 124 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
/* 125 */ "seltablist_paren ::= select",
/* 126 */ "seltablist_paren ::= seltablist",
/* 127 */ "dbnm ::=",
/* 128 */ "dbnm ::= DOT nm",
/* 129 */ "joinop ::= COMMA",
/* 130 */ "joinop ::= JOIN",
/* 131 */ "joinop ::= JOIN_KW JOIN",
/* 132 */ "joinop ::= JOIN_KW nm JOIN",
/* 133 */ "joinop ::= JOIN_KW nm nm JOIN",
/* 134 */ "on_opt ::= ON expr",
/* 135 */ "on_opt ::=",
/* 136 */ "using_opt ::= USING LP idxlist RP",
/* 137 */ "using_opt ::=",
/* 138 */ "orderby_opt ::=",
/* 139 */ "orderby_opt ::= ORDER BY sortlist",
/* 140 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
/* 141 */ "sortlist ::= sortitem collate sortorder",
/* 142 */ "sortitem ::= expr",
/* 143 */ "sortorder ::= ASC",
/* 144 */ "sortorder ::= DESC",
/* 145 */ "sortorder ::=",
/* 146 */ "collate ::=",
/* 147 */ "collate ::= COLLATE id",
/* 148 */ "groupby_opt ::=",
/* 149 */ "groupby_opt ::= GROUP BY exprlist",
/* 150 */ "having_opt ::=",
/* 151 */ "having_opt ::= HAVING expr",
/* 152 */ "limit_opt ::=",
/* 153 */ "limit_opt ::= LIMIT signed",
/* 154 */ "limit_opt ::= LIMIT signed OFFSET signed",
/* 155 */ "limit_opt ::= LIMIT signed COMMA signed",
/* 156 */ "cmd ::= DELETE FROM nm dbnm where_opt",
/* 157 */ "where_opt ::=",
/* 158 */ "where_opt ::= WHERE expr",
/* 159 */ "cmd ::= UPDATE orconf nm dbnm SET setlist where_opt",
/* 160 */ "setlist ::= setlist COMMA nm EQ expr",
/* 161 */ "setlist ::= nm EQ expr",
/* 162 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt VALUES LP itemlist RP",
/* 163 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt select",
/* 164 */ "insert_cmd ::= INSERT orconf",
/* 165 */ "insert_cmd ::= REPLACE",
/* 166 */ "itemlist ::= itemlist COMMA expr",
/* 167 */ "itemlist ::= expr",
/* 168 */ "inscollist_opt ::=",
/* 169 */ "inscollist_opt ::= LP inscollist RP",
/* 170 */ "inscollist ::= inscollist COMMA nm",
/* 171 */ "inscollist ::= nm",
/* 172 */ "expr ::= LP expr RP",
/* 173 */ "expr ::= NULL",
/* 174 */ "expr ::= ID",
/* 175 */ "expr ::= JOIN_KW",
/* 176 */ "expr ::= nm DOT nm",
/* 177 */ "expr ::= nm DOT nm DOT nm",
/* 178 */ "expr ::= INTEGER",
/* 179 */ "expr ::= FLOAT",
/* 180 */ "expr ::= STRING",
/* 181 */ "expr ::= VARIABLE",
/* 182 */ "expr ::= ID LP exprlist RP",
/* 183 */ "expr ::= ID LP STAR RP",
/* 184 */ "expr ::= expr AND expr",
/* 185 */ "expr ::= expr OR expr",
/* 186 */ "expr ::= expr LT expr",
/* 187 */ "expr ::= expr GT expr",
/* 188 */ "expr ::= expr LE expr",
/* 189 */ "expr ::= expr GE expr",
/* 190 */ "expr ::= expr NE expr",
/* 191 */ "expr ::= expr EQ expr",
/* 192 */ "expr ::= expr BITAND expr",
/* 193 */ "expr ::= expr BITOR expr",
/* 194 */ "expr ::= expr LSHIFT expr",
/* 195 */ "expr ::= expr RSHIFT expr",
/* 196 */ "expr ::= expr likeop expr",
/* 197 */ "expr ::= expr NOT likeop expr",
/* 198 */ "likeop ::= LIKE",
/* 199 */ "likeop ::= GLOB",
/* 200 */ "expr ::= expr PLUS expr",
/* 201 */ "expr ::= expr MINUS expr",
/* 202 */ "expr ::= expr STAR expr",
/* 203 */ "expr ::= expr SLASH expr",
/* 204 */ "expr ::= expr REM expr",
/* 205 */ "expr ::= expr CONCAT expr",
/* 206 */ "expr ::= expr ISNULL",
/* 207 */ "expr ::= expr IS NULL",
/* 208 */ "expr ::= expr NOTNULL",
/* 209 */ "expr ::= expr NOT NULL",
/* 210 */ "expr ::= expr IS NOT NULL",
/* 211 */ "expr ::= NOT expr",
/* 212 */ "expr ::= BITNOT expr",
/* 213 */ "expr ::= MINUS expr",
/* 214 */ "expr ::= PLUS expr",
/* 215 */ "expr ::= LP select RP",
/* 216 */ "expr ::= expr BETWEEN expr AND expr",
/* 217 */ "expr ::= expr NOT BETWEEN expr AND expr",
/* 218 */ "expr ::= expr IN LP exprlist RP",
/* 219 */ "expr ::= expr IN LP select RP",
/* 220 */ "expr ::= expr NOT IN LP exprlist RP",
/* 221 */ "expr ::= expr NOT IN LP select RP",
/* 222 */ "expr ::= expr IN nm dbnm",
/* 223 */ "expr ::= expr NOT IN nm dbnm",
/* 224 */ "expr ::= CASE case_operand case_exprlist case_else END",
/* 225 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
/* 226 */ "case_exprlist ::= WHEN expr THEN expr",
/* 227 */ "case_else ::= ELSE expr",
/* 228 */ "case_else ::=",
/* 229 */ "case_operand ::= expr",
/* 230 */ "case_operand ::=",
/* 231 */ "exprlist ::= exprlist COMMA expritem",
/* 232 */ "exprlist ::= expritem",
/* 233 */ "expritem ::= expr",
/* 234 */ "expritem ::=",
/* 235 */ "cmd ::= CREATE uniqueflag INDEX nm ON nm dbnm LP idxlist RP onconf",
/* 236 */ "uniqueflag ::= UNIQUE",
/* 237 */ "uniqueflag ::=",
/* 238 */ "idxlist_opt ::=",
/* 239 */ "idxlist_opt ::= LP idxlist RP",
/* 240 */ "idxlist ::= idxlist COMMA idxitem",
/* 241 */ "idxlist ::= idxitem",
/* 242 */ "idxitem ::= nm sortorder",
/* 243 */ "cmd ::= DROP INDEX nm dbnm",
/* 244 */ "cmd ::= COPY orconf nm dbnm FROM nm USING DELIMITERS STRING",
/* 245 */ "cmd ::= COPY orconf nm dbnm FROM nm",
/* 246 */ "cmd ::= VACUUM",
/* 247 */ "cmd ::= VACUUM nm",
/* 248 */ "cmd ::= PRAGMA ids EQ nm",
/* 249 */ "cmd ::= PRAGMA ids EQ ON",
/* 250 */ "cmd ::= PRAGMA ids EQ plus_num",
/* 251 */ "cmd ::= PRAGMA ids EQ minus_num",
/* 252 */ "cmd ::= PRAGMA ids LP nm RP",
/* 253 */ "cmd ::= PRAGMA ids",
/* 254 */ "plus_num ::= plus_opt number",
/* 255 */ "minus_num ::= MINUS number",
/* 256 */ "number ::= INTEGER",
/* 257 */ "number ::= FLOAT",
/* 258 */ "plus_opt ::= PLUS",
/* 259 */ "plus_opt ::=",
/* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
/* 261 */ "trigger_decl ::= temp TRIGGER nm trigger_time trigger_event ON nm dbnm foreach_clause when_clause",
/* 262 */ "trigger_time ::= BEFORE",
/* 263 */ "trigger_time ::= AFTER",
/* 264 */ "trigger_time ::= INSTEAD OF",
/* 265 */ "trigger_time ::=",
/* 266 */ "trigger_event ::= DELETE",
/* 267 */ "trigger_event ::= INSERT",
/* 268 */ "trigger_event ::= UPDATE",
/* 269 */ "trigger_event ::= UPDATE OF inscollist",
/* 270 */ "foreach_clause ::=",
/* 271 */ "foreach_clause ::= FOR EACH ROW",
/* 272 */ "foreach_clause ::= FOR EACH STATEMENT",
/* 273 */ "when_clause ::=",
/* 274 */ "when_clause ::= WHEN expr",
/* 275 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
/* 276 */ "trigger_cmd_list ::=",
/* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
/* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
/* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
/* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt",
/* 281 */ "trigger_cmd ::= select",
/* 282 */ "expr ::= RAISE LP IGNORE RP",
/* 283 */ "expr ::= RAISE LP ROLLBACK COMMA nm RP",
/* 284 */ "expr ::= RAISE LP ABORT COMMA nm RP",
/* 285 */ "expr ::= RAISE LP FAIL COMMA nm RP",
/* 286 */ "cmd ::= DROP TRIGGER nm dbnm",
/* 287 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
/* 288 */ "key_opt ::= USING ids",
/* 289 */ "key_opt ::=",
/* 290 */ "database_kw_opt ::= DATABASE",
/* 291 */ "database_kw_opt ::=",
/* 292 */ "cmd ::= DETACH database_kw_opt nm",
};
| parse.c | 791 |
CONST CHAR | sqliteParserTokenName(int tokenType)
const char *sqliteParserTokenName(int tokenType){
#ifndef NDEBUG
if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
return yyTokenName[tokenType];
}else{
return "Unknown";
}
#else
return "";
#endif
}
| parse.c | 1178 |
VOID *SQLITEPARSERALLOC(VOID *(*MALLOCPROC | (size_t))
void *sqliteParserAlloc(void *(*mallocProc)(size_t)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
if( pParser ){
pParser->yyidx = -1;
}
return pParser;
}
| parse.c | 1194 |
STATIC VOID | yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor)
static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
switch( yymajor ){
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
case 146:
#line 286 "parse.y"
{sqliteSelectDelete((yypminor->yy179));}
#line 1235 "parse.c"
break;
case 158:
#line 533 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1240 "parse.c"
break;
case 159:
#line 746 "parse.y"
{sqliteIdListDelete((yypminor->yy320));}
#line 1245 "parse.c"
break;
case 167:
#line 744 "parse.y"
{sqliteIdListDelete((yypminor->yy320));}
#line 1250 "parse.c"
break;
case 171:
#line 288 "parse.y"
{sqliteSelectDelete((yypminor->yy179));}
#line 1255 "parse.c"
break;
case 174:
#line 322 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1260 "parse.c"
break;
case 175:
#line 353 "parse.y"
{sqliteSrcListDelete((yypminor->yy307));}
#line 1265 "parse.c"
break;
case 176:
#line 483 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1270 "parse.c"
break;
case 177:
#line 459 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1275 "parse.c"
break;
case 178:
#line 464 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1280 "parse.c"
break;
case 179:
#line 431 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1285 "parse.c"
break;
case 181:
#line 324 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1290 "parse.c"
break;
case 183:
#line 349 "parse.y"
{sqliteSrcListDelete((yypminor->yy307));}
#line 1295 "parse.c"
break;
case 184:
#line 351 "parse.y"
{sqliteSrcListDelete((yypminor->yy307));}
#line 1300 "parse.c"
break;
case 187:
#line 420 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1305 "parse.c"
break;
case 188:
#line 425 "parse.y"
{sqliteIdListDelete((yypminor->yy320));}
#line 1310 "parse.c"
break;
case 189:
#line 400 "parse.y"
{sqliteSelectDelete((yypminor->yy179));}
#line 1315 "parse.c"
break;
case 191:
#line 433 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1320 "parse.c"
break;
case 192:
#line 435 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1325 "parse.c"
break;
case 194:
#line 719 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1330 "parse.c"
break;
case 195:
#line 489 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1335 "parse.c"
break;
case 197:
#line 520 "parse.y"
{sqliteIdListDelete((yypminor->yy320));}
#line 1340 "parse.c"
break;
case 198:
#line 514 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1345 "parse.c"
break;
case 199:
#line 522 "parse.y"
{sqliteIdListDelete((yypminor->yy320));}
#line 1350 "parse.c"
break;
case 202:
#line 702 "parse.y"
{sqliteExprListDelete((yypminor->yy322));}
#line 1355 "parse.c"
break;
case 204:
#line 721 "parse.y"
{sqliteExprDelete((yypminor->yy242));}
#line 1360 "parse.c"
break;
case 212:
#line 828 "parse.y"
{sqliteDeleteTriggerStep((yypminor->yy19));}
#line 1365 "parse.c"
break;
case 214:
#line 812 "parse.y"
{sqliteIdListDelete((yypminor->yy290).b);}
#line 1370 "parse.c"
break;
case 217:
#line 836 "parse.y"
{sqliteDeleteTriggerStep((yypminor->yy19));}
#line 1375 "parse.c"
break;
default: break; /* If no destructor action specified: do nothing */
}
}
| parse.c | 1215 |
STATIC INT | yy_pop_parser_stack(yyParser *pParser)
static int yy_pop_parser_stack(yyParser *pParser){
YYCODETYPE yymajor;
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
if( pParser->yyidx<0 ) return 0;
#ifndef NDEBUG
if( yyTraceFILE && pParser->yyidx>=0 ){
fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt,
yyTokenName[yytos->major]);
}
#endif
yymajor = yytos->major;
yy_destructor( yymajor, &yytos->minor);
pParser->yyidx--;
return yymajor;
}
| parse.c | 1381 |
VOID SQLITEPARSERFREE( VOID *P, VOID (*FREEPROC | (void*) )
void sqliteParserFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
if( pParser==0 ) return;
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
(*freeProc)((void*)pParser);
}
| parse.c | 1407 |
STATIC INT | yy_find_shift_action( yyParser *pParser, int iLookAhead )
static int yy_find_shift_action(
yyParser *pParser, /* The parser */
int iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
/* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
if( iLookAhead==YYNOCODE ){
return YY_NO_ACTION;
}
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
int iFallback; /* Fallback token */
if( iLookAhead %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
return yy_find_shift_action(pParser, iFallback);
}
#endif
return yy_default[stateno];
}else{
return yy_action[i];
}
}
| parse.c | 1429 |
STATIC INT | yy_find_reduce_action( yyParser *pParser, int iLookAhead )
static int yy_find_reduce_action(
yyParser *pParser, /* The parser */
int iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
i = yy_reduce_ofst[stateno];
if( i==YY_REDUCE_USE_DFLT ){
return yy_default[stateno];
}
if( iLookAhead==YYNOCODE ){
return YY_NO_ACTION;
}
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}else{
return yy_action[i];
}
}
| parse.c | 1473 |
STATIC VOID | yy_shift( yyParser *yypParser, int yyNewState, int yyMajor, YYMINORTYPE *yypMinor )
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
int yyNewState, /* The new state to shift in */
int yyMajor, /* The major token to shift in */
YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yyidx++;
if( yypParser->yyidx>=YYSTACKDEPTH ){
sqliteParserARG_FETCH;
yypParser->yyidx--;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument var */
return;
}
yytos = &yypParser->yystack[yypParser->yyidx];
yytos->stateno = yyNewState;
yytos->major = yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}
#endif
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
{ 132, 1 },
{ 133, 2 },
{ 133, 1 },
{ 134, 3 },
{ 134, 1 },
{ 136, 1 },
{ 135, 1 },
{ 135, 0 },
{ 137, 3 },
{ 138, 0 },
{ 138, 1 },
{ 138, 2 },
{ 137, 2 },
{ 137, 2 },
{ 137, 2 },
{ 137, 2 },
{ 141, 4 },
{ 143, 1 },
{ 143, 0 },
{ 142, 4 },
{ 142, 2 },
{ 144, 3 },
{ 144, 1 },
{ 147, 3 },
{ 148, 1 },
{ 151, 1 },
{ 152, 1 },
{ 152, 1 },
{ 140, 1 },
{ 140, 1 },
{ 140, 1 },
{ 149, 0 },
{ 149, 1 },
{ 149, 4 },
{ 149, 6 },
{ 153, 1 },
{ 153, 2 },
{ 154, 1 },
{ 154, 2 },
{ 154, 2 },
{ 150, 2 },
{ 150, 0 },
{ 155, 3 },
{ 155, 1 },
{ 155, 2 },
{ 155, 2 },
{ 155, 2 },
{ 155, 3 },
{ 155, 3 },
{ 155, 2 },
{ 155, 3 },
{ 155, 3 },
{ 155, 2 },
{ 156, 2 },
{ 156, 3 },
{ 156, 4 },
{ 156, 2 },
{ 156, 5 },
{ 156, 4 },
{ 156, 1 },
{ 156, 2 },
{ 160, 0 },
{ 160, 2 },
{ 162, 2 },
{ 162, 3 },
{ 162, 3 },
{ 162, 3 },
{ 163, 2 },
{ 163, 2 },
{ 163, 1 },
{ 163, 1 },
{ 161, 3 },
{ 161, 2 },
{ 164, 0 },
{ 164, 2 },
{ 164, 2 },
{ 145, 0 },
{ 145, 2 },
{ 165, 3 },
{ 165, 2 },
{ 165, 1 },
{ 166, 2 },
{ 166, 6 },
{ 166, 5 },
{ 166, 3 },
{ 166, 10 },
{ 168, 0 },
{ 168, 1 },
{ 139, 0 },
{ 139, 3 },
{ 169, 0 },
{ 169, 2 },
{ 170, 1 },
{ 170, 1 },
{ 170, 1 },
{ 170, 1 },
{ 170, 1 },
{ 137, 3 },
{ 137, 6 },
{ 137, 3 },
{ 137, 1 },
{ 146, 1 },
{ 146, 3 },
{ 172, 1 },
{ 172, 2 },
{ 172, 1 },
{ 172, 1 },
{ 171, 9 },
{ 173, 1 },
{ 173, 1 },
{ 173, 0 },
{ 181, 2 },
{ 181, 0 },
{ 174, 3 },
{ 174, 2 },
{ 174, 4 },
{ 182, 2 },
{ 182, 1 },
{ 182, 0 },
{ 175, 0 },
{ 175, 2 },
{ 184, 2 },
{ 184, 0 },
{ 183, 6 },
{ 183, 7 },
{ 189, 1 },
{ 189, 1 },
{ 186, 0 },
{ 186, 2 },
{ 185, 1 },
{ 185, 1 },
{ 185, 2 },
{ 185, 3 },
{ 185, 4 },
{ 187, 2 },
{ 187, 0 },
{ 188, 4 },
{ 188, 0 },
{ 179, 0 },
{ 179, 3 },
{ 191, 5 },
{ 191, 3 },
{ 192, 1 },
{ 157, 1 },
{ 157, 1 },
{ 157, 0 },
{ 193, 0 },
{ 193, 2 },
{ 177, 0 },
{ 177, 3 },
{ 178, 0 },
{ 178, 2 },
{ 180, 0 },
{ 180, 2 },
{ 180, 4 },
{ 180, 4 },
{ 137, 5 },
{ 176, 0 },
{ 176, 2 },
{ 137, 7 },
{ 195, 5 },
{ 195, 3 },
{ 137, 9 },
{ 137, 6 },
{ 196, 2 },
{ 196, 1 },
{ 198, 3 },
{ 198, 1 },
{ 197, 0 },
{ 197, 3 },
{ 199, 3 },
{ 199, 1 },
{ 158, 3 },
{ 158, 1 },
{ 158, 1 },
{ 158, 1 },
{ 158, 3 },
{ 158, 5 },
{ 158, 1 },
{ 158, 1 },
{ 158, 1 },
{ 158, 1 },
{ 158, 4 },
{ 158, 4 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 4 },
{ 200, 1 },
{ 200, 1 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 3 },
{ 158, 2 },
{ 158, 3 },
{ 158, 2 },
{ 158, 3 },
{ 158, 4 },
{ 158, 2 },
{ 158, 2 },
{ 158, 2 },
{ 158, 2 },
{ 158, 3 },
{ 158, 5 },
{ 158, 6 },
{ 158, 5 },
{ 158, 5 },
{ 158, 6 },
{ 158, 6 },
{ 158, 4 },
{ 158, 5 },
{ 158, 5 },
{ 202, 5 },
{ 202, 4 },
{ 203, 2 },
{ 203, 0 },
{ 201, 1 },
{ 201, 0 },
{ 194, 3 },
{ 194, 1 },
{ 204, 1 },
{ 204, 0 },
{ 137, 11 },
{ 205, 1 },
{ 205, 0 },
{ 159, 0 },
{ 159, 3 },
{ 167, 3 },
{ 167, 1 },
{ 206, 2 },
{ 137, 4 },
{ 137, 9 },
{ 137, 6 },
{ 137, 1 },
{ 137, 2 },
{ 137, 4 },
{ 137, 4 },
{ 137, 4 },
{ 137, 4 },
{ 137, 5 },
{ 137, 2 },
{ 207, 2 },
{ 208, 2 },
{ 210, 1 },
{ 210, 1 },
{ 209, 1 },
{ 209, 0 },
{ 137, 5 },
{ 211, 10 },
{ 213, 1 },
{ 213, 1 },
{ 213, 2 },
{ 213, 0 },
{ 214, 1 },
{ 214, 1 },
{ 214, 1 },
{ 214, 3 },
{ 215, 0 },
{ 215, 3 },
{ 215, 3 },
{ 216, 0 },
{ 216, 2 },
{ 212, 3 },
{ 212, 0 },
{ 217, 6 },
{ 217, 8 },
{ 217, 5 },
{ 217, 4 },
{ 217, 1 },
{ 158, 4 },
{ 158, 6 },
{ 158, 6 },
{ 158, 6 },
{ 137, 4 },
{ 137, 6 },
{ 219, 2 },
{ 219, 0 },
{ 218, 1 },
{ 218, 0 },
{ 137, 3 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
| parse.c | 1503 |
STATIC VOID | yy_reduce( yyParser *yypParser, int yyruleno )
static void yy_reduce(
yyParser *yypParser, /* The parser */
int yyruleno /* Number of the rule by which to reduce */
){
int yygoto; /* The next state */
int yyact; /* The next action */
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
sqliteParserARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno
** { ... } // User supplied code
** #line
** break;
*/
case 0:
/* No destructor defined for cmdlist */
break;
case 1:
/* No destructor defined for cmdlist */
/* No destructor defined for ecmd */
break;
case 2:
/* No destructor defined for ecmd */
break;
case 3:
/* No destructor defined for explain */
/* No destructor defined for cmdx */
/* No destructor defined for SEMI */
break;
case 4:
/* No destructor defined for SEMI */
break;
case 5:
#line 72 "parse.y"
{ sqliteExec(pParse); }
#line 1901 "parse.c"
/* No destructor defined for cmd */
break;
case 6:
#line 73 "parse.y"
{ sqliteBeginParse(pParse, 1); }
#line 1907 "parse.c"
/* No destructor defined for EXPLAIN */
break;
case 7:
#line 74 "parse.y"
{ sqliteBeginParse(pParse, 0); }
#line 1913 "parse.c"
break;
case 8:
#line 79 "parse.y"
{sqliteBeginTransaction(pParse,yymsp[0].minor.yy372);}
#line 1918 "parse.c"
/* No destructor defined for BEGIN */
/* No destructor defined for trans_opt */
break;
case 9:
break;
case 10:
/* No destructor defined for TRANSACTION */
break;
case 11:
/* No destructor defined for TRANSACTION */
/* No destructor defined for nm */
break;
case 12:
#line 83 "parse.y"
{sqliteCommitTransaction(pParse);}
#line 1934 "parse.c"
/* No destructor defined for COMMIT */
/* No destructor defined for trans_opt */
break;
case 13:
#line 84 "parse.y"
{sqliteCommitTransaction(pParse);}
#line 1941 "parse.c"
/* No destructor defined for END */
/* No destructor defined for trans_opt */
break;
case 14:
#line 85 "parse.y"
{sqliteRollbackTransaction(pParse);}
#line 1948 "parse.c"
/* No destructor defined for ROLLBACK */
/* No destructor defined for trans_opt */
break;
case 15:
/* No destructor defined for create_table */
/* No destructor defined for create_table_args */
break;
case 16:
#line 90 "parse.y"
{
sqliteStartTable(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy298,yymsp[-2].minor.yy372,0);
}
#line 1961 "parse.c"
/* No destructor defined for TABLE */
break;
case 17:
#line 94 "parse.y"
{yygotominor.yy372 = 1;}
#line 1967 "parse.c"
/* No destructor defined for TEMP */
break;
case 18:
#line 95 "parse.y"
{yygotominor.yy372 = 0;}
#line 1973 "parse.c"
break;
case 19:
#line 96 "parse.y"
{
sqliteEndTable(pParse,&yymsp[0].minor.yy0,0);
}
#line 1980 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for columnlist */
/* No destructor defined for conslist_opt */
break;
case 20:
#line 99 "parse.y"
{
sqliteEndTable(pParse,0,yymsp[0].minor.yy179);
sqliteSelectDelete(yymsp[0].minor.yy179);
}
#line 1991 "parse.c"
/* No destructor defined for AS */
break;
case 21:
/* No destructor defined for columnlist */
/* No destructor defined for COMMA */
/* No destructor defined for column */
break;
case 22:
/* No destructor defined for column */
break;
case 23:
/* No destructor defined for columnid */
/* No destructor defined for type */
/* No destructor defined for carglist */
break;
case 24:
#line 111 "parse.y"
{sqliteAddColumn(pParse,&yymsp[0].minor.yy298);}
#line 2010 "parse.c"
break;
case 25:
#line 117 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2015 "parse.c"
break;
case 26:
#line 149 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2020 "parse.c"
break;
case 27:
#line 150 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2025 "parse.c"
break;
case 28:
#line 155 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2030 "parse.c"
break;
case 29:
#line 156 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2035 "parse.c"
break;
case 30:
#line 157 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 2040 "parse.c"
break;
case 31:
break;
case 32:
#line 160 "parse.y"
{sqliteAddColumnType(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298);}
#line 2047 "parse.c"
break;
case 33:
#line 161 "parse.y"
{sqliteAddColumnType(pParse,&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0);}
#line 2052 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for signed */
break;
case 34:
#line 163 "parse.y"
{sqliteAddColumnType(pParse,&yymsp[-5].minor.yy298,&yymsp[0].minor.yy0);}
#line 2059 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for signed */
/* No destructor defined for COMMA */
/* No destructor defined for signed */
break;
case 35:
#line 165 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy298;}
#line 2068 "parse.c"
break;
case 36:
#line 166 "parse.y"
{yygotominor.yy298 = yymsp[-1].minor.yy298;}
#line 2073 "parse.c"
/* No destructor defined for ids */
break;
case 37:
#line 168 "parse.y"
{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); }
#line 2079 "parse.c"
break;
case 38:
#line 169 "parse.y"
{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); }
#line 2084 "parse.c"
/* No destructor defined for PLUS */
break;
case 39:
#line 170 "parse.y"
{ yygotominor.yy372 = -atoi(yymsp[0].minor.yy0.z); }
#line 2090 "parse.c"
/* No destructor defined for MINUS */
break;
case 40:
/* No destructor defined for carglist */
/* No destructor defined for carg */
break;
case 41:
break;
case 42:
/* No destructor defined for CONSTRAINT */
/* No destructor defined for nm */
/* No destructor defined for ccons */
break;
case 43:
/* No destructor defined for ccons */
break;
case 44:
#line 175 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2110 "parse.c"
/* No destructor defined for DEFAULT */
break;
case 45:
#line 176 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2116 "parse.c"
/* No destructor defined for DEFAULT */
break;
case 46:
#line 177 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2122 "parse.c"
/* No destructor defined for DEFAULT */
break;
case 47:
#line 178 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2128 "parse.c"
/* No destructor defined for DEFAULT */
/* No destructor defined for PLUS */
break;
case 48:
#line 179 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);}
#line 2135 "parse.c"
/* No destructor defined for DEFAULT */
/* No destructor defined for MINUS */
break;
case 49:
#line 180 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2142 "parse.c"
/* No destructor defined for DEFAULT */
break;
case 50:
#line 181 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
#line 2148 "parse.c"
/* No destructor defined for DEFAULT */
/* No destructor defined for PLUS */
break;
case 51:
#line 182 "parse.y"
{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);}
#line 2155 "parse.c"
/* No destructor defined for DEFAULT */
/* No destructor defined for MINUS */
break;
case 52:
/* No destructor defined for DEFAULT */
/* No destructor defined for NULL */
break;
case 53:
/* No destructor defined for NULL */
/* No destructor defined for onconf */
break;
case 54:
#line 189 "parse.y"
{sqliteAddNotNull(pParse, yymsp[0].minor.yy372);}
#line 2170 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for NULL */
break;
case 55:
#line 190 "parse.y"
{sqliteAddPrimaryKey(pParse,0,yymsp[0].minor.yy372);}
#line 2177 "parse.c"
/* No destructor defined for PRIMARY */
/* No destructor defined for KEY */
/* No destructor defined for sortorder */
break;
case 56:
#line 191 "parse.y"
{sqliteCreateIndex(pParse,0,0,0,yymsp[0].minor.yy372,0,0);}
#line 2185 "parse.c"
/* No destructor defined for UNIQUE */
break;
case 57:
/* No destructor defined for CHECK */
/* No destructor defined for LP */
yy_destructor(158,&yymsp[-2].minor);
/* No destructor defined for RP */
/* No destructor defined for onconf */
break;
case 58:
#line 194 "parse.y"
{sqliteCreateForeignKey(pParse,0,&yymsp[-2].minor.yy298,yymsp[-1].minor.yy320,yymsp[0].minor.yy372);}
#line 2198 "parse.c"
/* No destructor defined for REFERENCES */
break;
case 59:
#line 195 "parse.y"
{sqliteDeferForeignKey(pParse,yymsp[0].minor.yy372);}
#line 2204 "parse.c"
break;
case 60:
#line 196 "parse.y"
{
sqliteAddCollateType(pParse, sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n));
}
#line 2211 "parse.c"
/* No destructor defined for COLLATE */
break;
case 61:
#line 206 "parse.y"
{ yygotominor.yy372 = OE_Restrict * 0x010101; }
#line 2217 "parse.c"
break;
case 62:
#line 207 "parse.y"
{ yygotominor.yy372 = (yymsp[-1].minor.yy372 & yymsp[0].minor.yy407.mask) | yymsp[0].minor.yy407.value; }
#line 2222 "parse.c"
break;
case 63:
#line 209 "parse.y"
{ yygotominor.yy407.value = 0; yygotominor.yy407.mask = 0x000000; }
#line 2227 "parse.c"
/* No destructor defined for MATCH */
/* No destructor defined for nm */
break;
case 64:
#line 210 "parse.y"
{ yygotominor.yy407.value = yymsp[0].minor.yy372; yygotominor.yy407.mask = 0x0000ff; }
#line 2234 "parse.c"
/* No destructor defined for ON */
/* No destructor defined for DELETE */
break;
case 65:
#line 211 "parse.y"
{ yygotominor.yy407.value = yymsp[0].minor.yy372<<8; yygotominor.yy407.mask = 0x00ff00; }
#line 2241 "parse.c"
/* No destructor defined for ON */
/* No destructor defined for UPDATE */
break;
case 66:
#line 212 "parse.y"
{ yygotominor.yy407.value = yymsp[0].minor.yy372<<16; yygotominor.yy407.mask = 0xff0000; }
#line 2248 "parse.c"
/* No destructor defined for ON */
/* No destructor defined for INSERT */
break;
case 67:
#line 214 "parse.y"
{ yygotominor.yy372 = OE_SetNull; }
#line 2255 "parse.c"
/* No destructor defined for SET */
/* No destructor defined for NULL */
break;
case 68:
#line 215 "parse.y"
{ yygotominor.yy372 = OE_SetDflt; }
#line 2262 "parse.c"
/* No destructor defined for SET */
/* No destructor defined for DEFAULT */
break;
case 69:
#line 216 "parse.y"
{ yygotominor.yy372 = OE_Cascade; }
#line 2269 "parse.c"
/* No destructor defined for CASCADE */
break;
case 70:
#line 217 "parse.y"
{ yygotominor.yy372 = OE_Restrict; }
#line 2275 "parse.c"
/* No destructor defined for RESTRICT */
break;
case 71:
#line 219 "parse.y"
{yygotominor.yy372 = yymsp[0].minor.yy372;}
#line 2281 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for DEFERRABLE */
break;
case 72:
#line 220 "parse.y"
{yygotominor.yy372 = yymsp[0].minor.yy372;}
#line 2288 "parse.c"
/* No destructor defined for DEFERRABLE */
break;
case 73:
#line 222 "parse.y"
{yygotominor.yy372 = 0;}
#line 2294 "parse.c"
break;
case 74:
#line 223 "parse.y"
{yygotominor.yy372 = 1;}
#line 2299 "parse.c"
/* No destructor defined for INITIALLY */
/* No destructor defined for DEFERRED */
break;
case 75:
#line 224 "parse.y"
{yygotominor.yy372 = 0;}
#line 2306 "parse.c"
/* No destructor defined for INITIALLY */
/* No destructor defined for IMMEDIATE */
break;
case 76:
break;
case 77:
/* No destructor defined for COMMA */
/* No destructor defined for conslist */
break;
case 78:
/* No destructor defined for conslist */
/* No destructor defined for COMMA */
/* No destructor defined for tcons */
break;
case 79:
/* No destructor defined for conslist */
/* No destructor defined for tcons */
break;
case 80:
/* No destructor defined for tcons */
break;
case 81:
/* No destructor defined for CONSTRAINT */
/* No destructor defined for nm */
break;
case 82:
#line 236 "parse.y"
{sqliteAddPrimaryKey(pParse,yymsp[-2].minor.yy320,yymsp[0].minor.yy372);}
#line 2335 "parse.c"
/* No destructor defined for PRIMARY */
/* No destructor defined for KEY */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 83:
#line 238 "parse.y"
{sqliteCreateIndex(pParse,0,0,yymsp[-2].minor.yy320,yymsp[0].minor.yy372,0,0);}
#line 2344 "parse.c"
/* No destructor defined for UNIQUE */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 84:
/* No destructor defined for CHECK */
yy_destructor(158,&yymsp[-1].minor);
/* No destructor defined for onconf */
break;
case 85:
#line 241 "parse.y"
{
sqliteCreateForeignKey(pParse, yymsp[-6].minor.yy320, &yymsp[-3].minor.yy298, yymsp[-2].minor.yy320, yymsp[-1].minor.yy372);
sqliteDeferForeignKey(pParse, yymsp[0].minor.yy372);
}
#line 2360 "parse.c"
/* No destructor defined for FOREIGN */
/* No destructor defined for KEY */
/* No destructor defined for LP */
/* No destructor defined for RP */
/* No destructor defined for REFERENCES */
break;
case 86:
#line 246 "parse.y"
{yygotominor.yy372 = 0;}
#line 2370 "parse.c"
break;
case 87:
#line 247 "parse.y"
{yygotominor.yy372 = yymsp[0].minor.yy372;}
#line 2375 "parse.c"
break;
case 88:
#line 255 "parse.y"
{ yygotominor.yy372 = OE_Default; }
#line 2380 "parse.c"
break;
case 89:
#line 256 "parse.y"
{ yygotominor.yy372 = yymsp[0].minor.yy372; }
#line 2385 "parse.c"
/* No destructor defined for ON */
/* No destructor defined for CONFLICT */
break;
case 90:
#line 257 "parse.y"
{ yygotominor.yy372 = OE_Default; }
#line 2392 "parse.c"
break;
case 91:
#line 258 "parse.y"
{ yygotominor.yy372 = yymsp[0].minor.yy372; }
#line 2397 "parse.c"
/* No destructor defined for OR */
break;
case 92:
#line 259 "parse.y"
{ yygotominor.yy372 = OE_Rollback; }
#line 2403 "parse.c"
/* No destructor defined for ROLLBACK */
break;
case 93:
#line 260 "parse.y"
{ yygotominor.yy372 = OE_Abort; }
#line 2409 "parse.c"
/* No destructor defined for ABORT */
break;
case 94:
#line 261 "parse.y"
{ yygotominor.yy372 = OE_Fail; }
#line 2415 "parse.c"
/* No destructor defined for FAIL */
break;
case 95:
#line 262 "parse.y"
{ yygotominor.yy372 = OE_Ignore; }
#line 2421 "parse.c"
/* No destructor defined for IGNORE */
break;
case 96:
#line 263 "parse.y"
{ yygotominor.yy372 = OE_Replace; }
#line 2427 "parse.c"
/* No destructor defined for REPLACE */
break;
case 97:
#line 267 "parse.y"
{sqliteDropTable(pParse,&yymsp[0].minor.yy298,0);}
#line 2433 "parse.c"
/* No destructor defined for DROP */
/* No destructor defined for TABLE */
break;
case 98:
#line 271 "parse.y"
{
sqliteCreateView(pParse, &yymsp[-5].minor.yy0, &yymsp[-2].minor.yy298, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);
}
#line 2442 "parse.c"
/* No destructor defined for VIEW */
/* No destructor defined for AS */
break;
case 99:
#line 274 "parse.y"
{
sqliteDropTable(pParse, &yymsp[0].minor.yy298, 1);
}
#line 2451 "parse.c"
/* No destructor defined for DROP */
/* No destructor defined for VIEW */
break;
case 100:
#line 280 "parse.y"
{
sqliteSelect(pParse, yymsp[0].minor.yy179, SRT_Callback, 0, 0, 0, 0);
sqliteSelectDelete(yymsp[0].minor.yy179);
}
#line 2461 "parse.c"
break;
case 101:
#line 290 "parse.y"
{yygotominor.yy179 = yymsp[0].minor.yy179;}
#line 2466 "parse.c"
break;
case 102:
#line 291 "parse.y"
{
if( yymsp[0].minor.yy179 ){
yymsp[0].minor.yy179->op = yymsp[-1].minor.yy372;
yymsp[0].minor.yy179->pPrior = yymsp[-2].minor.yy179;
}
yygotominor.yy179 = yymsp[0].minor.yy179;
}
#line 2477 "parse.c"
break;
case 103:
#line 299 "parse.y"
{yygotominor.yy372 = TK_UNION;}
#line 2482 "parse.c"
/* No destructor defined for UNION */
break;
case 104:
#line 300 "parse.y"
{yygotominor.yy372 = TK_ALL;}
#line 2488 "parse.c"
/* No destructor defined for UNION */
/* No destructor defined for ALL */
break;
case 105:
#line 301 "parse.y"
{yygotominor.yy372 = TK_INTERSECT;}
#line 2495 "parse.c"
/* No destructor defined for INTERSECT */
break;
case 106:
#line 302 "parse.y"
{yygotominor.yy372 = TK_EXCEPT;}
#line 2501 "parse.c"
/* No destructor defined for EXCEPT */
break;
case 107:
#line 304 "parse.y"
{
yygotominor.yy179 = sqliteSelectNew(yymsp[-6].minor.yy322,yymsp[-5].minor.yy307,yymsp[-4].minor.yy242,yymsp[-3].minor.yy322,yymsp[-2].minor.yy242,yymsp[-1].minor.yy322,yymsp[-7].minor.yy372,yymsp[0].minor.yy124.limit,yymsp[0].minor.yy124.offset);
}
#line 2509 "parse.c"
/* No destructor defined for SELECT */
break;
case 108:
#line 312 "parse.y"
{yygotominor.yy372 = 1;}
#line 2515 "parse.c"
/* No destructor defined for DISTINCT */
break;
case 109:
#line 313 "parse.y"
{yygotominor.yy372 = 0;}
#line 2521 "parse.c"
/* No destructor defined for ALL */
break;
case 110:
#line 314 "parse.y"
{yygotominor.yy372 = 0;}
#line 2527 "parse.c"
break;
case 111:
#line 325 "parse.y"
{yygotominor.yy322 = yymsp[-1].minor.yy322;}
#line 2532 "parse.c"
/* No destructor defined for COMMA */
break;
case 112:
#line 326 "parse.y"
{yygotominor.yy322 = 0;}
#line 2538 "parse.c"
break;
case 113:
#line 327 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[-1].minor.yy242,yymsp[0].minor.yy298.n?&yymsp[0].minor.yy298:0);
}
#line 2545 "parse.c"
break;
case 114:
#line 330 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(yymsp[-1].minor.yy322, sqliteExpr(TK_ALL, 0, 0, 0), 0);
}
#line 2552 "parse.c"
/* No destructor defined for STAR */
break;
case 115:
#line 333 "parse.y"
{
Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0);
Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
yygotominor.yy322 = sqliteExprListAppend(yymsp[-3].minor.yy322, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0);
}
#line 2562 "parse.c"
/* No destructor defined for DOT */
/* No destructor defined for STAR */
break;
case 116:
#line 343 "parse.y"
{ yygotominor.yy298 = yymsp[0].minor.yy298; }
#line 2569 "parse.c"
/* No destructor defined for AS */
break;
case 117:
#line 344 "parse.y"
{ yygotominor.yy298 = yymsp[0].minor.yy298; }
#line 2575 "parse.c"
break;
case 118:
#line 345 "parse.y"
{ yygotominor.yy298.n = 0; }
#line 2580 "parse.c"
break;
case 119:
#line 357 "parse.y"
{yygotominor.yy307 = sqliteMalloc(sizeof(*yygotominor.yy307));}
#line 2585 "parse.c"
break;
case 120:
#line 358 "parse.y"
{yygotominor.yy307 = yymsp[0].minor.yy307;}
#line 2590 "parse.c"
/* No destructor defined for FROM */
break;
case 121:
#line 363 "parse.y"
{
yygotominor.yy307 = yymsp[-1].minor.yy307;
if( yygotominor.yy307 && yygotominor.yy307->nSrc>0 ) yygotominor.yy307->a[yygotominor.yy307->nSrc-1].jointype = yymsp[0].minor.yy372;
}
#line 2599 "parse.c"
break;
case 122:
#line 367 "parse.y"
{yygotominor.yy307 = 0;}
#line 2604 "parse.c"
break;
case 123:
#line 368 "parse.y"
{
yygotominor.yy307 = sqliteSrcListAppend(yymsp[-5].minor.yy307,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298);
if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298);
if( yymsp[-1].minor.yy242 ){
if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; }
else { sqliteExprDelete(yymsp[-1].minor.yy242); }
}
if( yymsp[0].minor.yy320 ){
if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; }
else { sqliteIdListDelete(yymsp[0].minor.yy320); }
}
}
#line 2620 "parse.c"
break;
case 124:
#line 381 "parse.y"
{
yygotominor.yy307 = sqliteSrcListAppend(yymsp[-6].minor.yy307,0,0);
yygotominor.yy307->a[yygotominor.yy307->nSrc-1].pSelect = yymsp[-4].minor.yy179;
if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298);
if( yymsp[-1].minor.yy242 ){
if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; }
else { sqliteExprDelete(yymsp[-1].minor.yy242); }
}
if( yymsp[0].minor.yy320 ){
if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; }
else { sqliteIdListDelete(yymsp[0].minor.yy320); }
}
}
#line 2637 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 125:
#line 401 "parse.y"
{yygotominor.yy179 = yymsp[0].minor.yy179;}
#line 2644 "parse.c"
break;
case 126:
#line 402 "parse.y"
{
yygotominor.yy179 = sqliteSelectNew(0,yymsp[0].minor.yy307,0,0,0,0,0,-1,0);
}
#line 2651 "parse.c"
break;
case 127:
#line 407 "parse.y"
{yygotominor.yy298.z=0; yygotominor.yy298.n=0;}
#line 2656 "parse.c"
break;
case 128:
#line 408 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy298;}
#line 2661 "parse.c"
/* No destructor defined for DOT */
break;
case 129:
#line 412 "parse.y"
{ yygotominor.yy372 = JT_INNER; }
#line 2667 "parse.c"
/* No destructor defined for COMMA */
break;
case 130:
#line 413 "parse.y"
{ yygotominor.yy372 = JT_INNER; }
#line 2673 "parse.c"
/* No destructor defined for JOIN */
break;
case 131:
#line 414 "parse.y"
{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
#line 2679 "parse.c"
/* No destructor defined for JOIN */
break;
case 132:
#line 415 "parse.y"
{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy298,0); }
#line 2685 "parse.c"
/* No destructor defined for JOIN */
break;
case 133:
#line 417 "parse.y"
{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298); }
#line 2691 "parse.c"
/* No destructor defined for JOIN */
break;
case 134:
#line 421 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 2697 "parse.c"
/* No destructor defined for ON */
break;
case 135:
#line 422 "parse.y"
{yygotominor.yy242 = 0;}
#line 2703 "parse.c"
break;
case 136:
#line 426 "parse.y"
{yygotominor.yy320 = yymsp[-1].minor.yy320;}
#line 2708 "parse.c"
/* No destructor defined for USING */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 137:
#line 427 "parse.y"
{yygotominor.yy320 = 0;}
#line 2716 "parse.c"
break;
case 138:
#line 437 "parse.y"
{yygotominor.yy322 = 0;}
#line 2721 "parse.c"
break;
case 139:
#line 438 "parse.y"
{yygotominor.yy322 = yymsp[0].minor.yy322;}
#line 2726 "parse.c"
/* No destructor defined for ORDER */
/* No destructor defined for BY */
break;
case 140:
#line 439 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[-2].minor.yy242,0);
if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
}
#line 2736 "parse.c"
/* No destructor defined for COMMA */
break;
case 141:
#line 443 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(0,yymsp[-2].minor.yy242,0);
if( yygotominor.yy322 ) yygotominor.yy322->a[0].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
}
#line 2745 "parse.c"
break;
case 142:
#line 447 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 2750 "parse.c"
break;
case 143:
#line 452 "parse.y"
{yygotominor.yy372 = SQLITE_SO_ASC;}
#line 2755 "parse.c"
/* No destructor defined for ASC */
break;
case 144:
#line 453 "parse.y"
{yygotominor.yy372 = SQLITE_SO_DESC;}
#line 2761 "parse.c"
/* No destructor defined for DESC */
break;
case 145:
#line 454 "parse.y"
{yygotominor.yy372 = SQLITE_SO_ASC;}
#line 2767 "parse.c"
break;
case 146:
#line 455 "parse.y"
{yygotominor.yy372 = SQLITE_SO_UNK;}
#line 2772 "parse.c"
break;
case 147:
#line 456 "parse.y"
{yygotominor.yy372 = sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n);}
#line 2777 "parse.c"
/* No destructor defined for COLLATE */
break;
case 148:
#line 460 "parse.y"
{yygotominor.yy322 = 0;}
#line 2783 "parse.c"
break;
case 149:
#line 461 "parse.y"
{yygotominor.yy322 = yymsp[0].minor.yy322;}
#line 2788 "parse.c"
/* No destructor defined for GROUP */
/* No destructor defined for BY */
break;
case 150:
#line 465 "parse.y"
{yygotominor.yy242 = 0;}
#line 2795 "parse.c"
break;
case 151:
#line 466 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 2800 "parse.c"
/* No destructor defined for HAVING */
break;
case 152:
#line 469 "parse.y"
{yygotominor.yy124.limit = -1; yygotominor.yy124.offset = 0;}
#line 2806 "parse.c"
break;
case 153:
#line 470 "parse.y"
{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = 0;}
#line 2811 "parse.c"
/* No destructor defined for LIMIT */
break;
case 154:
#line 472 "parse.y"
{yygotominor.yy124.limit = yymsp[-2].minor.yy372; yygotominor.yy124.offset = yymsp[0].minor.yy372;}
#line 2817 "parse.c"
/* No destructor defined for LIMIT */
/* No destructor defined for OFFSET */
break;
case 155:
#line 474 "parse.y"
{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = yymsp[-2].minor.yy372;}
#line 2824 "parse.c"
/* No destructor defined for LIMIT */
/* No destructor defined for COMMA */
break;
case 156:
#line 478 "parse.y"
{
sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298), yymsp[0].minor.yy242);
}
#line 2833 "parse.c"
/* No destructor defined for DELETE */
/* No destructor defined for FROM */
break;
case 157:
#line 485 "parse.y"
{yygotominor.yy242 = 0;}
#line 2840 "parse.c"
break;
case 158:
#line 486 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 2845 "parse.c"
/* No destructor defined for WHERE */
break;
case 159:
#line 494 "parse.y"
{sqliteUpdate(pParse,sqliteSrcListAppend(0,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298),yymsp[-1].minor.yy322,yymsp[0].minor.yy242,yymsp[-5].minor.yy372);}
#line 2851 "parse.c"
/* No destructor defined for UPDATE */
/* No destructor defined for SET */
break;
case 160:
#line 497 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);}
#line 2858 "parse.c"
/* No destructor defined for COMMA */
/* No destructor defined for EQ */
break;
case 161:
#line 498 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);}
#line 2865 "parse.c"
/* No destructor defined for EQ */
break;
case 162:
#line 504 "parse.y"
{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298), yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy320, yymsp[-8].minor.yy372);}
#line 2871 "parse.c"
/* No destructor defined for INTO */
/* No destructor defined for VALUES */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 163:
#line 506 "parse.y"
{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298), 0, yymsp[0].minor.yy179, yymsp[-1].minor.yy320, yymsp[-5].minor.yy372);}
#line 2880 "parse.c"
/* No destructor defined for INTO */
break;
case 164:
#line 509 "parse.y"
{yygotominor.yy372 = yymsp[0].minor.yy372;}
#line 2886 "parse.c"
/* No destructor defined for INSERT */
break;
case 165:
#line 510 "parse.y"
{yygotominor.yy372 = OE_Replace;}
#line 2892 "parse.c"
/* No destructor defined for REPLACE */
break;
case 166:
#line 516 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);}
#line 2898 "parse.c"
/* No destructor defined for COMMA */
break;
case 167:
#line 517 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);}
#line 2904 "parse.c"
break;
case 168:
#line 524 "parse.y"
{yygotominor.yy320 = 0;}
#line 2909 "parse.c"
break;
case 169:
#line 525 "parse.y"
{yygotominor.yy320 = yymsp[-1].minor.yy320;}
#line 2914 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 170:
#line 526 "parse.y"
{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);}
#line 2921 "parse.c"
/* No destructor defined for COMMA */
break;
case 171:
#line 527 "parse.y"
{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);}
#line 2927 "parse.c"
break;
case 172:
#line 535 "parse.y"
{yygotominor.yy242 = yymsp[-1].minor.yy242; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
#line 2932 "parse.c"
break;
case 173:
#line 536 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_NULL, 0, 0, &yymsp[0].minor.yy0);}
#line 2937 "parse.c"
break;
case 174:
#line 537 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
#line 2942 "parse.c"
break;
case 175:
#line 538 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
#line 2947 "parse.c"
break;
case 176:
#line 539 "parse.y"
{
Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298);
yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp2, 0);
}
#line 2956 "parse.c"
/* No destructor defined for DOT */
break;
case 177:
#line 544 "parse.y"
{
Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-4].minor.yy298);
Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298);
Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298);
Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0);
yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp4, 0);
}
#line 2968 "parse.c"
/* No destructor defined for DOT */
/* No destructor defined for DOT */
break;
case 178:
#line 551 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_INTEGER, 0, 0, &yymsp[0].minor.yy0);}
#line 2975 "parse.c"
break;
case 179:
#line 552 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_FLOAT, 0, 0, &yymsp[0].minor.yy0);}
#line 2980 "parse.c"
break;
case 180:
#line 553 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_STRING, 0, 0, &yymsp[0].minor.yy0);}
#line 2985 "parse.c"
break;
case 181:
#line 554 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_VARIABLE, 0, 0, &yymsp[0].minor.yy0);
if( yygotominor.yy242 ) yygotominor.yy242->iTable = ++pParse->nVar;
}
#line 2993 "parse.c"
break;
case 182:
#line 558 "parse.y"
{
yygotominor.yy242 = sqliteExprFunction(yymsp[-1].minor.yy322, &yymsp[-3].minor.yy0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
#line 3001 "parse.c"
/* No destructor defined for LP */
break;
case 183:
#line 562 "parse.y"
{
yygotominor.yy242 = sqliteExprFunction(0, &yymsp[-3].minor.yy0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
#line 3010 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for STAR */
break;
case 184:
#line 566 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_AND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3017 "parse.c"
/* No destructor defined for AND */
break;
case 185:
#line 567 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_OR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3023 "parse.c"
/* No destructor defined for OR */
break;
case 186:
#line 568 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_LT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3029 "parse.c"
/* No destructor defined for LT */
break;
case 187:
#line 569 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_GT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3035 "parse.c"
/* No destructor defined for GT */
break;
case 188:
#line 570 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_LE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3041 "parse.c"
/* No destructor defined for LE */
break;
case 189:
#line 571 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_GE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3047 "parse.c"
/* No destructor defined for GE */
break;
case 190:
#line 572 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_NE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3053 "parse.c"
/* No destructor defined for NE */
break;
case 191:
#line 573 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_EQ, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3059 "parse.c"
/* No destructor defined for EQ */
break;
case 192:
#line 574 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_BITAND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3065 "parse.c"
/* No destructor defined for BITAND */
break;
case 193:
#line 575 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_BITOR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3071 "parse.c"
/* No destructor defined for BITOR */
break;
case 194:
#line 576 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_LSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3077 "parse.c"
/* No destructor defined for LSHIFT */
break;
case 195:
#line 577 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_RSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3083 "parse.c"
/* No destructor defined for RSHIFT */
break;
case 196:
#line 578 "parse.y"
{
ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
pList = sqliteExprListAppend(pList, yymsp[-2].minor.yy242, 0);
yygotominor.yy242 = sqliteExprFunction(pList, 0);
if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372;
sqliteExprSpan(yygotominor.yy242, &yymsp[-2].minor.yy242->span, &yymsp[0].minor.yy242->span);
}
#line 3095 "parse.c"
break;
case 197:
#line 585 "parse.y"
{
ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
pList = sqliteExprListAppend(pList, yymsp[-3].minor.yy242, 0);
yygotominor.yy242 = sqliteExprFunction(pList, 0);
if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372;
yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy242->span);
}
#line 3107 "parse.c"
/* No destructor defined for NOT */
break;
case 198:
#line 594 "parse.y"
{yygotominor.yy372 = TK_LIKE;}
#line 3113 "parse.c"
/* No destructor defined for LIKE */
break;
case 199:
#line 595 "parse.y"
{yygotominor.yy372 = TK_GLOB;}
#line 3119 "parse.c"
/* No destructor defined for GLOB */
break;
case 200:
#line 596 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_PLUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3125 "parse.c"
/* No destructor defined for PLUS */
break;
case 201:
#line 597 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_MINUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3131 "parse.c"
/* No destructor defined for MINUS */
break;
case 202:
#line 598 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_STAR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3137 "parse.c"
/* No destructor defined for STAR */
break;
case 203:
#line 599 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_SLASH, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3143 "parse.c"
/* No destructor defined for SLASH */
break;
case 204:
#line 600 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_REM, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3149 "parse.c"
/* No destructor defined for REM */
break;
case 205:
#line 601 "parse.y"
{yygotominor.yy242 = sqliteExpr(TK_CONCAT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
#line 3155 "parse.c"
/* No destructor defined for CONCAT */
break;
case 206:
#line 602 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-1].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3164 "parse.c"
break;
case 207:
#line 606 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-2].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3172 "parse.c"
/* No destructor defined for IS */
break;
case 208:
#line 610 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-1].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3181 "parse.c"
break;
case 209:
#line 614 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-2].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3189 "parse.c"
/* No destructor defined for NOT */
break;
case 210:
#line 618 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-3].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3198 "parse.c"
/* No destructor defined for IS */
/* No destructor defined for NOT */
break;
case 211:
#line 622 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_NOT, yymsp[0].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
}
#line 3208 "parse.c"
break;
case 212:
#line 626 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_BITNOT, yymsp[0].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
}
#line 3216 "parse.c"
break;
case 213:
#line 630 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_UMINUS, yymsp[0].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
}
#line 3224 "parse.c"
break;
case 214:
#line 634 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_UPLUS, yymsp[0].minor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
}
#line 3232 "parse.c"
break;
case 215:
#line 638 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_SELECT, 0, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
#line 3241 "parse.c"
break;
case 216:
#line 643 "parse.y"
{
ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-4].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pList = pList;
sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy242->span);
}
#line 3252 "parse.c"
/* No destructor defined for BETWEEN */
/* No destructor defined for AND */
break;
case 217:
#line 650 "parse.y"
{
ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-5].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pList = pList;
yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy242->span);
}
#line 3266 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for BETWEEN */
/* No destructor defined for AND */
break;
case 218:
#line 658 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3278 "parse.c"
/* No destructor defined for IN */
/* No destructor defined for LP */
break;
case 219:
#line 663 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3289 "parse.c"
/* No destructor defined for IN */
/* No destructor defined for LP */
break;
case 220:
#line 668 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3301 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for IN */
/* No destructor defined for LP */
break;
case 221:
#line 674 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
}
#line 3314 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for IN */
/* No destructor defined for LP */
break;
case 222:
#line 680 "parse.y"
{
SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-3].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298);
}
#line 3327 "parse.c"
/* No destructor defined for IN */
break;
case 223:
#line 686 "parse.y"
{
SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298);
}
#line 3339 "parse.c"
/* No destructor defined for NOT */
/* No destructor defined for IN */
break;
case 224:
#line 696 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_CASE, yymsp[-3].minor.yy242, yymsp[-1].minor.yy242, 0);
if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-2].minor.yy322;
sqliteExprSpan(yygotominor.yy242, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
}
#line 3350 "parse.c"
break;
case 225:
#line 703 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322, yymsp[-2].minor.yy242, 0);
yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
}
#line 3358 "parse.c"
/* No destructor defined for WHEN */
/* No destructor defined for THEN */
break;
case 226:
#line 707 "parse.y"
{
yygotominor.yy322 = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
}
#line 3368 "parse.c"
/* No destructor defined for WHEN */
/* No destructor defined for THEN */
break;
case 227:
#line 712 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 3375 "parse.c"
/* No destructor defined for ELSE */
break;
case 228:
#line 713 "parse.y"
{yygotominor.yy242 = 0;}
#line 3381 "parse.c"
break;
case 229:
#line 715 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 3386 "parse.c"
break;
case 230:
#line 716 "parse.y"
{yygotominor.yy242 = 0;}
#line 3391 "parse.c"
break;
case 231:
#line 724 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);}
#line 3396 "parse.c"
/* No destructor defined for COMMA */
break;
case 232:
#line 725 "parse.y"
{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);}
#line 3402 "parse.c"
break;
case 233:
#line 726 "parse.y"
{yygotominor.yy242 = yymsp[0].minor.yy242;}
#line 3407 "parse.c"
break;
case 234:
#line 727 "parse.y"
{yygotominor.yy242 = 0;}
#line 3412 "parse.c"
break;
case 235:
#line 732 "parse.y"
{
SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-5].minor.yy298, &yymsp[-4].minor.yy298);
if( yymsp[-9].minor.yy372!=OE_None ) yymsp[-9].minor.yy372 = yymsp[0].minor.yy372;
if( yymsp[-9].minor.yy372==OE_Default) yymsp[-9].minor.yy372 = OE_Abort;
sqliteCreateIndex(pParse, &yymsp[-7].minor.yy298, pSrc, yymsp[-2].minor.yy320, yymsp[-9].minor.yy372, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
}
#line 3422 "parse.c"
/* No destructor defined for INDEX */
/* No destructor defined for ON */
/* No destructor defined for LP */
break;
case 236:
#line 740 "parse.y"
{ yygotominor.yy372 = OE_Abort; }
#line 3430 "parse.c"
/* No destructor defined for UNIQUE */
break;
case 237:
#line 741 "parse.y"
{ yygotominor.yy372 = OE_None; }
#line 3436 "parse.c"
break;
case 238:
#line 749 "parse.y"
{yygotominor.yy320 = 0;}
#line 3441 "parse.c"
break;
case 239:
#line 750 "parse.y"
{yygotominor.yy320 = yymsp[-1].minor.yy320;}
#line 3446 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 240:
#line 751 "parse.y"
{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);}
#line 3453 "parse.c"
/* No destructor defined for COMMA */
break;
case 241:
#line 752 "parse.y"
{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);}
#line 3459 "parse.c"
break;
case 242:
#line 753 "parse.y"
{yygotominor.yy298 = yymsp[-1].minor.yy298;}
#line 3464 "parse.c"
/* No destructor defined for sortorder */
break;
case 243:
#line 758 "parse.y"
{
sqliteDropIndex(pParse, sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298));
}
#line 3472 "parse.c"
/* No destructor defined for DROP */
/* No destructor defined for INDEX */
break;
case 244:
#line 766 "parse.y"
{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298),&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0,yymsp[-7].minor.yy372);}
#line 3479 "parse.c"
/* No destructor defined for COPY */
/* No destructor defined for FROM */
/* No destructor defined for USING */
/* No destructor defined for DELIMITERS */
break;
case 245:
#line 768 "parse.y"
{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298),&yymsp[0].minor.yy298,0,yymsp[-4].minor.yy372);}
#line 3488 "parse.c"
/* No destructor defined for COPY */
/* No destructor defined for FROM */
break;
case 246:
#line 772 "parse.y"
{sqliteVacuum(pParse,0);}
#line 3495 "parse.c"
/* No destructor defined for VACUUM */
break;
case 247:
#line 773 "parse.y"
{sqliteVacuum(pParse,&yymsp[0].minor.yy298);}
#line 3501 "parse.c"
/* No destructor defined for VACUUM */
break;
case 248:
#line 777 "parse.y"
{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);}
#line 3507 "parse.c"
/* No destructor defined for PRAGMA */
/* No destructor defined for EQ */
break;
case 249:
#line 778 "parse.y"
{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy0,0);}
#line 3514 "parse.c"
/* No destructor defined for PRAGMA */
/* No destructor defined for EQ */
break;
case 250:
#line 779 "parse.y"
{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);}
#line 3521 "parse.c"
/* No destructor defined for PRAGMA */
/* No destructor defined for EQ */
break;
case 251:
#line 780 "parse.y"
{sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,1);}
#line 3528 "parse.c"
/* No destructor defined for PRAGMA */
/* No destructor defined for EQ */
break;
case 252:
#line 781 "parse.y"
{sqlitePragma(pParse,&yymsp[-3].minor.yy298,&yymsp[-1].minor.yy298,0);}
#line 3535 "parse.c"
/* No destructor defined for PRAGMA */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 253:
#line 782 "parse.y"
{sqlitePragma(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298,0);}
#line 3543 "parse.c"
/* No destructor defined for PRAGMA */
break;
case 254:
#line 783 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy298;}
#line 3549 "parse.c"
/* No destructor defined for plus_opt */
break;
case 255:
#line 784 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy298;}
#line 3555 "parse.c"
/* No destructor defined for MINUS */
break;
case 256:
#line 785 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 3561 "parse.c"
break;
case 257:
#line 786 "parse.y"
{yygotominor.yy298 = yymsp[0].minor.yy0;}
#line 3566 "parse.c"
break;
case 258:
/* No destructor defined for PLUS */
break;
case 259:
break;
case 260:
#line 792 "parse.y"
{
Token all;
all.z = yymsp[-4].minor.yy0.z;
all.n = (yymsp[0].minor.yy0.z - yymsp[-4].minor.yy0.z) + yymsp[0].minor.yy0.n;
sqliteFinishTrigger(pParse, yymsp[-1].minor.yy19, &all);
}
#line 3581 "parse.c"
/* No destructor defined for trigger_decl */
/* No destructor defined for BEGIN */
break;
case 261:
#line 800 "parse.y"
{
SrcList *pTab = sqliteSrcListAppend(0, &yymsp[-3].minor.yy298, &yymsp[-2].minor.yy298);
sqliteBeginTrigger(pParse, &yymsp[-7].minor.yy298, yymsp[-6].minor.yy372, yymsp[-5].minor.yy290.a, yymsp[-5].minor.yy290.b, pTab, yymsp[-1].minor.yy372, yymsp[0].minor.yy182, yymsp[-9].minor.yy372);
}
#line 3591 "parse.c"
/* No destructor defined for TRIGGER */
/* No destructor defined for ON */
break;
case 262:
#line 806 "parse.y"
{ yygotominor.yy372 = TK_BEFORE; }
#line 3598 "parse.c"
/* No destructor defined for BEFORE */
break;
case 263:
#line 807 "parse.y"
{ yygotominor.yy372 = TK_AFTER; }
#line 3604 "parse.c"
/* No destructor defined for AFTER */
break;
case 264:
#line 808 "parse.y"
{ yygotominor.yy372 = TK_INSTEAD;}
#line 3610 "parse.c"
/* No destructor defined for INSTEAD */
/* No destructor defined for OF */
break;
case 265:
#line 809 "parse.y"
{ yygotominor.yy372 = TK_BEFORE; }
#line 3617 "parse.c"
break;
case 266:
#line 813 "parse.y"
{ yygotominor.yy290.a = TK_DELETE; yygotominor.yy290.b = 0; }
#line 3622 "parse.c"
/* No destructor defined for DELETE */
break;
case 267:
#line 814 "parse.y"
{ yygotominor.yy290.a = TK_INSERT; yygotominor.yy290.b = 0; }
#line 3628 "parse.c"
/* No destructor defined for INSERT */
break;
case 268:
#line 815 "parse.y"
{ yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = 0;}
#line 3634 "parse.c"
/* No destructor defined for UPDATE */
break;
case 269:
#line 816 "parse.y"
{yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = yymsp[0].minor.yy320; }
#line 3640 "parse.c"
/* No destructor defined for UPDATE */
/* No destructor defined for OF */
break;
case 270:
#line 819 "parse.y"
{ yygotominor.yy372 = TK_ROW; }
#line 3647 "parse.c"
break;
case 271:
#line 820 "parse.y"
{ yygotominor.yy372 = TK_ROW; }
#line 3652 "parse.c"
/* No destructor defined for FOR */
/* No destructor defined for EACH */
/* No destructor defined for ROW */
break;
case 272:
#line 821 "parse.y"
{ yygotominor.yy372 = TK_STATEMENT; }
#line 3660 "parse.c"
/* No destructor defined for FOR */
/* No destructor defined for EACH */
/* No destructor defined for STATEMENT */
break;
case 273:
#line 824 "parse.y"
{ yygotominor.yy182 = 0; }
#line 3668 "parse.c"
break;
case 274:
#line 825 "parse.y"
{ yygotominor.yy182 = yymsp[0].minor.yy242; }
#line 3673 "parse.c"
/* No destructor defined for WHEN */
break;
case 275:
#line 829 "parse.y"
{
yymsp[-2].minor.yy19->pNext = yymsp[0].minor.yy19;
yygotominor.yy19 = yymsp[-2].minor.yy19;
}
#line 3682 "parse.c"
/* No destructor defined for SEMI */
break;
case 276:
#line 833 "parse.y"
{ yygotominor.yy19 = 0; }
#line 3688 "parse.c"
break;
case 277:
#line 839 "parse.y"
{ yygotominor.yy19 = sqliteTriggerUpdateStep(&yymsp[-3].minor.yy298, yymsp[-1].minor.yy322, yymsp[0].minor.yy242, yymsp[-4].minor.yy372); }
#line 3693 "parse.c"
/* No destructor defined for UPDATE */
/* No destructor defined for SET */
break;
case 278:
#line 844 "parse.y"
{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-5].minor.yy298, yymsp[-4].minor.yy320, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy372);}
#line 3700 "parse.c"
/* No destructor defined for INTO */
/* No destructor defined for VALUES */
/* No destructor defined for LP */
/* No destructor defined for RP */
break;
case 279:
#line 847 "parse.y"
{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-2].minor.yy298, yymsp[-1].minor.yy320, 0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);}
#line 3709 "parse.c"
/* No destructor defined for INTO */
break;
case 280:
#line 851 "parse.y"
{yygotominor.yy19 = sqliteTriggerDeleteStep(&yymsp[-1].minor.yy298, yymsp[0].minor.yy242);}
#line 3715 "parse.c"
/* No destructor defined for DELETE */
/* No destructor defined for FROM */
break;
case 281:
#line 854 "parse.y"
{yygotominor.yy19 = sqliteTriggerSelectStep(yymsp[0].minor.yy179); }
#line 3722 "parse.c"
break;
case 282:
#line 857 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, 0);
yygotominor.yy242->iColumn = OE_Ignore;
sqliteExprSpan(yygotominor.yy242, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
#line 3731 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for IGNORE */
break;
case 283:
#line 862 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
yygotominor.yy242->iColumn = OE_Rollback;
sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
#line 3742 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for ROLLBACK */
/* No destructor defined for COMMA */
break;
case 284:
#line 867 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
yygotominor.yy242->iColumn = OE_Abort;
sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
#line 3754 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for ABORT */
/* No destructor defined for COMMA */
break;
case 285:
#line 872 "parse.y"
{
yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298);
yygotominor.yy242->iColumn = OE_Fail;
sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
#line 3766 "parse.c"
/* No destructor defined for LP */
/* No destructor defined for FAIL */
/* No destructor defined for COMMA */
break;
case 286:
#line 879 "parse.y"
{
sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298));
}
#line 3776 "parse.c"
/* No destructor defined for DROP */
/* No destructor defined for TRIGGER */
break;
case 287:
#line 884 "parse.y"
{
sqliteAttach(pParse, &yymsp[-3].minor.yy298, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298);
}
#line 3785 "parse.c"
/* No destructor defined for ATTACH */
/* No destructor defined for database_kw_opt */
/* No destructor defined for AS */
break;
case 288:
#line 888 "parse.y"
{ yygotominor.yy298 = yymsp[0].minor.yy298; }
#line 3793 "parse.c"
/* No destructor defined for USING */
break;
case 289:
#line 889 "parse.y"
{ yygotominor.yy298.z = 0; yygotominor.yy298.n = 0; }
#line 3799 "parse.c"
break;
case 290:
/* No destructor defined for DATABASE */
break;
case 291:
break;
case 292:
#line 895 "parse.y"
{
sqliteDetach(pParse, &yymsp[0].minor.yy298);
}
#line 3811 "parse.c"
/* No destructor defined for DETACH */
/* No destructor defined for database_kw_opt */
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yypParser,yygoto);
if( yyact < YYNSTATE ){
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}else if( yyact == YYNSTATE + YYNRULE + 1 ){
yy_accept(yypParser);
}
}
| parse.c | 1848 |
STATIC VOID | yy_parse_failed( yyParser *yypParser )
static void yy_parse_failed(
yyParser *yypParser /* The parser */
){
sqliteParserARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
| parse.c | 3827 |
STATIC VOID | yy_syntax_error( yyParser *yypParser, int yymajor, YYMINORTYPE yyminor )
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor, /* The major type of the error token */
YYMINORTYPE yyminor /* The minor type of the error token */
){
sqliteParserARG_FETCH;
#define TOKEN (yyminor.yy0)
#line 23 "parse.y"
if( pParse->zErrMsg==0 ){
if( TOKEN.z[0] ){
sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
}else{
sqliteErrorMsg(pParse, "incomplete SQL statement");
}
}
#line 3865 "parse.c"
sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
| parse.c | 3845 |
STATIC VOID | yy_accept( yyParser *yypParser )
static void yy_accept(
yyParser *yypParser /* The parser */
){
sqliteParserARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser accepts */
sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
| parse.c | 3869 |
VOID | sqliteParser( void *yyp, int yymajor, sqliteParserTOKENTYPE yyminor sqliteParserARG_PDECL )
void sqliteParser(
void *yyp, /* The parser */
int yymajor, /* The major token code number */
sqliteParserTOKENTYPE yyminor /* The value for the token */
sqliteParserARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
int yyendofinput; /* True if we are at the end of input */
int yyerrorhit = 0; /* True if yymajor has invoked an error */
yyParser *yypParser; /* The parser */
/* (re)initialize the parser, if necessary */
yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){
if( yymajor==0 ) return;
yypParser->yyidx = 0;
yypParser->yyerrcnt = -1;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
}
yyminorunion.yy0 = yyminor;
yyendofinput = (yymajor==0);
sqliteParserARG_STORE;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
}
#endif
do{
yyact = yy_find_shift_action(yypParser,yymajor);
if( yyactyyerrcnt--;
if( yyendofinput && yypParser->yyidx>=0 ){
yymajor = 0;
}else{
yymajor = YYNOCODE;
}
}else if( yyact < YYNSTATE + YYNRULE ){
yy_reduce(yypParser,yyact-YYNSTATE);
}else if( yyact == YY_ERROR_ACTION ){
int yymx;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
}
#endif
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
** * Call the %syntax_error function.
**
** * Begin popping the stack until we enter a state where
** it is legal to shift the error symbol, then shift
** the error symbol.
**
** * Set the error count to three.
**
** * Begin accepting and shifting new tokens. No new error
** processing will occur until three tokens have been
** shifted successfully.
**
*/
if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yymx = yypParser->yystack[yypParser->yyidx].major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
yy_destructor(yymajor,&yyminorunion);
yymajor = YYNOCODE;
}else{
while(
yypParser->yyidx >= 0 &&
yymx != YYERRORSYMBOL &&
(yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yyidx < 0 || yymajor==0 ){
yy_destructor(yymajor,&yyminorunion);
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
u2.YYERRSYMDT = 0;
yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
}
}
yypParser->yyerrcnt = 3;
yyerrorhit = 1;
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
** * Report an error message, and throw away the input token.
**
** * If the input token is $, then fail the parse.
**
** As before, subsequent error messages are suppressed until
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yypParser->yyerrcnt = 3;
yy_destructor(yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
#endif
}else{
yy_accept(yypParser);
yymajor = YYNOCODE;
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
return;
}
| parse.c | 3887 |
pragma.c |
Type | Function | Source | Line |
STATIC INT | getBoolean(const char *z)
static int getBoolean(const char *z){
static char *azTrue[] = { "yes", "on", "true" };
int i;
if( z[0]==0 ) return 0;
if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
return atoi(z);
}
for(i=0; ipragma.c | 19 | |
STATIC INT | getSafetyLevel(char *z)
static int getSafetyLevel(char *z){
static const struct {
const char *zWord;
int val;
} aKey[] = {
{ "no", 0 },
{ "off", 0 },
{ "false", 0 },
{ "yes", 1 },
{ "on", 1 },
{ "true", 1 },
{ "full", 2 },
};
int i;
if( z[0]==0 ) return 1;
if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
return atoi(z);
}
for(i=0; ipragma.c | 35 | |
STATIC INT | getTempStore(const char *z)
static int getTempStore(const char *z){
if( z[0]>='0' && z[0]<='2' ){
return z[0] - '0';
}else if( sqliteStrICmp(z, "file")==0 ){
return 1;
}else if( sqliteStrICmp(z, "memory")==0 ){
return 2;
}else{
return 0;
}
}
| pragma.c | 69 |
STATIC INT | changeTempStorage(Parse *pParse, const char *zStorageType)
static int changeTempStorage(Parse *pParse, const char *zStorageType){
int ts = getTempStore(zStorageType);
sqlite *db = pParse->db;
if( db->temp_store==ts ) return SQLITE_OK;
if( db->aDb[1].pBt!=0 ){
if( db->flags & SQLITE_InTrans ){
sqliteErrorMsg(pParse, "temporary storage cannot be changed "
"from within a transaction");
return SQLITE_ERROR;
}
sqliteBtreeClose(db->aDb[1].pBt);
db->aDb[1].pBt = 0;
sqliteResetInternalSchema(db, 0);
}
db->temp_store = ts;
return SQLITE_OK;
}
| pragma.c | 86 |
STATIC INT | flagPragma(Parse *pParse, const char *zLeft, const char *zRight)
static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
static const struct {
const char *zName; /* Name of the pragma */
int mask; /* Mask for the db->flags value */
} aPragma[] = {
{ "vdbe_trace", SQLITE_VdbeTrace },
{ "full_column_names", SQLITE_FullColNames },
{ "short_column_names", SQLITE_ShortColNames },
{ "show_datatypes", SQLITE_ReportTypes },
{ "count_changes", SQLITE_CountRows },
{ "empty_result_callbacks", SQLITE_NullCallback },
};
int i;
for(i=0; idb;
Vdbe *v;
if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
OP_Callback, 1, 0,
0);
}else if( getBoolean(zRight) ){
db->flags |= aPragma[i].mask;
}else{
db->flags &= ~aPragma[i].mask;
}
return 1;
}
}
return 0;
}
| pragma.c | 109 |
VOID | sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag)
void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
char *zLeft = 0;
char *zRight = 0;
sqlite *db = pParse->db;
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return;
zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
sqliteDequote(zLeft);
if( minusFlag ){
zRight = 0;
sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
}else{
zRight = sqliteStrNDup(pRight->z, pRight->n);
sqliteDequote(zRight);
}
if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
sqliteFree(zLeft);
sqliteFree(zRight);
return;
}
/*
** PRAGMA default_cache_size
** PRAGMA default_cache_size=N
**
** The first form reports the current persistent setting for the
** page cache size. The value returned is the maximum number of
** pages in the page cache. The second form sets both the current
** page cache size value and the persistent page cache size value
** stored in the database file.
**
** The default cache size is stored in meta-value 2 of page 1 of the
** database file. The cache size is actually the absolute value of
** this memory location. The sign of meta-value 2 determines the
** synchronous setting. A negative value means synchronous is off
** and a positive value means synchronous is on.
*/
if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
static VdbeOpList getCacheSize[] = {
{ OP_ReadCookie, 0, 2, 0},
{ OP_AbsValue, 0, 0, 0},
{ OP_Dup, 0, 0, 0},
{ OP_Integer, 0, 0, 0},
{ OP_Ne, 0, 6, 0},
{ OP_Integer, 0, 0, 0}, /* 5 */
{ OP_ColumnName, 0, 1, "cache_size"},
{ OP_Callback, 1, 0, 0},
};
int addr;
if( pRight->z==pLeft->z ){
addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
}else{
int size = atoi(zRight);
if( size<0 ) size = -size;
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteVdbeAddOp(v, OP_Integer, size, 0);
sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
sqliteVdbeAddOp(v, OP_Negative, 0, 0);
sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
sqliteEndWriteOperation(pParse);
db->cache_size = db->cache_size<0 ? -size : size;
sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
}
}else
/*
** PRAGMA cache_size
** PRAGMA cache_size=N
**
** The first form reports the current local setting for the
** page cache size. The local setting can be different from
** the persistent cache size value that is stored in the database
** file itself. The value returned is the maximum number of
** pages in the page cache. The second form sets the local
** page cache size value. It does not change the persistent
** cache size stored on the disk so the cache size will revert
** to its default value when the database is closed and reopened.
** N should be a positive integer.
*/
if( sqliteStrICmp(zLeft,"cache_size")==0 ){
static VdbeOpList getCacheSize[] = {
{ OP_ColumnName, 0, 1, "cache_size"},
{ OP_Callback, 1, 0, 0},
};
if( pRight->z==pLeft->z ){
int size = db->cache_size;;
if( size<0 ) size = -size;
sqliteVdbeAddOp(v, OP_Integer, size, 0);
sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
}else{
int size = atoi(zRight);
if( size<0 ) size = -size;
if( db->cache_size<0 ) size = -size;
db->cache_size = size;
sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
}
}else
/*
** PRAGMA default_synchronous
** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
**
** The first form returns the persistent value of the "synchronous" setting
** that is stored in the database. This is the synchronous setting that
** is used whenever the database is opened unless overridden by a separate
** "synchronous" pragma. The second form changes the persistent and the
** local synchronous setting to the value given.
**
** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
** to make sure data is committed to disk. Write operations are very fast,
** but a power failure can leave the database in an inconsistent state.
** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
** make sure data is being written to disk. The risk of corruption due to
** a power loss in this mode is negligible but non-zero. If synchronous
** is FULL, extra fsync()s occur to reduce the risk of corruption to near
** zero, but with a write performance penalty. The default mode is NORMAL.
*/
if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
static VdbeOpList getSync[] = {
{ OP_ColumnName, 0, 1, "synchronous"},
{ OP_ReadCookie, 0, 3, 0},
{ OP_Dup, 0, 0, 0},
{ OP_If, 0, 0, 0}, /* 3 */
{ OP_ReadCookie, 0, 2, 0},
{ OP_Integer, 0, 0, 0},
{ OP_Lt, 0, 5, 0},
{ OP_AddImm, 1, 0, 0},
{ OP_Callback, 1, 0, 0},
{ OP_Halt, 0, 0, 0},
{ OP_AddImm, -1, 0, 0}, /* 10 */
{ OP_Callback, 1, 0, 0}
};
if( pRight->z==pLeft->z ){
int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
sqliteVdbeChangeP2(v, addr+3, addr+10);
}else{
int addr;
int size = db->cache_size;
if( size<0 ) size = -size;
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
db->safety_level = getSafetyLevel(zRight)+1;
if( db->safety_level==1 ){
sqliteVdbeAddOp(v, OP_Negative, 0, 0);
size = -size;
}
sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
sqliteEndWriteOperation(pParse);
db->cache_size = size;
sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
}
}else
/*
** PRAGMA synchronous
** PRAGMA synchronous=OFF|ON|NORMAL|FULL
**
** Return or set the local value of the synchronous flag. Changing
** the local value does not make changes to the disk file and the
** default value will be restored the next time the database is
** opened.
*/
if( sqliteStrICmp(zLeft,"synchronous")==0 ){
static VdbeOpList getSync[] = {
{ OP_ColumnName, 0, 1, "synchronous"},
{ OP_Callback, 1, 0, 0},
};
if( pRight->z==pLeft->z ){
sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
}else{
int size = db->cache_size;
if( size<0 ) size = -size;
db->safety_level = getSafetyLevel(zRight)+1;
if( db->safety_level==1 ) size = -size;
db->cache_size = size;
sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
}
}else
#ifndef NDEBUG
if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
if( getBoolean(zRight) ){
always_code_trigger_setup = 1;
}else{
always_code_trigger_setup = 0;
}
}else
#endif
if( flagPragma(pParse, zLeft, zRight) ){
/* The flagPragma() call also generates any necessary code */
}else
if( sqliteStrICmp(zLeft, "table_info")==0 ){
Table *pTab;
pTab = sqliteFindTable(db, zRight, 0);
if( pTab ){
static VdbeOpList tableInfoPreface[] = {
{ OP_ColumnName, 0, 0, "cid"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 0, "type"},
{ OP_ColumnName, 3, 0, "notnull"},
{ OP_ColumnName, 4, 0, "dflt_value"},
{ OP_ColumnName, 5, 1, "pk"},
};
int i;
sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
sqliteViewGetColumnNames(pParse, pTab);
for(i=0; inCol; i++){
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
sqliteVdbeOp3(v, OP_String, 0, 0,
pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
sqliteVdbeOp3(v, OP_String, 0, 0,
pTab->aCol[i].zDflt, P3_STATIC);
sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
sqliteVdbeAddOp(v, OP_Callback, 6, 0);
}
}
}else
if( sqliteStrICmp(zLeft, "index_info")==0 ){
Index *pIdx;
Table *pTab;
pIdx = sqliteFindIndex(db, zRight, 0);
if( pIdx ){
static VdbeOpList tableInfoPreface[] = {
{ OP_ColumnName, 0, 0, "seqno"},
{ OP_ColumnName, 1, 0, "cid"},
{ OP_ColumnName, 2, 1, "name"},
};
int i;
pTab = pIdx->pTable;
sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
for(i=0; inColumn; i++){
int cnum = pIdx->aiColumn[i];
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
assert( pTab->nCol>cnum );
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
sqliteVdbeAddOp(v, OP_Callback, 3, 0);
}
}
}else
if( sqliteStrICmp(zLeft, "index_list")==0 ){
Index *pIdx;
Table *pTab;
pTab = sqliteFindTable(db, zRight, 0);
if( pTab ){
v = sqliteGetVdbe(pParse);
pIdx = pTab->pIndex;
}
if( pTab && pIdx ){
int i = 0;
static VdbeOpList indexListPreface[] = {
{ OP_ColumnName, 0, 0, "seq"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 1, "unique"},
};
sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
while(pIdx){
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
sqliteVdbeAddOp(v, OP_Callback, 3, 0);
++i;
pIdx = pIdx->pNext;
}
}
}else
if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
FKey *pFK;
Table *pTab;
pTab = sqliteFindTable(db, zRight, 0);
if( pTab ){
v = sqliteGetVdbe(pParse);
pFK = pTab->pFKey;
}
if( pTab && pFK ){
int i = 0;
static VdbeOpList indexListPreface[] = {
{ OP_ColumnName, 0, 0, "id"},
{ OP_ColumnName, 1, 0, "seq"},
{ OP_ColumnName, 2, 0, "table"},
{ OP_ColumnName, 3, 0, "from"},
{ OP_ColumnName, 4, 1, "to"},
};
sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
while(pFK){
int j;
for(j=0; jnCol; j++){
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeAddOp(v, OP_Integer, j, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
sqliteVdbeOp3(v, OP_String, 0, 0,
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
sqliteVdbeAddOp(v, OP_Callback, 5, 0);
}
++i;
pFK = pFK->pNextFrom;
}
}
}else
if( sqliteStrICmp(zLeft, "database_list")==0 ){
int i;
static VdbeOpList indexListPreface[] = {
{ OP_ColumnName, 0, 0, "seq"},
{ OP_ColumnName, 1, 0, "name"},
{ OP_ColumnName, 2, 1, "file"},
};
sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
for(i=0; inDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zName!=0 );
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
sqliteVdbeOp3(v, OP_String, 0, 0,
sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
sqliteVdbeAddOp(v, OP_Callback, 3, 0);
}
}else
/*
** PRAGMA temp_store
** PRAGMA temp_store = "default"|"memory"|"file"
**
** Return or set the local value of the temp_store flag. Changing
** the local value does not make changes to the disk file and the default
** value will be restored the next time the database is opened.
**
** Note that it is possible for the library compile-time options to
** override this setting
*/
if( sqliteStrICmp(zLeft, "temp_store")==0 ){
static VdbeOpList getTmpDbLoc[] = {
{ OP_ColumnName, 0, 1, "temp_store"},
{ OP_Callback, 1, 0, 0},
};
if( pRight->z==pLeft->z ){
sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
}else{
changeTempStorage(pParse, zRight);
}
}else
/*
** PRAGMA default_temp_store
** PRAGMA default_temp_store = "default"|"memory"|"file"
**
** Return or set the value of the persistent temp_store flag. Any
** change does not take effect until the next time the database is
** opened.
**
** Note that it is possible for the library compile-time options to
** override this setting
*/
if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){
static VdbeOpList getTmpDbLoc[] = {
{ OP_ColumnName, 0, 1, "temp_store"},
{ OP_ReadCookie, 0, 5, 0},
{ OP_Callback, 1, 0, 0}};
if( pRight->z==pLeft->z ){
sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
}else{
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
sqliteEndWriteOperation(pParse);
}
}else
#ifndef NDEBUG
if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
extern void sqliteParserTrace(FILE*, char *);
if( getBoolean(zRight) ){
sqliteParserTrace(stdout, "parser: ");
}else{
sqliteParserTrace(0, 0);
}
}else
#endif
if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
int i, j, addr;
/* Code that initializes the integrity check program. Set the
** error count 0
*/
static VdbeOpList initCode[] = {
{ OP_Integer, 0, 0, 0},
{ OP_MemStore, 0, 1, 0},
{ OP_ColumnName, 0, 1, "integrity_check"},
};
/* Code to do an BTree integrity check on a single database file.
*/
static VdbeOpList checkDb[] = {
{ OP_SetInsert, 0, 0, "2"},
{ OP_Integer, 0, 0, 0}, /* 1 */
{ OP_OpenRead, 0, 2, 0},
{ OP_Rewind, 0, 7, 0}, /* 3 */
{ OP_Column, 0, 3, 0}, /* 4 */
{ OP_SetInsert, 0, 0, 0},
{ OP_Next, 0, 4, 0}, /* 6 */
{ OP_IntegrityCk, 0, 0, 0}, /* 7 */
{ OP_Dup, 0, 1, 0},
{ OP_String, 0, 0, "ok"},
{ OP_StrEq, 0, 12, 0}, /* 10 */
{ OP_MemIncr, 0, 0, 0},
{ OP_String, 0, 0, "*** in database "},
{ OP_String, 0, 0, 0}, /* 13 */
{ OP_String, 0, 0, " ***\n"},
{ OP_Pull, 3, 0, 0},
{ OP_Concat, 4, 1, 0},
{ OP_Callback, 1, 0, 0},
};
/* Code that appears at the end of the integrity check. If no error
** messages have been generated, output OK. Otherwise output the
** error message
*/
static VdbeOpList endCode[] = {
{ OP_MemLoad, 0, 0, 0},
{ OP_Integer, 0, 0, 0},
{ OP_Ne, 0, 0, 0}, /* 2 */
{ OP_String, 0, 0, "ok"},
{ OP_Callback, 1, 0, 0},
};
/* Initialize the VDBE program */
sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
/* Do an integrity check on each database file */
for(i=0; inDb; i++){
HashElem *x;
/* Do an integrity check of the B-Tree
*/
addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
sqliteVdbeChangeP1(v, addr+1, i);
sqliteVdbeChangeP2(v, addr+3, addr+7);
sqliteVdbeChangeP2(v, addr+6, addr+4);
sqliteVdbeChangeP2(v, addr+7, i);
sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
/* Make sure all the indices are constructed correctly.
*/
sqliteCodeVerifySchema(pParse, i);
for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
int loopTop;
if( pTab->pIndex==0 ) continue;
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pIdx->tnum==0 ) continue;
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
}
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int k, jmp2;
static VdbeOpList idxErr[] = {
{ OP_MemIncr, 0, 0, 0},
{ OP_String, 0, 0, "rowid "},
{ OP_Recno, 1, 0, 0},
{ OP_String, 0, 0, " missing from index "},
{ OP_String, 0, 0, 0}, /* 4 */
{ OP_Concat, 4, 0, 0},
{ OP_Callback, 1, 0, 0},
};
sqliteVdbeAddOp(v, OP_Recno, 1, 0);
for(k=0; knColumn; k++){
int idx = pIdx->aiColumn[k];
if( idx==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_Recno, 1, 0);
}else{
sqliteVdbeAddOp(v, OP_Column, 1, idx);
}
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
}
sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
static VdbeOpList cntIdx[] = {
{ OP_Integer, 0, 0, 0},
{ OP_MemStore, 2, 1, 0},
{ OP_Rewind, 0, 0, 0}, /* 2 */
{ OP_MemIncr, 2, 0, 0},
{ OP_Next, 0, 0, 0}, /* 4 */
{ OP_MemLoad, 1, 0, 0},
{ OP_MemLoad, 2, 0, 0},
{ OP_Eq, 0, 0, 0}, /* 7 */
{ OP_MemIncr, 0, 0, 0},
{ OP_String, 0, 0, "wrong # of entries in index "},
{ OP_String, 0, 0, 0}, /* 10 */
{ OP_Concat, 2, 0, 0},
{ OP_Callback, 1, 0, 0},
};
if( pIdx->tnum==0 ) continue;
addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
sqliteVdbeChangeP1(v, addr+2, j+2);
sqliteVdbeChangeP2(v, addr+2, addr+5);
sqliteVdbeChangeP1(v, addr+4, j+2);
sqliteVdbeChangeP2(v, addr+4, addr+3);
sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
}
}
}
addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
}else
{}
sqliteFree(zLeft);
sqliteFree(zRight);
}
| pragma.c | 148 |
printf.c |
Type | Function | Source | Line |
STATIC INT | et_getdigit(LONGDOUBLE_TYPE *val, int *cnt)
static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
int digit;
LONGDOUBLE_TYPE d;
if( (*cnt)++ >= 16 ) return '0';
digit = (int)*val;
d = digit;
digit += '0';
*val = (*val - d)*10.0;
return digit;
}
| printf.c | 137 |
STATIC INT VXPRINTF( VOID (*FUNC | (void*,const char*,int), void *arg, int useExtended, const char *fmt, va_list ap )
static int vxprintf(
void (*func)(void*,const char*,int), /* Consumer of text */
void *arg, /* First argument to the consumer */
int useExtended, /* Allow extended %-conversions */
const char *fmt, /* Format string */
va_list ap /* arguments */
){
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
int precision; /* Precision of the current field */
int length; /* Length of the field */
int idx; /* A general purpose loop counter */
int count; /* Total number of characters output */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */
unsigned long longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static char spaces[] = " ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef etNOFLOATINGPOINT
int exp; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
etByte flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
#endif
func(arg,"",0);
count = length = 0;
bufpt = 0;
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
int amt;
bufpt = (char *)fmt;
amt = 1;
while( (c=(*++fmt))!='%' && c!=0 ) amt++;
(*func)(arg,bufpt,amt);
count += amt;
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
errorflag = 1;
(*func)(arg,"%",1);
count++;
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_zeropad = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; c = 0; break;
case '+': flag_plussign = 1; c = 0; break;
case ' ': flag_blanksign = 1; c = 0; break;
case '#': flag_alternateform = 1; c = 0; break;
case '0': flag_zeropad = 1; c = 0; break;
default: break;
}
}while( c==0 && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
width = va_arg(ap,int);
if( width<0 ){
flag_leftjustify = 1;
width = -width;
}
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
width = width*10 + c - '0';
c = *++fmt;
}
}
if( width > etBUFSIZE-10 ){
width = etBUFSIZE-10;
}
/* Get the precision */
if( c=='.' ){
precision = 0;
c = *++fmt;
if( c=='*' ){
precision = va_arg(ap,int);
if( precision<0 ) precision = -precision;
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
precision = precision*10 + c - '0';
c = *++fmt;
}
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
}else{
precision = -1;
}
/* Get the conversion type modifier */
if( c=='l' ){
flag_long = 1;
c = *++fmt;
}else{
flag_long = 0;
}
/* Fetch the info entry for the field */
infop = 0;
xtype = etERROR;
for(idx=0; idxflags & FLAG_INTERN)==0 ){
xtype = infop->type;
}
break;
}
}
zExtra = 0;
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch( xtype ){
case etRADIX:
if( flag_long ) longvalue = va_arg(ap,long);
else longvalue = va_arg(ap,int);
#if 1
/* For the format %#x, the value zero is printed "0" not "0x0".
** I think this is stupid. */
if( longvalue==0 ) flag_alternateform = 0;
#else
/* More sensible: turn off the prefix for octal (to prevent "00"),
** but leave the prefix for hex. */
if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
#endif
if( infop->flags & FLAG_SIGNED ){
if( *(long*)&longvalue<0 ){
longvalue = -*(long*)&longvalue;
prefix = '-';
}else if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}else prefix = 0;
if( flag_zeropad && precisioncharset;
base = infop->base;
do{ /* Convert to ascii */
*(--bufpt) = cset[longvalue%base];
longvalue = longvalue/base;
}while( longvalue>0 );
}
length = &buf[etBUFSIZE-1]-bufpt;
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
char *pre, x;
pre = infop->prefix;
if( *bufpt!=pre[0] ){
for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
}
length = &buf[etBUFSIZE-1]-bufpt;
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
#ifndef etNOFLOATINGPOINT
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
}else{
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
if( infop->type==etGENERIC && precision>0 ) precision--;
rounder = 0.0;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
#else
/* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
#endif
if( infop->type==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
if( exp>350 || exp<-350 ){
bufpt = "NaN";
length = 3;
break;
}
}
bufpt = buf;
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
flag_exp = xtype==etEXP;
if( xtype!=etFLOAT ){
realvalue += rounder;
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
}
if( xtype==etGENERIC ){
flag_rtz = !flag_alternateform;
if( exp<-4 || exp>precision ){
xtype = etEXP;
}else{
precision = precision - exp;
xtype = etFLOAT;
}
}else{
flag_rtz = 0;
}
/*
** The "exp+precision" test causes output to be of type etEXP if
** the precision is too large to fit in buf[].
*/
nsd = 0;
if( xtype==etFLOAT && exp+precision0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
for(exp++; exp<0 && precision>0; precision--, exp++){
*(bufpt++) = '0';
}
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
*(bufpt--) = 0; /* Null terminate */
if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
}else{ /* etEXP or etGENERIC */
flag_dp = (precision>0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
*(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
bufpt--; /* point to last digit */
if( flag_rtz && flag_dp ){ /* Remove tail zeros */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
if( exp || flag_exp ){
*(bufpt++) = infop->charset[0];
if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
else { *(bufpt++) = '+'; }
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
}
}
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
length = bufpt-buf;
bufpt = buf;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
if( flag_zeropad && !flag_leftjustify && length < width){
int i;
int nPad = width - length;
for(i=width; i>=nPad; i--){
bufpt[i] = bufpt[i-nPad];
}
i = prefix!=0;
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
#endif
break;
case etSIZE:
*(va_arg(ap,int*)) = count;
length = width = 0;
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARLIT:
case etCHARX:
c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
if( precision>=0 ){
for(idx=1; idx=0 && precisionetBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if( precision>=0 && precisionz, pToken->n);
length = width = 0;
break;
}
case etSRCLIST: {
SrcList *pSrc = va_arg(ap, SrcList*);
int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k];
assert( k>=0 && knSrc );
if( pItem->zDatabase && pItem->zDatabase[0] ){
(*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
(*func)(arg, ".", 1);
}
(*func)(arg, pItem->zName, strlen(pItem->zName));
length = width = 0;
break;
}
case etERROR:
buf[0] = '%';
buf[1] = c;
errorflag = 0;
idx = 1+(c!=0);
(*func)(arg,"%",idx);
count += idx;
if( c==0 ) fmt--;
break;
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long. The field width is "width". Do
** the output.
*/
if( !flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
count += nspace;
while( nspace>=etSPACESIZE ){
(*func)(arg,spaces,etSPACESIZE);
nspace -= etSPACESIZE;
}
if( nspace>0 ) (*func)(arg,spaces,nspace);
}
}
if( length>0 ){
(*func)(arg,bufpt,length);
count += length;
}
if( flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
count += nspace;
while( nspace>=etSPACESIZE ){
(*func)(arg,spaces,etSPACESIZE);
nspace -= etSPACESIZE;
}
if( nspace>0 ) (*func)(arg,spaces,nspace);
}
}
if( zExtra ){
sqliteFree(zExtra);
}
}/* End for loop over the format string */
return errorflag ? -1 : count;
} /* End of function */
/* This structure is used to store state information about the
** write to memory that is currently in progress.
*/
struct sgMprintf {
char *zBase; /* A base allocation */
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nTotal; /* Output size if unconstrained */
int nAlloc; /* Amount of space allocated in zText */
void *(*xRealloc)(void*,int); /* Function used to realloc memory */
};
| printf.c | 164 |
STATIC VOID | mout(void *arg, const char *zNewText, int nNewChar)
static void mout(void *arg, const char *zNewText, int nNewChar){
struct sgMprintf *pM = (struct sgMprintf*)arg;
pM->nTotal += nNewChar;
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
if( pM->xRealloc==0 ){
nNewChar = pM->nAlloc - pM->nChar - 1;
}else{
pM->nAlloc = pM->nChar + nNewChar*2 + 1;
if( pM->zText==pM->zBase ){
pM->zText = pM->xRealloc(0, pM->nAlloc);
if( pM->zText && pM->nChar ){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
}
}
}
if( pM->zText ){
if( nNewChar>0 ){
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
}
pM->zText[pM->nChar] = 0;
}
}
| printf.c | 653 |
STATIC CHAR *BASE_VPRINTF( VOID *(*XREALLOC | (void*,int), int useInternal, char *zInitBuf, int nInitBuf, const char *zFormat, va_list ap )
static char *base_vprintf(
void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
int useInternal, /* Use internal %-conversions if true */
char *zInitBuf, /* Initially write here, before mallocing */
int nInitBuf, /* Size of zInitBuf[] */
const char *zFormat, /* format string */
va_list ap /* arguments */
){
struct sgMprintf sM;
sM.zBase = sM.zText = zInitBuf;
sM.nChar = sM.nTotal = 0;
sM.nAlloc = nInitBuf;
sM.xRealloc = xRealloc;
vxprintf(mout, &sM, useInternal, zFormat, ap);
if( xRealloc ){
if( sM.zText==sM.zBase ){
sM.zText = xRealloc(0, sM.nChar+1);
memcpy(sM.zText, sM.zBase, sM.nChar+1);
}else if( sM.nAlloc>sM.nChar+10 ){
sM.zText = xRealloc(sM.zText, sM.nChar+1);
}
}
return sM.zText;
}
| printf.c | 686 |
STATIC VOID | printf_realloc(void *old, int size)
static void *printf_realloc(void *old, int size){
return sqliteRealloc(old,size);
}
| printf.c | 715 |
CHAR | sqliteVMPrintf(const char *zFormat, va_list ap)
char *sqliteVMPrintf(const char *zFormat, va_list ap){
char zBase[1000];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
}
| printf.c | 722 |
CHAR | sqliteMPrintf(const char *zFormat, ...)
char *sqliteMPrintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[1000];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
return z;
}
| printf.c | 731 |
CHAR | sqlite_mprintf(const char *zFormat, ...)
char *sqlite_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBuf[200];
va_start(ap,zFormat);
z = base_vprintf((void*(*)(void*,int))realloc, 0,
zBuf, sizeof(zBuf), zFormat, ap);
va_end(ap);
return z;
}
| printf.c | 745 |
CHAR | sqlite_vmprintf(const char *zFormat, va_list ap)
char *sqlite_vmprintf(const char *zFormat, va_list ap){
char zBuf[200];
return base_vprintf((void*(*)(void*,int))realloc, 0,
zBuf, sizeof(zBuf), zFormat, ap);
}
| printf.c | 761 |
CHAR | sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...)
char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
va_list ap;
va_start(ap,zFormat);
z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
va_end(ap);
return z;
}
| printf.c | 769 |
INT | sqlite_exec_printf( sqlite *db, const char *sqlFormat, sqlite_callback xCallback, void *pArg, char **errmsg, ... )
int sqlite_exec_printf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback xCallback, /* Callback function */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string. */
){
va_list ap;
int rc;
va_start(ap, errmsg);
rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap);
va_end(ap);
return rc;
}
| printf.c | 785 |
INT | sqlite_exec_vprintf( sqlite *db, const char *sqlFormat, sqlite_callback xCallback, void *pArg, char **errmsg, va_list ap )
int sqlite_exec_vprintf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback xCallback, /* Callback function */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string. */
){
char *zSql;
int rc;
zSql = sqlite_vmprintf(sqlFormat, ap);
rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg);
free(zSql);
return rc;
}
| printf.c | 809 |
INT | sqlite_get_table_printf( sqlite *db, const char *sqlFormat, char ***resultp, int *nrow, int *ncol, char **errmsg, ... )
int sqlite_get_table_printf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncol, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
){
va_list ap;
int rc;
va_start(ap, errmsg);
rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap);
va_end(ap);
return rc;
}
| printf.c | 825 |
INT | sqlite_get_table_vprintf( sqlite *db, const char *sqlFormat, char ***resultp, int *nrow, int *ncolumn, char **errmsg, va_list ap )
int sqlite_get_table_vprintf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string */
){
char *zSql;
int rc;
zSql = sqlite_vmprintf(sqlFormat, ap);
rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
free(zSql);
return rc;
}
| printf.c | 842 |
random.c |
Type | Function | Source | Line |
STATIC INT | randomByte()
static int randomByte(){
unsigned char t;
/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
static struct {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
} prng;
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
**
** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
if( !prng.isInit ){
int i;
char k[256];
prng.j = 0;
prng.i = 0;
sqliteOsRandomSeed(k);
for(i=0; i<256; i++){
prng.s[i] = i;
}
for(i=0; i<256; i++){
prng.j += prng.s[i] + k[i];
t = prng.s[prng.j];
prng.s[prng.j] = prng.s[i];
prng.s[i] = t;
}
prng.isInit = 1;
}
/* Generate and return single random byte
*/
prng.i++;
t = prng.s[prng.i];
prng.j += t;
prng.s[prng.i] = prng.s[prng.j];
prng.s[prng.j] = t;
t += prng.s[prng.i];
return prng.s[t];
}
| random.c | 24 |
VOID | sqliteRandomness(int N, void *pBuf)
void sqliteRandomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
sqliteOsEnterMutex();
while( N-- ){
*(zBuf++) = randomByte();
}
sqliteOsLeaveMutex();
}
| random.c | 87 |
select.c |
Type | Function | Source | Line |
SELECT | sqliteSelectNew( ExprList *pEList, SrcList *pSrc, Expr *pWhere, ExprList *pGroupBy, Expr *pHaving, ExprList *pOrderBy, int isDistinct, int nLimit, int nOffset )
Select *sqliteSelectNew(
ExprList *pEList, /* which columns to include in the result */
SrcList *pSrc, /* the FROM clause -- which tables to scan */
Expr *pWhere, /* the WHERE clause */
ExprList *pGroupBy, /* the GROUP BY clause */
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
int isDistinct, /* true if the DISTINCT keyword is present */
int nLimit, /* LIMIT value. -1 means not used */
int nOffset /* OFFSET value. 0 means no offset */
){
Select *pNew;
pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ){
sqliteExprListDelete(pEList);
sqliteSrcListDelete(pSrc);
sqliteExprDelete(pWhere);
sqliteExprListDelete(pGroupBy);
sqliteExprDelete(pHaving);
sqliteExprListDelete(pOrderBy);
}else{
if( pEList==0 ){
pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
}
pNew->pEList = pEList;
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
pNew->isDistinct = isDistinct;
pNew->op = TK_SELECT;
pNew->nLimit = nLimit;
pNew->nOffset = nOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
}
return pNew;
}
| select.c | 20 |
INT | sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC)
int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
int jointype = 0;
Token *apAll[3];
Token *p;
static struct {
const char *zKeyword;
int nChar;
int code;
} keywords[] = {
{ "natural", 7, JT_NATURAL },
{ "left", 4, JT_LEFT|JT_OUTER },
{ "right", 5, JT_RIGHT|JT_OUTER },
{ "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER },
{ "outer", 5, JT_OUTER },
{ "inner", 5, JT_INNER },
{ "cross", 5, JT_INNER },
};
int i, j;
apAll[0] = pA;
apAll[1] = pB;
apAll[2] = pC;
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
for(j=0; jn==keywords[j].nChar
&& sqliteStrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){
jointype |= keywords[j].code;
break;
}
}
if( j>=sizeof(keywords)/sizeof(keywords[0]) ){
jointype |= JT_ERROR;
break;
}
}
if(
(jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
(jointype & JT_ERROR)!=0
){
static Token dummy = { 0, 0 };
char *zSp1 = " ", *zSp2 = " ";
if( pB==0 ){ pB = &dummy; zSp1 = 0; }
if( pC==0 ){ pC = &dummy; zSp2 = 0; }
sqliteSetNString(&pParse->zErrMsg, "unknown or unsupported join type: ", 0,
pA->z, pA->n, zSp1, 1, pB->z, pB->n, zSp2, 1, pC->z, pC->n, 0);
pParse->nErr++;
jointype = JT_INNER;
}else if( jointype & JT_RIGHT ){
sqliteErrorMsg(pParse,
"RIGHT and FULL OUTER JOINs are not currently supported");
jointype = JT_INNER;
}
return jointype;
}
| select.c | 64 |
STATIC INT | columnIndex(Table *pTab, const char *zCol)
static int columnIndex(Table *pTab, const char *zCol){
int i;
for(i=0; inCol; i++){
if( sqliteStrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
}
return -1;
}
| select.c | 135 |
STATIC VOID | addWhereTerm( const char *zCol, const Table *pTab1, const Table *pTab2, Expr **ppExpr )
static void addWhereTerm(
const char *zCol, /* Name of the column */
const Table *pTab1, /* First table */
const Table *pTab2, /* Second table */
Expr **ppExpr /* Add the equality term to this expression */
){
Token dummy;
Expr *pE1a, *pE1b, *pE1c;
Expr *pE2a, *pE2b, *pE2c;
Expr *pE;
dummy.z = zCol;
dummy.n = strlen(zCol);
dummy.dyn = 0;
pE1a = sqliteExpr(TK_ID, 0, 0, &dummy);
pE2a = sqliteExpr(TK_ID, 0, 0, &dummy);
dummy.z = pTab1->zName;
dummy.n = strlen(dummy.z);
pE1b = sqliteExpr(TK_ID, 0, 0, &dummy);
dummy.z = pTab2->zName;
dummy.n = strlen(dummy.z);
pE2b = sqliteExpr(TK_ID, 0, 0, &dummy);
pE1c = sqliteExpr(TK_DOT, pE1b, pE1a, 0);
pE2c = sqliteExpr(TK_DOT, pE2b, pE2a, 0);
pE = sqliteExpr(TK_EQ, pE1c, pE2c, 0);
ExprSetProperty(pE, EP_FromJoin);
if( *ppExpr ){
*ppExpr = sqliteExpr(TK_AND, *ppExpr, pE, 0);
}else{
*ppExpr = pE;
}
}
| select.c | 147 |
STATIC VOID | setJoinExpr(Expr *p)
static void setJoinExpr(Expr *p){
while( p ){
ExprSetProperty(p, EP_FromJoin);
setJoinExpr(p->pLeft);
p = p->pRight;
}
}
| select.c | 184 |
STATIC INT | sqliteProcessJoin(Parse *pParse, Select *p)
static int sqliteProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc;
int i, j;
pSrc = p->pSrc;
for(i=0; inSrc-1; i++){
struct SrcList_item *pTerm = &pSrc->a[i];
struct SrcList_item *pOther = &pSrc->a[i+1];
if( pTerm->pTab==0 || pOther->pTab==0 ) continue;
/* When the NATURAL keyword is present, add WHERE clause terms for
** every column that the two tables have in common.
*/
if( pTerm->jointype & JT_NATURAL ){
Table *pTab;
if( pTerm->pOn || pTerm->pUsing ){
sqliteErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0);
return 1;
}
pTab = pTerm->pTab;
for(j=0; jnCol; j++){
if( columnIndex(pOther->pTab, pTab->aCol[j].zName)>=0 ){
addWhereTerm(pTab->aCol[j].zName, pTab, pOther->pTab, &p->pWhere);
}
}
}
/* Disallow both ON and USING clauses in the same join
*/
if( pTerm->pOn && pTerm->pUsing ){
sqliteErrorMsg(pParse, "cannot have both ON and USING "
"clauses in the same join");
return 1;
}
/* Add the ON clause to the end of the WHERE clause, connected by
** and AND operator.
*/
if( pTerm->pOn ){
setJoinExpr(pTerm->pOn);
if( p->pWhere==0 ){
p->pWhere = pTerm->pOn;
}else{
p->pWhere = sqliteExpr(TK_AND, p->pWhere, pTerm->pOn, 0);
}
pTerm->pOn = 0;
}
/* Create extra terms on the WHERE clause for each column named
** in the USING clause. Example: If the two tables to be joined are
** A and B and the USING clause names X, Y, and Z, then add this
** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
** Report an error if any column mentioned in the USING clause is
** not contained in both tables to be joined.
*/
if( pTerm->pUsing ){
IdList *pList;
int j;
assert( inSrc-1 );
pList = pTerm->pUsing;
for(j=0; jnId; j++){
if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 ||
columnIndex(pOther->pTab, pList->a[j].zName)<0 ){
sqliteErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", pList->a[j].zName);
return 1;
}
addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere);
}
}
}
return 0;
}
| select.c | 202 |
VOID | sqliteSelectDelete(Select *p)
void sqliteSelectDelete(Select *p){
if( p==0 ) return;
sqliteExprListDelete(p->pEList);
sqliteSrcListDelete(p->pSrc);
sqliteExprDelete(p->pWhere);
sqliteExprListDelete(p->pGroupBy);
sqliteExprDelete(p->pHaving);
sqliteExprListDelete(p->pOrderBy);
sqliteSelectDelete(p->pPrior);
sqliteFree(p->zSelect);
sqliteFree(p);
}
| select.c | 284 |
STATIC VOID | sqliteAggregateInfoReset(Parse *pParse)
static void sqliteAggregateInfoReset(Parse *pParse){
sqliteFree(pParse->aAgg);
pParse->aAgg = 0;
pParse->nAgg = 0;
pParse->useAgg = 0;
}
| select.c | 300 |
STATIC VOID | pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy)
static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
char *zSortOrder;
int i;
zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
if( zSortOrder==0 ) return;
for(i=0; inExpr; i++){
int order = pOrderBy->a[i].sortOrder;
int type;
int c;
if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
type = SQLITE_SO_TEXT;
}else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){
type = SQLITE_SO_NUM;
}else if( pParse->db->file_format>=4 ){
type = sqliteExprType(pOrderBy->a[i].pExpr);
}else{
type = SQLITE_SO_NUM;
}
if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){
c = type==SQLITE_SO_TEXT ? 'A' : '+';
}else{
c = type==SQLITE_SO_TEXT ? 'D' : '-';
}
zSortOrder[i] = c;
sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
}
zSortOrder[pOrderBy->nExpr] = 0;
sqliteVdbeOp3(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, P3_DYNAMIC);
sqliteVdbeAddOp(v, OP_SortPut, 0, 0);
}
| select.c | 310 |
VOID | sqliteAddKeyType(Vdbe *v, ExprList *pEList)
void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
int nColumn = pEList->nExpr;
char *zType = sqliteMalloc( nColumn+1 );
int i;
if( zType==0 ) return;
for(i=0; ia[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
}
zType[i] = 0;
sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
}
| select.c | 345 |
STATIC VOID | codeLimiter( Vdbe *v, Select *p, int iContinue, int iBreak, int nPop )
static void codeLimiter(
Vdbe *v, /* Generate code into this VM */
Select *p, /* The SELECT statement being coded */
int iContinue, /* Jump here to skip the current record */
int iBreak, /* Jump here to end the loop */
int nPop /* Number of times to pop stack when jumping */
){
if( p->iOffset>=0 ){
int addr = sqliteVdbeCurrentAddr(v) + 2;
if( nPop>0 ) addr++;
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
if( nPop>0 ){
sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
}
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
}
if( p->iLimit>=0 ){
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
}
}
| select.c | 367 |
STATIC INT | selectInnerLoop( Parse *pParse, Select *p, ExprList *pEList, int srcTab, int nColumn, ExprList *pOrderBy, int distinct, int eDest, int iParm, int iContinue, int iBreak )
static int selectInnerLoop(
Parse *pParse, /* The parser context */
Select *p, /* The complete select statement being coded */
ExprList *pEList, /* List of values being extracted */
int srcTab, /* Pull data from this table */
int nColumn, /* Number of columns in the source table */
ExprList *pOrderBy, /* If not NULL, sort results using this key */
int distinct, /* If >=0, make sure results are distinct */
int eDest, /* How to dispose of the results */
int iParm, /* An argument to the disposal method */
int iContinue, /* Jump here to continue with next row */
int iBreak /* Jump here to break out of the inner loop */
){
Vdbe *v = pParse->pVdbe;
int i;
int hasDistinct; /* True if the DISTINCT keyword is present */
if( v==0 ) return 0;
assert( pEList!=0 );
/* If there was a LIMIT clause on the SELECT statement, then do the check
** to see if this row should be output.
*/
hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
if( pOrderBy==0 && !hasDistinct ){
codeLimiter(v, p, iContinue, iBreak, 0);
}
/* Pull the requested columns.
*/
if( nColumn>0 ){
for(i=0; inExpr;
for(i=0; inExpr; i++){
sqliteExprCode(pParse, pEList->a[i].pExpr);
}
}
/* If the DISTINCT keyword was present on the SELECT statement
** and this row has been seen before, then do not make this row
** part of the result.
*/
if( hasDistinct ){
#if NULL_ALWAYS_DISTINCT
sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
#endif
sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);
sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
if( pOrderBy==0 ){
codeLimiter(v, p, iContinue, iBreak, nColumn);
}
}
switch( eDest ){
/* In this mode, write each query result to the key of the temporary
** table iParm.
*/
case SRT_Union: {
sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
break;
}
/* Store the result as data using a unique key.
*/
case SRT_Table:
case SRT_TempTable: {
sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
if( pOrderBy ){
pushOntoSorter(pParse, v, pOrderBy);
}else{
sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
}
break;
}
/* Construct a record from the query result, but instead of
** saving that record, use it as a key to delete elements from
** the temporary table iParm.
*/
case SRT_Except: {
int addr;
addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);
sqliteVdbeAddOp(v, OP_Delete, iParm, 0);
break;
}
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
** item into the set table with bogus data.
*/
case SRT_Set: {
int addr1 = sqliteVdbeCurrentAddr(v);
int addr2;
assert( nColumn==1 );
sqliteVdbeAddOp(v, OP_NotNull, -1, addr1+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
addr2 = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
if( pOrderBy ){
pushOntoSorter(pParse, v, pOrderBy);
}else{
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
}
sqliteVdbeChangeP2(v, addr2, sqliteVdbeCurrentAddr(v));
break;
}
/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell and break out
** of the scan loop.
*/
case SRT_Mem: {
assert( nColumn==1 );
if( pOrderBy ){
pushOntoSorter(pParse, v, pOrderBy);
}else{
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
sqliteVdbeAddOp(v, OP_Goto, 0, iBreak);
}
break;
}
/* Send the data to the callback function.
*/
case SRT_Callback:
case SRT_Sorter: {
if( pOrderBy ){
sqliteVdbeAddOp(v, OP_SortMakeRec, nColumn, 0);
pushOntoSorter(pParse, v, pOrderBy);
}else{
assert( eDest==SRT_Callback );
sqliteVdbeAddOp(v, OP_Callback, nColumn, 0);
}
break;
}
/* Invoke a subroutine to handle the results. The subroutine itself
** is responsible for popping the results off of the stack.
*/
case SRT_Subroutine: {
if( pOrderBy ){
sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
pushOntoSorter(pParse, v, pOrderBy);
}else{
sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
}
break;
}
/* Discard the results. This is used for SELECT statements inside
** the body of a TRIGGER. The purpose of such selects is to call
** user-defined functions that have side effects. We do not care
** about the actual results of the select.
*/
default: {
assert( eDest==SRT_Discard );
sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
break;
}
}
return 0;
}
| select.c | 391 |
STATIC VOID | generateSortTail( Select *p, Vdbe *v, int nColumn, int eDest, int iParm )
static void generateSortTail(
Select *p, /* The SELECT statement */
Vdbe *v, /* Generate code into this VDBE */
int nColumn, /* Number of columns of data */
int eDest, /* Write the sorted results here */
int iParm /* Optional parameter associated with eDest */
){
int end1 = sqliteVdbeMakeLabel(v);
int end2 = sqliteVdbeMakeLabel(v);
int addr;
if( eDest==SRT_Sorter ) return;
sqliteVdbeAddOp(v, OP_Sort, 0, 0);
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
codeLimiter(v, p, addr, end2, 1);
switch( eDest ){
case SRT_Callback: {
sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
break;
}
case SRT_Table:
case SRT_TempTable: {
sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
break;
}
case SRT_Set: {
assert( nColumn==1 );
sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
break;
}
case SRT_Mem: {
assert( nColumn==1 );
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
sqliteVdbeAddOp(v, OP_Goto, 0, end1);
break;
}
case SRT_Subroutine: {
int i;
for(i=0; iselect.c | 576 | |
STATIC VOID | generateColumnTypes( Parse *pParse, SrcList *pTabList, ExprList *pEList )
static void generateColumnTypes(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i, j;
for(i=0; inExpr; i++){
Expr *p = pEList->a[i].pExpr;
char *zType = 0;
if( p==0 ) continue;
if( p->op==TK_COLUMN && pTabList ){
Table *pTab;
int iCol = p->iColumn;
for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
assert( jnSrc );
pTab = pTabList->a[j].pTab;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iColnCol) );
if( iCol<0 ){
zType = "INTEGER";
}else{
zType = pTab->aCol[iCol].zType;
}
}else{
if( sqliteExprType(p)==SQLITE_SO_TEXT ){
zType = "TEXT";
}else{
zType = "NUMERIC";
}
}
sqliteVdbeOp3(v, OP_ColumnName, i + pEList->nExpr, 0, zType, 0);
}
}
| select.c | 644 |
STATIC VOID | generateColumnNames( Parse *pParse, SrcList *pTabList, ExprList *pEList )
static void generateColumnNames(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i, j;
sqlite *db = pParse->db;
int fullNames, shortNames;
assert( v!=0 );
if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
pParse->colNamesSet = 1;
fullNames = (db->flags & SQLITE_FullColNames)!=0;
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
for(i=0; inExpr; i++){
Expr *p;
int p2 = i==pEList->nExpr-1;
p = pEList->a[i].pExpr;
if( p==0 ) continue;
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
continue;
}
if( p->op==TK_COLUMN && pTabList ){
Table *pTab;
char *zCol;
int iCol = p->iColumn;
for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
assert( jnSrc );
pTab = pTabList->a[j].pTab;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iColnCol) );
if( iCol<0 ){
zCol = "_ROWID_";
}else{
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
sqliteVdbeCompressSpace(v, addr);
}else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
char *zName = 0;
char *zTab;
zTab = pTabList->a[j].zAlias;
if( fullNames || zTab==0 ) zTab = pTab->zName;
sqliteSetString(&zName, zTab, ".", zCol, 0);
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC);
}else{
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zCol, 0);
}
}else if( p->span.z && p->span.z[0] ){
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
sqliteVdbeCompressSpace(v, addr);
}else{
char zName[30];
assert( p->op!=TK_COLUMN || pTabList==0 );
sprintf(zName, "column%d", i+1);
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
}
}
}
| select.c | 694 |
STATIC CONST CHAR | selectOpName(int id)
static const char *selectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
case TK_INTERSECT: z = "INTERSECT"; break;
case TK_EXCEPT: z = "EXCEPT"; break;
default: z = "UNION"; break;
}
return z;
}
/*
** Forward declaration
*/
static int fillInColumnList(Parse*, Select*);
| select.c | 764 |
TABLE | sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect)
Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
Table *pTab;
int i, j;
ExprList *pEList;
Column *aCol;
if( fillInColumnList(pParse, pSelect) ){
return 0;
}
pTab = sqliteMalloc( sizeof(Table) );
if( pTab==0 ){
return 0;
}
pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;
pEList = pSelect->pEList;
pTab->nCol = pEList->nExpr;
assert( pTab->nCol>0 );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
for(i=0; inCol; i++){
Expr *p, *pR;
if( pEList->a[i].zName ){
aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
}else if( (p=pEList->a[i].pExpr)->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
int cnt;
sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
for(j=cnt=0; jtoken.z, pR->token.n, zBuf, n,0);
j = -1;
}
}
}else if( p->span.z && p->span.z[0] ){
sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
}else{
char zBuf[30];
sprintf(zBuf, "column%d", i+1);
aCol[i].zName = sqliteStrDup(zBuf);
}
sqliteDequote(aCol[i].zName);
}
pTab->iPKey = -1;
return pTab;
}
| select.c | 783 |
STATIC INT | fillInColumnList(Parse *pParse, Select *p)
static int fillInColumnList(Parse *pParse, Select *p){
int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
Table *pTab;
if( p==0 || p->pSrc==0 ) return 1;
pTabList = p->pSrc;
pEList = p->pEList;
/* Look up every table in the table list.
*/
for(i=0; inSrc; i++){
if( pTabList->a[i].pTab ){
/* This routine has run before! No need to continue */
return 0;
}
if( pTabList->a[i].zName==0 ){
/* A sub-query in the FROM clause of a SELECT */
assert( pTabList->a[i].pSelect!=0 );
if( pTabList->a[i].zAlias==0 ){
char zFakeName[60];
sprintf(zFakeName, "sqlite_subquery_%p_",
(void*)pTabList->a[i].pSelect);
sqliteSetString(&pTabList->a[i].zAlias, zFakeName, 0);
}
pTabList->a[i].pTab = pTab =
sqliteResultSetOfSelect(pParse, pTabList->a[i].zAlias,
pTabList->a[i].pSelect);
if( pTab==0 ){
return 1;
}
/* The isTransient flag indicates that the Table structure has been
** dynamically allocated and may be freed at any time. In other words,
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
pTab->isTransient = 1;
}else{
/* An ordinary table or view name in the FROM clause */
pTabList->a[i].pTab = pTab =
sqliteLocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase);
if( pTab==0 ){
return 1;
}
if( pTab->pSelect ){
/* We reach here if the named table is a really a view */
if( sqliteViewGetColumnNames(pParse, pTab) ){
return 1;
}
/* If pTabList->a[i].pSelect!=0 it means we are dealing with a
** view within a view. The SELECT structure has already been
** copied by the outer view so we can skip the copy step here
** in the inner view.
*/
if( pTabList->a[i].pSelect==0 ){
pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect);
}
}
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
if( sqliteProcessJoin(pParse, p) ) return 1;
/* For every "*" that occurs in the column list, insert the names of
** all columns in all tables. And for every TABLE.* insert the names
** of all columns in TABLE. The parser inserted a special expression
** with the TK_ALL operator for each "*" that it found in the column list.
** The following code just has to locate the TK_ALL expressions and expand
** each one to the list of all columns in all tables.
**
** The first loop just checks to see if there are any "*" operators
** that need expanding.
*/
for(k=0; knExpr; k++){
Expr *pE = pEList->a[k].pExpr;
if( pE->op==TK_ALL ) break;
if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
&& pE->pLeft && pE->pLeft->op==TK_ID ) break;
}
rc = 0;
if( knExpr ){
/*
** If we get here it means the result set contains one or more "*"
** operators that need to be expanded. Loop through each expression
** in the result set and expand them one by one.
*/
struct ExprList_item *a = pEList->a;
ExprList *pNew = 0;
for(k=0; knExpr; k++){
Expr *pE = a[k].pExpr;
if( pE->op!=TK_ALL &&
(pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
*/
pNew = sqliteExprListAppend(pNew, a[k].pExpr, 0);
pNew->a[pNew->nExpr-1].zName = a[k].zName;
a[k].pExpr = 0;
a[k].zName = 0;
}else{
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT && pE->pLeft ){
zTName = sqliteTableNameFromToken(&pE->pLeft->token);
}else{
zTName = 0;
}
for(i=0; inSrc; i++){
Table *pTab = pTabList->a[i].pTab;
char *zTabName = pTabList->a[i].zAlias;
if( zTabName==0 || zTabName[0]==0 ){
zTabName = pTab->zName;
}
if( zTName && (zTabName==0 || zTabName[0]==0 ||
sqliteStrICmp(zTName, zTabName)!=0) ){
continue;
}
tableSeen = 1;
for(j=0; jnCol; j++){
Expr *pExpr, *pLeft, *pRight;
char *zName = pTab->aCol[j].zName;
if( i>0 && (pTabList->a[i-1].jointype & JT_NATURAL)!=0 &&
columnIndex(pTabList->a[i-1].pTab, zName)>=0 ){
/* In a NATURAL join, omit the join columns from the
** table on the right */
continue;
}
if( i>0 && sqliteIdListIndex(pTabList->a[i-1].pUsing, zName)>=0 ){
/* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
}
pRight = sqliteExpr(TK_ID, 0, 0, 0);
if( pRight==0 ) break;
pRight->token.z = zName;
pRight->token.n = strlen(zName);
pRight->token.dyn = 0;
if( zTabName && pTabList->nSrc>1 ){
pLeft = sqliteExpr(TK_ID, 0, 0, 0);
pExpr = sqliteExpr(TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break;
pLeft->token.z = zTabName;
pLeft->token.n = strlen(zTabName);
pLeft->token.dyn = 0;
sqliteSetString((char**)&pExpr->span.z, zTabName, ".", zName, 0);
pExpr->span.n = strlen(pExpr->span.z);
pExpr->span.dyn = 1;
pExpr->token.z = 0;
pExpr->token.n = 0;
pExpr->token.dyn = 0;
}else{
pExpr = pRight;
pExpr->span = pExpr->token;
}
pNew = sqliteExprListAppend(pNew, pExpr, 0);
}
}
if( !tableSeen ){
if( zTName ){
sqliteErrorMsg(pParse, "no such table: %s", zTName);
}else{
sqliteErrorMsg(pParse, "no tables specified");
}
rc = 1;
}
sqliteFree(zTName);
}
}
sqliteExprListDelete(pEList);
p->pEList = pNew;
}
return rc;
}
| select.c | 836 |
VOID | sqliteSelectUnbind(Select *p)
void sqliteSelectUnbind(Select *p){
int i;
SrcList *pSrc = p->pSrc;
Table *pTab;
if( p==0 ) return;
for(i=0; inSrc; i++){
if( (pTab = pSrc->a[i].pTab)!=0 ){
if( pTab->isTransient ){
sqliteDeleteTable(0, pTab);
}
pSrc->a[i].pTab = 0;
if( pSrc->a[i].pSelect ){
sqliteSelectUnbind(pSrc->a[i].pSelect);
}
}
}
}
| select.c | 1036 |
STATIC INT | matchOrderbyToColumn( Parse *pParse, Select *pSelect, ExprList *pOrderBy, int iTable, int mustComplete )
static int matchOrderbyToColumn(
Parse *pParse, /* A place to leave error messages */
Select *pSelect, /* Match to result columns of this SELECT */
ExprList *pOrderBy, /* The ORDER BY values to match against columns */
int iTable, /* Insert this value in iTable */
int mustComplete /* If TRUE all ORDER BYs must match */
){
int nErr = 0;
int i, j;
ExprList *pEList;
if( pSelect==0 || pOrderBy==0 ) return 1;
if( mustComplete ){
for(i=0; inExpr; i++){ pOrderBy->a[i].done = 0; }
}
if( fillInColumnList(pParse, pSelect) ){
return 1;
}
if( pSelect->pPrior ){
if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){
return 1;
}
}
pEList = pSelect->pEList;
for(i=0; inExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
int iCol = -1;
if( pOrderBy->a[i].done ) continue;
if( sqliteExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
sqliteErrorMsg(pParse,
"ORDER BY position %d should be between 1 and %d",
iCol, pEList->nExpr);
nErr++;
break;
}
if( !mustComplete ) continue;
iCol--;
}
for(j=0; iCol<0 && jnExpr; j++){
if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
char *zName, *zLabel;
zName = pEList->a[j].zName;
assert( pE->token.z );
zLabel = sqliteStrNDup(pE->token.z, pE->token.n);
sqliteDequote(zLabel);
if( sqliteStrICmp(zName, zLabel)==0 ){
iCol = j;
}
sqliteFree(zLabel);
}
if( iCol<0 && sqliteExprCompare(pE, pEList->a[j].pExpr) ){
iCol = j;
}
}
if( iCol>=0 ){
pE->op = TK_COLUMN;
pE->iColumn = iCol;
pE->iTable = iTable;
pOrderBy->a[i].done = 1;
}
if( iCol<0 && mustComplete ){
sqliteErrorMsg(pParse,
"ORDER BY term number %d does not match any result column", i+1);
nErr++;
break;
}
}
return nErr;
}
| select.c | 1067 |
VDBE | sqliteGetVdbe(Parse *pParse)
Vdbe *sqliteGetVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe;
if( v==0 ){
v = pParse->pVdbe = sqliteVdbeCreate(pParse->db);
}
return v;
}
| select.c | 1158 |
STATIC VOID | multiSelectSortOrder(Select *p, ExprList *pOrderBy)
static void multiSelectSortOrder(Select *p, ExprList *pOrderBy){
int i;
ExprList *pEList;
if( pOrderBy==0 ) return;
if( p==0 ){
for(i=0; inExpr; i++){
pOrderBy->a[i].pExpr->dataType = SQLITE_SO_TEXT;
}
return;
}
multiSelectSortOrder(p->pPrior, pOrderBy);
pEList = p->pEList;
for(i=0; inExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
if( pE->dataType==SQLITE_SO_NUM ) continue;
assert( pE->iColumn>=0 );
if( pEList->nExpr>pE->iColumn ){
pE->dataType = sqliteExprType(pEList->a[pE->iColumn].pExpr);
}
}
}
| select.c | 1170 |
STATIC VOID | computeLimitRegisters(Parse *pParse, Select *p)
static void computeLimitRegisters(Parse *pParse, Select *p){
/*
** If the comparison is p->nLimit>0 then "LIMIT 0" shows
** all rows. It is the same as no limit. If the comparision is
** p->nLimit>=0 then "LIMIT 0" show no rows at all.
** "LIMIT -1" always shows all rows. There is some
** contraversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
if( p->nLimit>=0 ){
int iMem = pParse->nMem++;
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return;
sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0);
sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
p->iLimit = iMem;
}
if( p->nOffset>0 ){
int iMem = pParse->nMem++;
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return;
sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0);
sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
p->iOffset = iMem;
}
}
| select.c | 1219 |
STATIC INT | multiSelect(Parse *pParse, Select *p, int eDest, int iParm)
static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
int rc; /* Success code from a subroutine */
Select *pPrior; /* Another SELECT immediately to our left */
Vdbe *v; /* Generate code to this VDBE */
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
** the last SELECT in the series may have an ORDER BY or LIMIT.
*/
if( p==0 || p->pPrior==0 ) return 1;
pPrior = p->pPrior;
if( pPrior->pOrderBy ){
sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
return 1;
}
if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){
sqliteErrorMsg(pParse,"LIMIT clause should come after %s not before",
selectOpName(p->op));
return 1;
}
/* Make sure we have a valid query engine. If not, create a new one.
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
/* Create the destination temporary table if necessary
*/
if( eDest==SRT_TempTable ){
sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
eDest = SRT_Table;
}
/* Generate code for the left and right SELECT statements.
*/
switch( p->op ){
case TK_ALL: {
if( p->pOrderBy==0 ){
pPrior->nLimit = p->nLimit;
pPrior->nOffset = p->nOffset;
rc = sqliteSelect(pParse, pPrior, eDest, iParm, 0, 0, 0);
if( rc ) return rc;
p->pPrior = 0;
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
p->nLimit = -1;
p->nOffset = 0;
rc = sqliteSelect(pParse, p, eDest, iParm, 0, 0, 0);
p->pPrior = pPrior;
if( rc ) return rc;
break;
}
/* For UNION ALL ... ORDER BY fall through to the next case */
}
case TK_EXCEPT:
case TK_UNION: {
int unionTab; /* Cursor number of the temporary table holding result */
int op; /* One of the SRT_ operations to apply to self */
int priorOp; /* The SRT_ operation to apply to prior selects */
int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */
ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */
priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){
/* We can reuse a temporary table generated by a SELECT to our
** right.
*/
unionTab = iParm;
}else{
/* We will need to create our own temporary table to hold the
** intermediate results.
*/
unionTab = pParse->nTab++;
if( p->pOrderBy
&& matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){
return 1;
}
if( p->op!=TK_ALL ){
sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 1);
sqliteVdbeAddOp(v, OP_KeyAsData, unionTab, 1);
}else{
sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 0);
}
}
/* Code the SELECT statements to our left
*/
rc = sqliteSelect(pParse, pPrior, priorOp, unionTab, 0, 0, 0);
if( rc ) return rc;
/* Code the current SELECT statement
*/
switch( p->op ){
case TK_EXCEPT: op = SRT_Except; break;
case TK_UNION: op = SRT_Union; break;
case TK_ALL: op = SRT_Table; break;
}
p->pPrior = 0;
pOrderBy = p->pOrderBy;
p->pOrderBy = 0;
nLimit = p->nLimit;
p->nLimit = -1;
nOffset = p->nOffset;
p->nOffset = 0;
rc = sqliteSelect(pParse, p, op, unionTab, 0, 0, 0);
p->pPrior = pPrior;
p->pOrderBy = pOrderBy;
p->nLimit = nLimit;
p->nOffset = nOffset;
if( rc ) return rc;
/* Convert the data in the temporary table into whatever form
** it is that we currently need.
*/
if( eDest!=priorOp || unionTab!=iParm ){
int iCont, iBreak, iStart;
assert( p->pEList );
if( eDest==SRT_Callback ){
generateColumnNames(pParse, 0, p->pEList);
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
computeLimitRegisters(pParse, p);
iStart = sqliteVdbeCurrentAddr(v);
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
sqliteVdbeResolveLabel(v, iCont);
sqliteVdbeAddOp(v, OP_Next, unionTab, iStart);
sqliteVdbeResolveLabel(v, iBreak);
sqliteVdbeAddOp(v, OP_Close, unionTab, 0);
if( p->pOrderBy ){
generateSortTail(p, v, p->pEList->nExpr, eDest, iParm);
}
}
break;
}
case TK_INTERSECT: {
int tab1, tab2;
int iCont, iBreak, iStart;
int nLimit, nOffset;
/* INTERSECT is different from the others since it requires
** two temporary tables. Hence it has its own case. Begin
** by allocating the tables we will need.
*/
tab1 = pParse->nTab++;
tab2 = pParse->nTab++;
if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){
return 1;
}
sqliteVdbeAddOp(v, OP_OpenTemp, tab1, 1);
sqliteVdbeAddOp(v, OP_KeyAsData, tab1, 1);
/* Code the SELECTs to our left into temporary table "tab1".
*/
rc = sqliteSelect(pParse, pPrior, SRT_Union, tab1, 0, 0, 0);
if( rc ) return rc;
/* Code the current SELECT into temporary table "tab2"
*/
sqliteVdbeAddOp(v, OP_OpenTemp, tab2, 1);
sqliteVdbeAddOp(v, OP_KeyAsData, tab2, 1);
p->pPrior = 0;
nLimit = p->nLimit;
p->nLimit = -1;
nOffset = p->nOffset;
p->nOffset = 0;
rc = sqliteSelect(pParse, p, SRT_Union, tab2, 0, 0, 0);
p->pPrior = pPrior;
p->nLimit = nLimit;
p->nOffset = nOffset;
if( rc ) return rc;
/* Generate code to take the intersection of the two temporary
** tables.
*/
assert( p->pEList );
if( eDest==SRT_Callback ){
generateColumnNames(pParse, 0, p->pEList);
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
computeLimitRegisters(pParse, p);
iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
sqliteVdbeResolveLabel(v, iCont);
sqliteVdbeAddOp(v, OP_Next, tab1, iStart);
sqliteVdbeResolveLabel(v, iBreak);
sqliteVdbeAddOp(v, OP_Close, tab2, 0);
sqliteVdbeAddOp(v, OP_Close, tab1, 0);
if( p->pOrderBy ){
generateSortTail(p, v, p->pEList->nExpr, eDest, iParm);
}
break;
}
}
assert( p->pEList && pPrior->pEList );
if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
sqliteErrorMsg(pParse, "SELECTs to the left and right of %s"
" do not have the same number of result columns", selectOpName(p->op));
return 1;
}
return 0;
}
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
| select.c | 1265 |
STATIC VOID | substExpr(Expr *pExpr, int iTable, ExprList *pEList)
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else{
Expr *pNew;
assert( pEList!=0 && pExpr->iColumnnExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
pNew = pEList->a[pExpr->iColumn].pExpr;
assert( pNew!=0 );
pExpr->op = pNew->op;
pExpr->dataType = pNew->dataType;
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqliteExprDup(pNew->pLeft);
assert( pExpr->pRight==0 );
pExpr->pRight = sqliteExprDup(pNew->pRight);
assert( pExpr->pList==0 );
pExpr->pList = sqliteExprListDup(pNew->pList);
pExpr->iTable = pNew->iTable;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqliteTokenCopy(&pExpr->token, &pNew->token);
sqliteTokenCopy(&pExpr->span, &pNew->span);
}
}else{
substExpr(pExpr->pLeft, iTable, pEList);
substExpr(pExpr->pRight, iTable, pEList);
substExprList(pExpr->pList, iTable, pEList);
}
}
| select.c | 1526 |
STATIC VOID | substExprList(ExprList *pList, int iTable, ExprList *pEList)
static void
substExprList(ExprList *pList, int iTable, ExprList *pEList){
int i;
if( pList==0 ) return;
for(i=0; inExpr; i++){
substExpr(pList->a[i].pExpr, iTable, pEList);
}
}
| select.c | 1557 |
STATIC INT | flattenSubquery( Parse *pParse, Select *p, int iFrom, int isAgg, int subqueryIsAgg )
static int flattenSubquery(
Parse *pParse, /* The parsing context */
Select *p, /* The parent or outer SELECT statement */
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
int isAgg, /* True if outer SELECT uses aggregate functions */
int subqueryIsAgg /* True if the subquery uses aggregate functions */
){
Select *pSub; /* The inner query or "subquery" */
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int i;
Expr *pWhere;
/* Check to see if flattening is permitted. Return 0 if not.
*/
if( p==0 ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFromnSrc );
pSub = pSrc->a[iFrom].pSelect;
assert( pSub!=0 );
if( isAgg && subqueryIsAgg ) return 0;
if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
pSubSrc = pSub->pSrc;
assert( pSubSrc );
if( pSubSrc->nSrc==0 ) return 0;
if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){
return 0;
}
if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
if( p->pOrderBy && pSub->pOrderBy ) return 0;
/* Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
** t1 LEFT OUTER JOIN (t2 JOIN t3)
**
** If we flatten the above, we would get
**
** (t1 LEFT OUTER JOIN t2) JOIN t3
**
** which is not at all the same thing.
*/
if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){
return 0;
}
/* Restriction 12: If the subquery is the right operand of a left outer
** join, make sure the subquery has no WHERE clause.
** An examples of why this is not allowed:
**
** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
**
** If we flatten the above, we would get
**
** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
**
** But the t2.x>0 test will always fail on a NULL row of t2, which
** effectively converts the OUTER JOIN into an INNER JOIN.
*/
if( iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0
&& pSub->pWhere!=0 ){
return 0;
}
/* If we reach this point, it means flattening is permitted for the
** iFrom-th entry of the FROM clause in the outer query.
*/
/* Move all of the FROM elements of the subquery into the
** the FROM clause of the outer query. Before doing this, remember
** the cursor number for the original outer query FROM element in
** iParent. The iParent cursor will never be used. Subsequent code
** will scan expressions looking for iParent references and replace
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
iParent = pSrc->a[iFrom].iCursor;
{
int nSubSrc = pSubSrc->nSrc;
int jointype = pSrc->a[iFrom].jointype;
if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
sqliteDeleteTable(0, pSrc->a[iFrom].pTab);
}
sqliteFree(pSrc->a[iFrom].zDatabase);
sqliteFree(pSrc->a[iFrom].zName);
sqliteFree(pSrc->a[iFrom].zAlias);
if( nSubSrc>1 ){
int extra = nSubSrc - 1;
for(i=1; ipSrc = pSrc;
for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
pSrc->a[i] = pSrc->a[i-extra];
}
}
for(i=0; ia[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom+nSubSrc-1].jointype = jointype;
}
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
**
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
** \ \_____________ subquery __________/ /
** \_____________________ outer query ______________________________/
**
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
substExprList(p->pEList, iParent, pSub->pEList);
pList = p->pEList;
for(i=0; inExpr; i++){
Expr *pExpr;
if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){
pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n);
}
}
if( isAgg ){
substExprList(p->pGroupBy, iParent, pSub->pEList);
substExpr(p->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
assert( p->pOrderBy==0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
}else if( p->pOrderBy ){
substExprList(p->pOrderBy, iParent, pSub->pEList);
}
if( pSub->pWhere ){
pWhere = sqliteExprDup(pSub->pWhere);
}else{
pWhere = 0;
}
if( subqueryIsAgg ){
assert( p->pHaving==0 );
p->pHaving = p->pWhere;
p->pWhere = pWhere;
substExpr(p->pHaving, iParent, pSub->pEList);
if( pSub->pHaving ){
Expr *pHaving = sqliteExprDup(pSub->pHaving);
if( p->pHaving ){
p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0);
}else{
p->pHaving = pHaving;
}
}
assert( p->pGroupBy==0 );
p->pGroupBy = sqliteExprListDup(pSub->pGroupBy);
}else if( p->pWhere==0 ){
p->pWhere = pWhere;
}else{
substExpr(p->pWhere, iParent, pSub->pEList);
if( pWhere ){
p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0);
}
}
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
*/
p->isDistinct = p->isDistinct || pSub->isDistinct;
/* Transfer the limit expression from the subquery to the outer
** query.
*/
if( pSub->nLimit>=0 ){
if( p->nLimit<0 ){
p->nLimit = pSub->nLimit;
}else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){
p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset;
}
}
p->nOffset += pSub->nOffset;
/* Finially, delete what is left of the subquery and return
** success.
*/
sqliteSelectDelete(pSub);
return 1;
}
| select.c | 1566 |
STATIC INT | simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm)
static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
Expr *pExpr;
int iCol;
Table *pTab;
Index *pIdx;
int base;
Vdbe *v;
int seekOp;
int cont;
ExprList *pEList, *pList, eList;
struct ExprList_item eListItem;
SrcList *pSrc;
/* Check to see if this query is a simple min() or max() query. Return
** zero if it is not.
*/
if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
pSrc = p->pSrc;
if( pSrc->nSrc!=1 ) return 0;
pEList = p->pEList;
if( pEList->nExpr!=1 ) return 0;
pExpr = pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
pList = pExpr->pList;
if( pList==0 || pList->nExpr!=1 ) return 0;
if( pExpr->token.n!=3 ) return 0;
if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){
seekOp = OP_Rewind;
}else if( sqliteStrNICmp(pExpr->token.z,"max",3)==0 ){
seekOp = OP_Last;
}else{
return 0;
}
pExpr = pList->a[0].pExpr;
if( pExpr->op!=TK_COLUMN ) return 0;
iCol = pExpr->iColumn;
pTab = pSrc->a[0].pTab;
/* If we get to here, it means the query is of the correct form.
** Check to make sure we have an index and make pIdx point to the
** appropriate index. If the min() or max() is on an INTEGER PRIMARY
** key column, no index is necessary so set pIdx to NULL. If no
** usable index is found, return 0.
*/
if( iCol<0 ){
pIdx = 0;
}else{
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->nColumn>=1 );
if( pIdx->aiColumn[0]==iCol ) break;
}
if( pIdx==0 ) return 0;
}
/* Identify column types if we will be using the callback. This
** step is skipped if the output is going to a table or a memory cell.
** The column names have already been generated in the calling function.
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) return 0;
if( eDest==SRT_Callback ){
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
/* If the output is destined for a temporary table, open that table.
*/
if( eDest==SRT_TempTable ){
sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
}
/* Generating code to find the min or the max. Basically all we have
** to do is find the first or the last entry in the chosen index. If
** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
** or last entry in the main table.
*/
sqliteCodeVerifySchema(pParse, pTab->iDb);
base = pSrc->a[0].iCursor;
computeLimitRegisters(pParse, p);
if( pSrc->a[0].pSelect==0 ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, base, pTab->tnum, pTab->zName, 0);
}
cont = sqliteVdbeMakeLabel(v);
if( pIdx==0 ){
sqliteVdbeAddOp(v, seekOp, base, 0);
}else{
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
if( seekOp==OP_Rewind ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
seekOp = OP_MoveTo;
}
sqliteVdbeAddOp(v, seekOp, base+1, 0);
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
}
eList.nExpr = 1;
memset(&eListItem, 0, sizeof(eListItem));
eList.a = &eListItem;
eList.a[0].pExpr = pExpr;
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
sqliteVdbeResolveLabel(v, cont);
sqliteVdbeAddOp(v, OP_Close, base, 0);
return 1;
}
| select.c | 1826 |
INT | sqliteSelect( Parse *pParse, Select *p, int eDest, int iParm, Select *pParent, int parentTab, int *pParentAgg )
int sqliteSelect(
Parse *pParse, /* The parser context */
Select *p, /* The SELECT statement being coded. */
int eDest, /* How to dispose of the results */
int iParm, /* A parameter used by the eDest disposal method */
Select *pParent, /* Another SELECT for which this is a sub-query */
int parentTab, /* Index in pParent->pSrc of this query */
int *pParentAgg /* True if pParent uses aggregate functions */
){
int i;
WhereInfo *pWInfo;
Vdbe *v;
int isAgg = 0; /* True for select lists like "count(*)" */
ExprList *pEList; /* List of columns to extract. */
SrcList *pTabList; /* List of tables to select from */
Expr *pWhere; /* The WHERE clause. May be NULL */
ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
Expr *pHaving; /* The HAVING clause. May be NULL */
int isDistinct; /* True if the DISTINCT keyword is present */
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;
if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
return multiSelect(pParse, p, eDest, iParm);
}
/* Make local copies of the parameters for this query.
*/
pTabList = p->pSrc;
pWhere = p->pWhere;
pOrderBy = p->pOrderBy;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
isDistinct = p->isDistinct;
/* Allocate VDBE cursors for each table in the FROM clause
*/
sqliteSrcListAssignCursors(pParse, pTabList);
/*
** Do not even attempt to generate any code if we have already seen
** errors before this routine starts.
*/
if( pParse->nErr>0 ) goto select_end;
/* Expand any "*" terms in the result set. (For example the "*" in
** "SELECT * FROM t1") The fillInColumnlist() routine also does some
** other housekeeping - see the header comment for details.
*/
if( fillInColumnList(pParse, p) ){
goto select_end;
}
pWhere = p->pWhere;
pEList = p->pEList;
if( pEList==0 ) goto select_end;
/* If writing to memory or generating a set
** only a single column may be output.
*/
if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
sqliteErrorMsg(pParse, "only a single result allowed for "
"a SELECT that is part of an expression");
goto select_end;
}
/* ORDER BY is ignored for some destinations.
*/
switch( eDest ){
case SRT_Union:
case SRT_Except:
case SRT_Discard:
pOrderBy = 0;
break;
default:
break;
}
/* At this point, we should have allocated all the cursors that we
** need to handle subquerys and temporary tables.
**
** Resolve the column names and do a semantics check on all the expressions.
*/
for(i=0; inExpr; i++){
if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
goto select_end;
}
}
if( pWhere ){
if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto select_end;
}
}
if( pHaving ){
if( pGroupBy==0 ){
sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
goto select_end;
}
if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){
goto select_end;
}
}
if( pOrderBy ){
for(i=0; inExpr; i++){
int iCol;
Expr *pE = pOrderBy->a[i].pExpr;
if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
sqliteExprDelete(pE);
pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
}
if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
goto select_end;
}
if( sqliteExprIsConstant(pE) ){
if( sqliteExprIsInteger(pE, &iCol)==0 ){
sqliteErrorMsg(pParse,
"ORDER BY terms must not be non-integer constants");
goto select_end;
}else if( iCol<=0 || iCol>pEList->nExpr ){
sqliteErrorMsg(pParse,
"ORDER BY column number %d out of range - should be "
"between 1 and %d", iCol, pEList->nExpr);
goto select_end;
}
}
}
}
if( pGroupBy ){
for(i=0; inExpr; i++){
int iCol;
Expr *pE = pGroupBy->a[i].pExpr;
if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
sqliteExprDelete(pE);
pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
}
if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
goto select_end;
}
if( sqliteExprIsConstant(pE) ){
if( sqliteExprIsInteger(pE, &iCol)==0 ){
sqliteErrorMsg(pParse,
"GROUP BY terms must not be non-integer constants");
goto select_end;
}else if( iCol<=0 || iCol>pEList->nExpr ){
sqliteErrorMsg(pParse,
"GROUP BY column number %d out of range - should be "
"between 1 and %d", iCol, pEList->nExpr);
goto select_end;
}
}
}
}
/* Begin generating code.
*/
v = sqliteGetVdbe(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
*/
for(i=0; inSrc; i++){
const char *zSavedAuthContext;
int needRestoreContext;
if( pTabList->a[i].pSelect==0 ) continue;
if( pTabList->a[i].zName!=0 ){
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pTabList->a[i].zName;
needRestoreContext = 1;
}else{
needRestoreContext = 0;
}
sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable,
pTabList->a[i].iCursor, p, i, &isAgg);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
}
pTabList = p->pSrc;
pWhere = p->pWhere;
if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){
pOrderBy = p->pOrderBy;
}
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
isDistinct = p->isDistinct;
}
/* Check for the special case of a min() or max() function by itself
** in the result set.
*/
if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
rc = 0;
goto select_end;
}
/* Check to see if this is a subquery that can be "flattened" into its parent.
** If flattening is a possiblity, do so and return immediately.
*/
if( pParent && pParentAgg &&
flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
if( isAgg ) *pParentAgg = 1;
return rc;
}
/* Set the limiter.
*/
computeLimitRegisters(pParse, p);
/* Identify column types if we will be using a callback. This
** step is skipped if the output is going to a destination other
** than a callback.
**
** We have to do this separately from the creation of column names
** above because if the pTabList contains views then they will not
** have been resolved and we will not know the column types until
** now.
*/
if( eDest==SRT_Callback ){
generateColumnTypes(pParse, pTabList, pEList);
}
/* If the output is destined for a temporary table, open that table.
*/
if( eDest==SRT_TempTable ){
sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
}
/* Do an analysis of aggregate expressions.
*/
sqliteAggregateInfoReset(pParse);
if( isAgg || pGroupBy ){
assert( pParse->nAgg==0 );
isAgg = 1;
for(i=0; inExpr; i++){
if( sqliteExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){
goto select_end;
}
}
if( pGroupBy ){
for(i=0; inExpr; i++){
if( sqliteExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){
goto select_end;
}
}
}
if( pHaving && sqliteExprAnalyzeAggregates(pParse, pHaving) ){
goto select_end;
}
if( pOrderBy ){
for(i=0; inExpr; i++){
if( sqliteExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){
goto select_end;
}
}
}
}
/* Reset the aggregator
*/
if( isAgg ){
sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg);
for(i=0; inAgg; i++){
FuncDef *pFunc;
if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
sqliteVdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER);
}
}
if( pGroupBy==0 ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_AggFocus, 0, 0);
}
}
/* Initialize the memory cell to NULL
*/
if( eDest==SRT_Mem ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
}
/* Open a temporary table to use for the distinct set.
*/
if( isDistinct ){
distinct = pParse->nTab++;
sqliteVdbeAddOp(v, OP_OpenTemp, distinct, 1);
}else{
distinct = -1;
}
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0,
pGroupBy ? 0 : &pOrderBy);
if( pWInfo==0 ) goto select_end;
/* Use the standard inner loop if we are not dealing with
** aggregates
*/
if( !isAgg ){
if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
iParm, pWInfo->iContinue, pWInfo->iBreak) ){
goto select_end;
}
}
/* If we are dealing with aggregates, then do the special aggregate
** processing.
*/
else{
AggExpr *pAgg;
if( pGroupBy ){
int lbl1;
for(i=0; inExpr; i++){
sqliteExprCode(pParse, pGroupBy->a[i].pExpr);
}
sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0);
if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pGroupBy);
lbl1 = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){
if( pAgg->isAgg ) continue;
sqliteExprCode(pParse, pAgg->pExpr);
sqliteVdbeAddOp(v, OP_AggSet, 0, i);
}
sqliteVdbeResolveLabel(v, lbl1);
}
for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){
Expr *pE;
int nExpr;
FuncDef *pDef;
if( !pAgg->isAgg ) continue;
assert( pAgg->pFunc!=0 );
assert( pAgg->pFunc->xStep!=0 );
pDef = pAgg->pFunc;
pE = pAgg->pExpr;
assert( pE!=0 );
assert( pE->op==TK_AGG_FUNCTION );
nExpr = sqliteExprCodeExprList(pParse, pE->pList, pDef->includeTypes);
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER);
}
}
/* End the database scan loop.
*/
sqliteWhereEnd(pWInfo);
/* If we are processing aggregates, we need to set up a second loop
** over all of the aggregate values and process them.
*/
if( isAgg ){
int endagg = sqliteVdbeMakeLabel(v);
int startagg;
startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg);
pParse->useAgg = 1;
if( pHaving ){
sqliteExprIfFalse(pParse, pHaving, startagg, 1);
}
if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
iParm, startagg, endagg) ){
goto select_end;
}
sqliteVdbeAddOp(v, OP_Goto, 0, startagg);
sqliteVdbeResolveLabel(v, endagg);
sqliteVdbeAddOp(v, OP_Noop, 0, 0);
pParse->useAgg = 0;
}
/* If there is an ORDER BY clause, then we need to sort the results
** and send them to the callback one by one.
*/
if( pOrderBy ){
generateSortTail(p, v, pEList->nExpr, eDest, iParm);
}
/* 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.
*/
if( pParent ){
assert( pParent->pSrc->nSrc>parentTab );
assert( pParent->pSrc->a[parentTab].pSelect==p );
sqliteSelectDelete(p);
pParent->pSrc->a[parentTab].pSelect = 0;
}
/* The SELECT was successfully coded. Set the return code to 0
** to indicate no errors.
*/
rc = 0;
/* Control jumps to here if an error is encountered above, or upon
** successful coding of the SELECT.
*/
select_end:
sqliteAggregateInfoReset(pParse);
return rc;
}
| select.c | 1957 |
table.c |
Type | Function | Source | Line |
STATIC INT | sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv)
static int sqlite_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 ){
p->rc = SQLITE_NOMEM;
return 1;
}
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; irc = SQLITE_NOMEM;
return 1;
}
strcpy(z, colv[i]);
}
p->azResult[p->nData++] = z;
}
}else if( p->nColumn!=nCol ){
sqliteSetString(&p->zErrMsg,
"sqlite_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; irc = SQLITE_NOMEM;
return 1;
}
strcpy(z, argv[i]);
}
p->azResult[p->nData++] = z;
}
p->nRow++;
}
return 0;
}
| table.c | 38 |
INT | sqlite_get_table( sqlite *db, const char *zSql, char ***pazResult, int *pnRow, int *pnColumn, char **pzErrMsg )
int sqlite_get_table(
sqlite *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 = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);
if( res.azResult ){
res.azResult[0] = (char*)res.nData;
}
if( rc==SQLITE_ABORT ){
sqlite_free_table(&res.azResult[1]);
if( res.zErrMsg ){
if( pzErrMsg ){
free(*pzErrMsg);
*pzErrMsg = res.zErrMsg;
sqliteStrRealloc(pzErrMsg);
}else{
sqliteFree(res.zErrMsg);
}
}
return res.rc;
}
sqliteFree(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite_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 ){
sqlite_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;
}
| table.c | 115 |
VOID | sqlite_free_table( char **azResult )
void sqlite_free_table(
char **azResult /* Result returned from from sqlite_get_table() */
){
if( azResult ){
int i, n;
azResult--;
if( azResult==0 ) return;
n = (int)(long)azResult[0];
for(i=1; itable.c | 189 | |
tokenize.c |
Type | Function | Source | Line |
INT | sqliteKeywordCode(const char *z, int n)
int sqliteKeywordCode(const char *z, int n){
int h, i;
Keyword *p;
static char needInit = 1;
if( needInit ){
/* Initialize the keyword hash table */
sqliteOsEnterMutex();
if( needInit ){
int nk;
nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
for(i=0; iiNext){
p = &aKeywordTable[i-1];
if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
return p->tokenType;
}
}
return TK_ID;
}
/*
** If X is a character that can be used in an identifier and
** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then
** X is always an identifier character. (Hence all UTF-8
** characters can be part of an identifier). isIdChar[X] will
** be 0 for every character in the lower 128 ASCII characters
** that cannot be used as part of an identifier.
**
** In this implementation, an identifier can be a string of
** alphabetic characters, digits, and "_" plus any character
** with the high-order bit set. The latter rule means that
** any sequence of UTF-8 characters or characters taken from
** an extended ISO8859 character set can form an identifier.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
| tokenize.c | 150 |
STATIC INT | sqliteGetToken(const unsigned char *z, int *tokenType)
static int sqliteGetToken(const unsigned char *z, int *tokenType){
int i;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
}
case '-': {
if( z[1]=='-' ){
for(i=2; z[i] && z[i]!='\n'; i++){}
*tokenType = TK_COMMENT;
return i;
}
*tokenType = TK_MINUS;
return 1;
}
case '(': {
*tokenType = TK_LP;
return 1;
}
case ')': {
*tokenType = TK_RP;
return 1;
}
case ';': {
*tokenType = TK_SEMI;
return 1;
}
case '+': {
*tokenType = TK_PLUS;
return 1;
}
case '*': {
*tokenType = TK_STAR;
return 1;
}
case '/': {
if( z[1]!='*' || z[2]==0 ){
*tokenType = TK_SLASH;
return 1;
}
for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
if( z[i] ) i++;
*tokenType = TK_COMMENT;
return i;
}
case '%': {
*tokenType = TK_REM;
return 1;
}
case '=': {
*tokenType = TK_EQ;
return 1 + (z[1]=='=');
}
case '<': {
if( z[1]=='=' ){
*tokenType = TK_LE;
return 2;
}else if( z[1]=='>' ){
*tokenType = TK_NE;
return 2;
}else if( z[1]=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
*tokenType = TK_LT;
return 1;
}
}
case '>': {
if( z[1]=='=' ){
*tokenType = TK_GE;
return 2;
}else if( z[1]=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
*tokenType = TK_GT;
return 1;
}
}
case '!': {
if( z[1]!='=' ){
*tokenType = TK_ILLEGAL;
return 2;
}else{
*tokenType = TK_NE;
return 2;
}
}
case '|': {
if( z[1]!='|' ){
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
return 2;
}
}
case ',': {
*tokenType = TK_COMMA;
return 1;
}
case '&': {
*tokenType = TK_BITAND;
return 1;
}
case '~': {
*tokenType = TK_BITNOT;
return 1;
}
case '\'': case '"': {
int delim = z[0];
for(i=1; z[i]; i++){
if( z[i]==delim ){
if( z[i+1]==delim ){
i++;
}else{
break;
}
}
}
if( z[i] ) i++;
*tokenType = TK_STRING;
return i;
}
case '.': {
*tokenType = TK_DOT;
return 1;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
if( z[i]=='.' && isdigit(z[i+1]) ){
i += 2;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
( isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
)
){
i += 2;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
return i;
}
case '[': {
for(i=1; z[i] && z[i-1]!=']'; i++){}
*tokenType = TK_ID;
return i;
}
case '?': {
*tokenType = TK_VARIABLE;
return 1;
}
default: {
if( (*z&0x80)==0 && !isIdChar[*z] ){
break;
}
for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
*tokenType = sqliteKeywordCode((char*)z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
return 1;
}
| tokenize.c | 214 |
} INT | sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg)
int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int nErr = 0;
int i;
void *pEngine;
int tokenType;
int lastTokenParsed = -1;
sqlite *db = pParse->db;
extern void *sqliteParserAlloc(void*(*)(int));
extern void sqliteParserFree(void*, void(*)(void*));
extern int sqliteParser(void*, int, Token, Parse*);
db->flags &= ~SQLITE_Interrupt;
pParse->rc = SQLITE_OK;
i = 0;
pEngine = sqliteParserAlloc((void*(*)(int))malloc);
if( pEngine==0 ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
return 1;
}
pParse->sLastToken.dyn = 0;
pParse->zTail = zSql;
while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
assert( pParse->sLastToken.dyn==0 );
pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
i += pParse->sLastToken.n;
switch( tokenType ){
case TK_SPACE:
case TK_COMMENT: {
if( (db->flags & SQLITE_Interrupt)!=0 ){
pParse->rc = SQLITE_INTERRUPT;
sqliteSetString(pzErrMsg, "interrupt", (char*)0);
goto abort_parse;
}
break;
}
case TK_ILLEGAL: {
sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1,
pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
nErr++;
goto abort_parse;
}
case TK_SEMI: {
pParse->zTail = &zSql[i];
/* Fall thru into the default case */
}
default: {
sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
if( pParse->rc!=SQLITE_OK ){
goto abort_parse;
}
break;
}
}
}
abort_parse:
if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
if( lastTokenParsed!=TK_SEMI ){
sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
}
sqliteParserFree(pEngine, free);
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc),
(char*)0);
}
if( pParse->zErrMsg ){
if( pzErrMsg && *pzErrMsg==0 ){
*pzErrMsg = pParse->zErrMsg;
}else{
sqliteFree(pParse->zErrMsg);
}
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 ){
sqliteVdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
if( pParse->pNewTable ){
sqliteDeleteTable(pParse->db, pParse->pNewTable);
pParse->pNewTable = 0;
}
if( pParse->pNewTrigger ){
sqliteDeleteTrigger(pParse->pNewTrigger);
pParse->pNewTrigger = 0;
}
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
return nErr;
}
| tokenize.c | 391 |
INT | sqlite_complete(const char *zSql)
int sqlite_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
/* The following matrix defines the transition from one state to another
** according to what token is seen. trans[state][token] returns the
** next state.
*/
static const u8 trans[7][8] = {
/* Token: */
/* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
/* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
/* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
/* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, },
/* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, },
/* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, },
/* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, },
/* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, },
};
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
if( isIdChar[(u8)*zSql] ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){}
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==0;
}
| tokenize.c | 508 |
trigger.c |
Type | Function | Source | Line |
VOID | sqliteDeleteTriggerStep(TriggerStep *pTriggerStep)
void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
sqliteExprDelete(pTmp->pWhere);
sqliteExprListDelete(pTmp->pExprList);
sqliteSelectDelete(pTmp->pSelect);
sqliteIdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
}
}
| trigger.c | 15 |
VOID | sqliteBeginTrigger( Parse *pParse, Token *pName, int tr_tm, int op, IdList *pColumns, SrcList *pTableName, int foreach, Expr *pWhen, int isTemp )
void sqliteBeginTrigger(
Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
Token *pName, /* The name of the trigger */
int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
IdList *pColumns, /* column list if this is an UPDATE OF trigger */
SrcList *pTableName,/* The name of the table/view the trigger applies to */
int foreach, /* One of TK_ROW or TK_STATEMENT */
Expr *pWhen, /* WHEN clause */
int isTemp /* True if the TEMPORARY keyword is present */
){
Trigger *nt;
Table *tab;
char *zName = 0; /* Name of the trigger */
sqlite *db = pParse->db;
int iDb; /* When database to store the trigger in */
DbFixer sFix;
/* Check that:
** 1. the trigger name does not already exist.
** 2. the table (or view) does exist in the same database as the trigger.
** 3. that we are not trying to create a trigger on the sqlite_master table
** 4. That we are not trying to create an INSTEAD OF trigger on a table.
** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
*/
if( sqlite_malloc_failed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( db->init.busy
&& sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
&& sqliteFixSrcList(&sFix, pTableName)
){
goto trigger_cleanup;
}
tab = sqliteSrcListLookup(pParse, pTableName);
if( !tab ){
goto trigger_cleanup;
}
iDb = isTemp ? 1 : tab->iDb;
if( iDb>=2 && !db->init.busy ){
sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
"database %s", db->aDb[tab->iDb].zName);
goto trigger_cleanup;
}
zName = sqliteStrNDup(pName->z, pName->n);
sqliteDequote(zName);
if( sqliteHashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
sqliteErrorMsg(pParse, "trigger %T already exists", pName);
goto trigger_cleanup;
}
if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
sqliteErrorMsg(pParse, "cannot create trigger on system table");
pParse->nErr++;
goto trigger_cleanup;
}
if( tab->pSelect && tr_tm != TK_INSTEAD ){
sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
goto trigger_cleanup;
}
if( !tab->pSelect && tr_tm == TK_INSTEAD ){
sqliteErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName, 0);
goto trigger_cleanup;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_CREATE_TRIGGER;
const char *zDb = db->aDb[tab->iDb].zName;
const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
goto trigger_cleanup;
}
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
goto trigger_cleanup;
}
}
#endif
/* INSTEAD OF triggers can only appear on views and BEGIN triggers
** cannot appear on views. So we might as well translate every
** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
** elsewhere.
*/
if (tr_tm == TK_INSTEAD){
tr_tm = TK_BEFORE;
}
/* Build the Trigger object */
nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
if( nt==0 ) goto trigger_cleanup;
nt->name = zName;
zName = 0;
nt->table = sqliteStrDup(pTableName->a[0].zName);
if( sqlite_malloc_failed ) goto trigger_cleanup;
nt->iDb = iDb;
nt->iTabDb = tab->iDb;
nt->op = op;
nt->tr_tm = tr_tm;
nt->pWhen = sqliteExprDup(pWhen);
nt->pColumns = sqliteIdListDup(pColumns);
nt->foreach = foreach;
sqliteTokenCopy(&nt->nameToken,pName);
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = nt;
trigger_cleanup:
sqliteFree(zName);
sqliteSrcListDelete(pTableName);
sqliteIdListDelete(pColumns);
sqliteExprDelete(pWhen);
}
| trigger.c | 33 |
VOID | sqliteFinishTrigger( Parse *pParse, TriggerStep *pStepList, Token *pAll )
void sqliteFinishTrigger(
Parse *pParse, /* Parser context */
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *nt = 0; /* The trigger whose construction is finishing up */
sqlite *db = pParse->db; /* The database */
DbFixer sFix;
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
nt = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
nt->step_list = pStepList;
while( pStepList ){
pStepList->pTrig = nt;
pStepList = pStepList->pNext;
}
if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)
&& sqliteFixTriggerStep(&sFix, nt->step_list) ){
goto triggerfinish_cleanup;
}
/* if we are not initializing, and this trigger is not on a TEMP table,
** build the sqlite_master entry
*/
if( !db->init.busy ){
static VdbeOpList insertTrig[] = {
{ OP_NewRecno, 0, 0, 0 },
{ OP_String, 0, 0, "trigger" },
{ OP_String, 0, 0, 0 }, /* 2: trigger name */
{ OP_String, 0, 0, 0 }, /* 3: table name */
{ OP_Integer, 0, 0, 0 },
{ OP_String, 0, 0, 0 }, /* 5: SQL */
{ OP_MakeRecord, 5, 0, 0 },
{ OP_PutIntKey, 0, 0, 0 },
};
int addr;
Vdbe *v;
/* Make an entry in the sqlite_master table */
v = sqliteGetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteOpenMasterTable(v, nt->iDb);
addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
if( nt->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteEndWriteOperation(pParse);
}
if( !pParse->explain ){
Table *pTab;
sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
nt->name, strlen(nt->name)+1, nt);
pTab = sqliteLocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
assert( pTab!=0 );
nt->pNext = pTab->pTrigger;
pTab->pTrigger = nt;
nt = 0;
}
triggerfinish_cleanup:
sqliteDeleteTrigger(nt);
sqliteDeleteTrigger(pParse->pNewTrigger);
pParse->pNewTrigger = 0;
sqliteDeleteTriggerStep(pStepList);
}
| trigger.c | 155 |
STATIC VOID | sqlitePersistTriggerStep(TriggerStep *p)
static void sqlitePersistTriggerStep(TriggerStep *p){
if( p->target.z ){
p->target.z = sqliteStrNDup(p->target.z, p->target.n);
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqliteSelectDup(p->pSelect);
sqliteSelectDelete(p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqliteExprDup(p->pWhere);
sqliteExprDelete(p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqliteExprListDup(p->pExprList);
sqliteExprListDelete(p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqliteIdListDup(p->pIdList);
sqliteIdListDelete(p->pIdList);
p->pIdList = pNew;
}
}
| trigger.c | 232 |
TRIGGERSTEP | sqliteTriggerSelectStep(Select *pSelect)
TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
| trigger.c | 269 |
TRIGGERSTEP | sqliteTriggerInsertStep( Token *pTableName, IdList *pColumn, ExprList *pEList, Select *pSelect, int orconf )
TriggerStep *sqliteTriggerInsertStep(
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
Select *pSelect, /* A SELECT statement that supplies values */
int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
assert(pEList == 0 || pSelect == 0);
assert(pEList != 0 || pSelect != 0);
pTriggerStep->op = TK_INSERT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->target = *pTableName;
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
| trigger.c | 288 |
TRIGGERSTEP | sqliteTriggerUpdateStep( Token *pTableName, ExprList *pEList, Expr *pWhere, int orconf )
TriggerStep *sqliteTriggerUpdateStep(
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
pTriggerStep->op = TK_UPDATE;
pTriggerStep->target = *pTableName;
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
| trigger.c | 319 |
TRIGGERSTEP | sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere)
TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
pTriggerStep->op = TK_DELETE;
pTriggerStep->target = *pTableName;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
| trigger.c | 343 |
VOID | sqliteDeleteTrigger(Trigger *pTrigger)
void sqliteDeleteTrigger(Trigger *pTrigger){
if( pTrigger==0 ) return;
sqliteDeleteTriggerStep(pTrigger->step_list);
sqliteFree(pTrigger->name);
sqliteFree(pTrigger->table);
sqliteExprDelete(pTrigger->pWhen);
sqliteIdListDelete(pTrigger->pColumns);
if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
sqliteFree(pTrigger);
}
| trigger.c | 361 |
VOID | sqliteDropTrigger(Parse *pParse, SrcList *pName)
void sqliteDropTrigger(Parse *pParse, SrcList *pName){
Trigger *pTrigger;
int i;
const char *zDb;
const char *zName;
int nName;
sqlite *db = pParse->db;
if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
assert( pName->nSrc==1 );
zDb = pName->a[0].zDatabase;
zName = pName->a[0].zName;
nName = strlen(zName);
for(i=0; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
if( pTrigger ) break;
}
if( !pTrigger ){
sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
goto drop_trigger_cleanup;
}
sqliteDropTriggerPtr(pParse, pTrigger, 0);
drop_trigger_cleanup:
sqliteSrcListDelete(pName);
}
| trigger.c | 375 |
VOID | sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested)
void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
Table *pTable;
Vdbe *v;
sqlite *db = pParse->db;
assert( pTrigger->iDbnDb );
if( pTrigger->iDb>=2 ){
sqliteErrorMsg(pParse, "triggers may not be removed from "
"auxiliary database %s", db->aDb[pTrigger->iDb].zName);
return;
}
pTable = sqliteFindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
assert(pTable);
assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[pTrigger->iDb].zName;
const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
return;
}
}
#endif
/* Generate code to destroy the database record of the trigger.
*/
if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
int base;
static VdbeOpList dropTrigger[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String, 0, 0, 0}, /* 1 */
{ OP_Column, 0, 1, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_String, 0, 0, "trigger"},
{ OP_Column, 0, 0, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
};
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteOpenMasterTable(v, pTrigger->iDb);
base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
sqliteVdbeChangeP3(v, base+1, pTrigger->name, 0);
if( pTrigger->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteEndWriteOperation(pParse);
}
/*
* If this is not an "explain", then delete the trigger structure.
*/
if( !pParse->explain ){
const char *zName = pTrigger->name;
int nName = strlen(zName);
if( pTable->pTrigger == pTrigger ){
pTable->pTrigger = pTrigger->pNext;
}else{
Trigger *cc = pTable->pTrigger;
while( cc ){
if( cc->pNext == pTrigger ){
cc->pNext = cc->pNext->pNext;
break;
}
cc = cc->pNext;
}
assert(cc);
}
sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
sqliteDeleteTrigger(pTrigger);
}
}
| trigger.c | 417 |
STATIC INT | checkColumnOverLap(IdList *pIdList, ExprList *pEList)
static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
int e;
if( !pIdList || !pEList ) return 1;
for(e=0; enExpr; e++){
if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
}
return 0;
}
/* A global variable that is TRUE if we should always set up temp tables for
* for triggers, even if there are no triggers to code. This is used to test
* how much overhead the triggers algorithm is causing.
*
* This flag can be set or cleared using the "trigger_overhead_test" pragma.
* The pragma is not documented since it is not really part of the interface
* to SQLite, just the test procedure.
*/
int always_code_trigger_setup = 0;
| trigger.c | 500 |
INT | sqliteTriggersExist( Parse *pParse, Trigger *pTrigger, int op, int tr_tm, int foreach, ExprList *pChanges )
int sqliteTriggersExist(
Parse *pParse, /* Used to check for recursive triggers */
Trigger *pTrigger, /* A list of triggers associated with a table */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
int tr_tm, /* one of TK_BEFORE, TK_AFTER */
int foreach, /* one of TK_ROW or TK_STATEMENT */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
Trigger * pTriggerCursor;
if( always_code_trigger_setup ){
return 1;
}
pTriggerCursor = pTrigger;
while( pTriggerCursor ){
if( pTriggerCursor->op == op &&
pTriggerCursor->tr_tm == tr_tm &&
pTriggerCursor->foreach == foreach &&
checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
TriggerStack * ss;
ss = pParse->trigStack;
while( ss && ss->pTrigger != pTrigger ){
ss = ss->pNext;
}
if( !ss )return 1;
}
pTriggerCursor = pTriggerCursor->pNext;
}
return 0;
}
| trigger.c | 528 |
STATIC SRCLIST | targetSrcList( Parse *pParse, TriggerStep *pStep )
static SrcList *targetSrcList(
Parse *pParse, /* The parsing context */
TriggerStep *pStep /* The trigger containing the target token */
){
Token sDb; /* Dummy database name token */
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
iDb = pStep->pTrig->iDb;
if( iDb==0 || iDb>=2 ){
assert( iDbdb->nDb );
sDb.z = pParse->db->aDb[iDb].zName;
sDb.n = strlen(sDb.z);
pSrc = sqliteSrcListAppend(0, &sDb, &pStep->target);
} else {
pSrc = sqliteSrcListAppend(0, &pStep->target, 0);
}
return pSrc;
}
| trigger.c | 566 |
STATIC INT | codeTriggerProgram( Parse *pParse, TriggerStep *pStepList, int orconfin )
static int codeTriggerProgram(
Parse *pParse, /* The parser context */
TriggerStep *pStepList, /* List of statements inside the trigger body */
int orconfin /* Conflict algorithm. (OE_Abort, etc) */
){
TriggerStep * pTriggerStep = pStepList;
int orconf;
while( pTriggerStep ){
int saveNTab = pParse->nTab;
orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
assert(ss);
assert(ss->pSrc);
sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
sqliteSelectDelete(ss);
break;
}
case TK_UPDATE: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
sqliteUpdate(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
sqliteExprDup(pTriggerStep->pWhere), orconf);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
break;
}
case TK_INSERT: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteInsert(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
sqliteSelectDup(pTriggerStep->pSelect),
sqliteIdListDup(pTriggerStep->pIdList), orconf);
break;
}
case TK_DELETE: {
SrcList *pSrc;
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
break;
}
default:
assert(0);
}
pParse->nTab = saveNTab;
pTriggerStep = pTriggerStep->pNext;
}
return 0;
}
| trigger.c | 596 |
INT | sqliteCodeRowTrigger( Parse *pParse, int op, ExprList *pChanges, int tr_tm, Table *pTab, int newIdx, int oldIdx, int orconf, int ignoreJump )
int sqliteCodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
int tr_tm, /* One of TK_BEFORE, TK_AFTER */
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
int orconf, /* ON CONFLICT policy */
int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
){
Trigger * pTrigger;
TriggerStack * pTriggerStack;
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
assert(newIdx != -1 || oldIdx != -1);
pTrigger = pTab->pTrigger;
while( pTrigger ){
int fire_this = 0;
/* determine whether we should code this trigger */
if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
pTrigger->foreach == TK_ROW ){
fire_this = 1;
pTriggerStack = pParse->trigStack;
while( pTriggerStack ){
if( pTriggerStack->pTrigger == pTrigger ){
fire_this = 0;
}
pTriggerStack = pTriggerStack->pNext;
}
if( op == TK_UPDATE && pTrigger->pColumns &&
!checkColumnOverLap(pTrigger->pColumns, pChanges) ){
fire_this = 0;
}
}
if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
int endTrigger;
SrcList dummyTablist;
Expr * whenExpr;
AuthContext sContext;
dummyTablist.nSrc = 0;
/* Push an entry on to the trigger stack */
pTriggerStack->pTrigger = pTrigger;
pTriggerStack->newIdx = newIdx;
pTriggerStack->oldIdx = oldIdx;
pTriggerStack->pTab = pTab;
pTriggerStack->pNext = pParse->trigStack;
pTriggerStack->ignoreJump = ignoreJump;
pParse->trigStack = pTriggerStack;
sqliteAuthContextPush(pParse, &sContext, pTrigger->name);
/* code the WHEN clause */
endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
whenExpr = sqliteExprDup(pTrigger->pWhen);
if( sqliteExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
pParse->trigStack = pParse->trigStack->pNext;
sqliteFree(pTriggerStack);
sqliteExprDelete(whenExpr);
return 1;
}
sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
sqliteExprDelete(whenExpr);
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPush, 0, 0);
codeTriggerProgram(pParse, pTrigger->step_list, orconf);
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPop, 0, 0);
/* Pop the entry off the trigger stack */
pParse->trigStack = pParse->trigStack->pNext;
sqliteAuthContextPop(&sContext);
sqliteFree(pTriggerStack);
sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
}
pTrigger = pTrigger->pNext;
}
return 0;
}
| trigger.c | 659 |
update.c |
Type | Function | Source | Line |
VOID | sqliteUpdate( Parse *pParse, SrcList *pTabList, ExprList *pChanges, Expr *pWhere, int onError )
void sqliteUpdate(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table in which we should change things */
ExprList *pChanges, /* Things to be changed */
Expr *pWhere, /* The WHERE clause. May be null */
int onError /* How to handle constraint errors */
){
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
int loopStart; /* VDBE instruction address of the start of the loop */
int jumpInst; /* Addr of VDBE instruction to jump out of loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
int nIdx; /* Number of indices that need updating */
int nIdxTotal; /* Total number of indices */
int iCur; /* VDBE Cursor number of pTab */
sqlite *db; /* The database structure */
Index **apIdx = 0; /* An array of indices that need updating too */
char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
int chngRecno; /* True if the record number is being changed */
Expr *pRecnoExpr; /* Expression defining the new record number */
int openAll; /* True if all indices need to be opened */
int isView; /* Trying to update a view */
int iStackDepth; /* Index of memory cell holding stack depth */
AuthContext sContext; /* The authorization context */
int before_triggers; /* True if there are any BEFORE triggers */
int after_triggers; /* True if there are any AFTER triggers */
int row_triggers_exist = 0; /* True if any row triggers exist */
int newIdx = -1; /* index of trigger "new" temp table */
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
db = pParse->db;
assert( pTabList->nSrc==1 );
iStackDepth = pParse->nMem++;
/* Locate the table which we want to update.
*/
pTab = sqliteSrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
row_triggers_exist = before_triggers || after_triggers;
isView = pTab->pSelect!=0;
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
goto update_cleanup;
}
if( isView ){
if( sqliteViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
}
aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; inCol; i++) aXRef[i] = -1;
/* If there are FOR EACH ROW triggers, allocate cursors for the
** special OLD and NEW tables
*/
if( row_triggers_exist ){
newIdx = pParse->nTab++;
oldIdx = pParse->nTab++;
}
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
pTabList->a[0].iCursor = iCur = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
}
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
** that column.
*/
chngRecno = 0;
for(i=0; inExpr; i++){
if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
goto update_cleanup;
}
for(j=0; jnCol; j++){
if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( j==pTab->iPKey ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
}
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
if( sqliteIsRowid(pChanges->a[i].zName) ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
}else{
sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
goto update_cleanup;
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
aXRef[j] = -1;
}
}
#endif
}
/* Allocate memory for the array apIdx[] and fill it with pointers to every
** index that needs to be updated. Indices only need updating if their
** key includes one of the columns named in pChanges or if the record
** number of the original table entry is changing.
*/
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
if( chngRecno ){
i = 0;
}else {
for(i=0; inColumn; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
}
}
if( inColumn ) nIdx++;
}
if( nIdxTotal>0 ){
apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
if( apIdx==0 ) goto update_cleanup;
aIdxUsed = (char*)&apIdx[nIdx];
}
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( chngRecno ){
i = 0;
}else{
for(i=0; inColumn; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
}
}
if( inColumn ){
apIdx[nIdx++] = pIdx;
aIdxUsed[j] = 1;
}else{
aIdxUsed[j] = 0;
}
}
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( pWhere ){
if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto update_cleanup;
}
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
if( v==0 ) goto update_cleanup;
sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
/* If we are trying to update a view, construct that view into
** a temporary table.
*/
if( isView ){
Select *pView;
pView = sqliteSelectDup(pTab->pSelect);
sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqliteSelectDelete(pView);
}
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
if( pWInfo==0 ) goto update_cleanup;
/* Remember the index of every item to be updated.
*/
sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
/* End the database scan loop.
*/
sqliteWhereEnd(pWInfo);
/* Initialize the count of updated rows
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
}
if( row_triggers_exist ){
/* Create pseudo-tables for NEW and OLD
*/
sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
/* The top of the update loop for when there are triggers.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
}
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
/* Generate the OLD table
*/
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
/* Generate the NEW table
*/
if( chngRecno ){
sqliteExprCode(pParse, pRecnoExpr);
}else{
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
}
for(i=0; inCol; i++){
if( i==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqliteVdbeAddOp(v, OP_Column, iCur, i);
}else{
sqliteExprCode(pParse, pChanges->a[j].pExpr);
}
}
sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
}
/* Fire the BEFORE and INSTEAD OF triggers
*/
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
newIdx, oldIdx, onError, loopStart) ){
goto update_cleanup;
}
}
if( !isView ){
/*
** Open every index that needs updating. Note that if any
** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum);
if( onError==OE_Replace ){
openAll = 1;
}else{
openAll = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_Replace ){
openAll = 1;
break;
}
}
}
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
assert( pParse->nTab>iCur+i+1 );
}
}
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** might not change and we will need to copy the old value.
** Also, the old data is needed to delete the old index entires.
** So make the cursor point at the old record.
*/
if( !row_triggers_exist ){
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
}
sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
/* If the record number will change, push the record number as it
** will be after the update. (The old record number is currently
** on top of the stack.)
*/
if( chngRecno ){
sqliteExprCode(pParse, pRecnoExpr);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
}
/* Compute new data for this record.
*/
for(i=0; inCol; i++){
if( i==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqliteVdbeAddOp(v, OP_Column, iCur, i);
}else{
sqliteExprCode(pParse, pChanges->a[j].pExpr);
}
}
/* Do constraint checks
*/
sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
onError, loopStart);
/* Delete the old indices for the current record.
*/
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);
/* If changing the record number, delete the old record.
*/
if( chngRecno ){
sqliteVdbeAddOp(v, OP_Delete, iCur, 0);
}
/* Create the new index entries and the new record.
*/
sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
}
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
}
/* If there are triggers, close all the cursors after each iteration
** through the loop. The fire the after triggers.
*/
if( row_triggers_exist ){
if( !isView ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] )
sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
}
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
newIdx, oldIdx, onError, loopStart) ){
goto update_cleanup;
}
}
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !row_triggers_exist ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
}else{
sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were changed.
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
}
update_cleanup:
sqliteAuthContextPop(&sContext);
sqliteFree(apIdx);
sqliteFree(aXRef);
sqliteSrcListDelete(pTabList);
sqliteExprListDelete(pChanges);
sqliteExprDelete(pWhere);
return;
}
| update.c | 19 |
util.c |
Type | Function | Source | Line |
VOID | sqliteMalloc_(int n, int bZero, char *zFile, int line)
void *sqliteMalloc_(int n, int bZero, char *zFile, int line){
void *p;
int *pi;
int i, k;
if( sqlite_iMallocFail>=0 ){
sqlite_iMallocFail--;
if( sqlite_iMallocFail==0 ){
sqlite_malloc_failed++;
#if MEMORY_DEBUG>1
fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
n, zFile,line);
#endif
sqlite_iMallocFail--;
return 0;
}
}
if( n==0 ) return 0;
k = (n+sizeof(int)-1)/sizeof(int);
pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
if( pi==0 ){
sqlite_malloc_failed++;
return 0;
}
sqlite_nMalloc++;
for(i=0; i1
fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
++memcnt, n, (int)p, zFile,line);
#endif
return p;
}
| util.c | 51 |
VOID | sqliteCheckMemory(void *p, int N)
void sqliteCheckMemory(void *p, int N){
int *pi = p;
int n, i, k;
pi -= N_GUARD+1;
for(i=0; i=0 && Nutil.c | 91 | |
VOID | sqliteFree_(void *p, char *zFile, int line)
void sqliteFree_(void *p, char *zFile, int line){
if( p ){
int *pi, i, k, n;
pi = p;
pi -= N_GUARD+1;
sqlite_nFree++;
for(i=0; i1
fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n",
++memcnt, n, (int)p, zFile,line);
#endif
free(pi);
}
}
| util.c | 113 |
VOID | sqliteRealloc_(void *oldP, int n, char *zFile, int line)
void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){
int *oldPi, *pi, i, k, oldN, oldK;
void *p;
if( oldP==0 ){
return sqliteMalloc_(n,1,zFile,line);
}
if( n==0 ){
sqliteFree_(oldP,zFile,line);
return 0;
}
oldPi = oldP;
oldPi -= N_GUARD+1;
if( oldPi[0]!=0xdead1122 ){
fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP);
return 0;
}
oldN = oldPi[N_GUARD];
oldK = (oldN+sizeof(int)-1)/sizeof(int);
for(i=0; ioldN ? oldN : n);
if( n>oldN ){
memset(&((char*)p)[oldN], 0, n-oldN);
}
memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
free(oldPi);
#if MEMORY_DEBUG>1
fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
#endif
return p;
}
| util.c | 145 |
VOID | sqliteStrRealloc(char **pz)
void sqliteStrRealloc(char **pz){
char *zNew;
if( pz==0 || *pz==0 ) return;
zNew = malloc( strlen(*pz) + 1 );
if( zNew==0 ){
sqlite_malloc_failed++;
sqliteFree(*pz);
*pz = 0;
}
strcpy(zNew, *pz);
sqliteFree(*pz);
*pz = zNew;
}
| util.c | 198 |
CHAR | sqliteStrDup_(const char *z, char *zFile, int line)
char *sqliteStrDup_(const char *z, char *zFile, int line){
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMalloc_(strlen(z)+1, 0, zFile, line);
if( zNew ) strcpy(zNew, z);
return zNew;
}
| util.c | 220 |
CHAR | sqliteStrNDup_(const char *z, int n, char *zFile, int line)
char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMalloc_(n+1, 0, zFile, line);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;
}
return zNew;
}
#endif /* MEMORY_DEBUG */
| util.c | 230 |
VOID | sqliteMalloc(int n)
void *sqliteMalloc(int n){
void *p;
if( (p = malloc(n))==0 ){
if( n>0 ) sqlite_malloc_failed++;
}else{
memset(p, 0, n);
}
return p;
}
| util.c | 248 |
VOID | sqliteMallocRaw(int n)
void *sqliteMallocRaw(int n){
void *p;
if( (p = malloc(n))==0 ){
if( n>0 ) sqlite_malloc_failed++;
}
return p;
}
| util.c | 262 |
VOID | sqliteFree(void *p)
void sqliteFree(void *p){
if( p ){
free(p);
}
}
| util.c | 274 |
VOID | sqliteRealloc(void *p, int n)
void *sqliteRealloc(void *p, int n){
void *p2;
if( p==0 ){
return sqliteMalloc(n);
}
if( n==0 ){
sqliteFree(p);
return 0;
}
p2 = realloc(p, n);
if( p2==0 ){
sqlite_malloc_failed++;
}
return p2;
}
| util.c | 283 |
CHAR | sqliteStrDup(const char *z)
char *sqliteStrDup(const char *z){
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMallocRaw(strlen(z)+1);
if( zNew ) strcpy(zNew, z);
return zNew;
}
| util.c | 304 |
CHAR | sqliteStrNDup(const char *z, int n)
char *sqliteStrNDup(const char *z, int n){
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMallocRaw(n+1);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;
}
return zNew;
}
| util.c | 314 |
VOID | sqliteSetString(char **pz, const char *zFirst, ...)
void sqliteSetString(char **pz, const char *zFirst, ...){
va_list ap;
int nByte;
const char *z;
char *zResult;
if( pz==0 ) return;
nByte = strlen(zFirst) + 1;
va_start(ap, zFirst);
while( (z = va_arg(ap, const char*))!=0 ){
nByte += strlen(z);
}
va_end(ap);
sqliteFree(*pz);
*pz = zResult = sqliteMallocRaw( nByte );
if( zResult==0 ){
return;
}
strcpy(zResult, zFirst);
zResult += strlen(zResult);
va_start(ap, zFirst);
while( (z = va_arg(ap, const char*))!=0 ){
strcpy(zResult, z);
zResult += strlen(zResult);
}
va_end(ap);
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1
fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
#endif
#endif
}
| util.c | 326 |
VOID | sqliteSetNString(char **pz, ...)
void sqliteSetNString(char **pz, ...){
va_list ap;
int nByte;
const char *z;
char *zResult;
int n;
if( pz==0 ) return;
nByte = 0;
va_start(ap, pz);
while( (z = va_arg(ap, const char*))!=0 ){
n = va_arg(ap, int);
if( n<=0 ) n = strlen(z);
nByte += n;
}
va_end(ap);
sqliteFree(*pz);
*pz = zResult = sqliteMallocRaw( nByte + 1 );
if( zResult==0 ) return;
va_start(ap, pz);
while( (z = va_arg(ap, const char*))!=0 ){
n = va_arg(ap, int);
if( n<=0 ) n = strlen(z);
strncpy(zResult, z, n);
zResult += n;
}
*zResult = 0;
#ifdef MEMORY_DEBUG
#if MEMORY_DEBUG>1
fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
#endif
#endif
va_end(ap);
}
| util.c | 366 |
VOID | sqliteErrorMsg(Parse *pParse, const char *zFormat, ...)
void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
pParse->nErr++;
sqliteFree(pParse->zErrMsg);
va_start(ap, zFormat);
pParse->zErrMsg = sqliteVMPrintf(zFormat, ap);
va_end(ap);
}
| util.c | 408 |
VOID | sqliteDequote(char *z)
void sqliteDequote(char *z){
int quote;
int i, j;
if( z==0 ) return;
quote = z[0];
switch( quote ){
case '\'': break;
case '"': break;
case '[': quote = ']'; break;
default: return;
}
for(i=1, j=0; z[i]; i++){
if( z[i]==quote ){
if( z[i+1]==quote ){
z[j++] = quote;
i++;
}else{
z[j++] = 0;
break;
}
}else{
z[j++] = z[i];
}
}
}
/* An array to map all upper-case characters into their corresponding
** lower-case character.
*/
static unsigned char UpperToLower[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
252,253,254,255
};
| util.c | 427 |
INT | sqliteHashNoCase(const char *z, int n)
int sqliteHashNoCase(const char *z, int n){
int h = 0;
if( n<=0 ) n = strlen(z);
while( n > 0 ){
h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
n--;
}
return h & 0x7fffffff;
}
| util.c | 484 |
INT | sqliteStrICmp(const char *zLeft, const char *zRight)
int sqliteStrICmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
return UpperToLower[*a] - UpperToLower[*b];
}
| util.c | 498 |
INT | sqliteStrNICmp(const char *zLeft, const char *zRight, int N)
int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
register unsigned char *a, *b;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}
| util.c | 509 |
INT | sqliteIsNumber(const char *z)
int sqliteIsNumber(const char *z){
if( *z=='-' || *z=='+' ) z++;
if( !isdigit(*z) ){
return 0;
}
z++;
while( isdigit(*z) ){ z++; }
if( *z=='.' ){
z++;
if( !isdigit(*z) ) return 0;
while( isdigit(*z) ){ z++; }
}
if( *z=='e' || *z=='E' ){
z++;
if( *z=='+' || *z=='-' ) z++;
if( !isdigit(*z) ) return 0;
while( isdigit(*z) ){ z++; }
}
return *z==0;
}
| util.c | 517 |
DOUBLE | sqliteAtoF(const char *z, const char **pzEnd)
double sqliteAtoF(const char *z, const char **pzEnd){
int sign = 1;
LONGDOUBLE_TYPE v1 = 0.0;
if( *z=='-' ){
sign = -1;
z++;
}else if( *z=='+' ){
z++;
}
while( isdigit(*z) ){
v1 = v1*10.0 + (*z - '0');
z++;
}
if( *z=='.' ){
LONGDOUBLE_TYPE divisor = 1.0;
z++;
while( isdigit(*z) ){
v1 = v1*10.0 + (*z - '0');
divisor *= 10.0;
z++;
}
v1 /= divisor;
}
if( *z=='e' || *z=='E' ){
int esign = 1;
int eval = 0;
LONGDOUBLE_TYPE scale = 1.0;
z++;
if( *z=='-' ){
esign = -1;
z++;
}else if( *z=='+' ){
z++;
}
while( isdigit(*z) ){
eval = eval*10 + *z - '0';
z++;
}
while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; }
while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; }
while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; }
while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; }
if( esign<0 ){
v1 /= scale;
}else{
v1 *= scale;
}
}
if( pzEnd ) *pzEnd = z;
return sign<0 ? -v1 : v1;
}
| util.c | 544 |
INT | sqliteFitsIn32Bits(const char *zNum)
int sqliteFitsIn32Bits(const char *zNum){
int i, c;
if( *zNum=='-' || *zNum=='+' ) zNum++;
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
}
| util.c | 608 |
INT | sqliteCompare(const char *atext, const char *btext)
int sqliteCompare(const char *atext, const char *btext){
int result;
int isNumA, isNumB;
if( atext==0 ){
return -1;
}else if( btext==0 ){
return 1;
}
isNumA = sqliteIsNumber(atext);
isNumB = sqliteIsNumber(btext);
if( isNumA ){
if( !isNumB ){
result = -1;
}else{
double rA, rB;
rA = sqliteAtoF(atext, 0);
rB = sqliteAtoF(btext, 0);
if( rArB ){
result = +1;
}else{
result = 0;
}
}
}else if( isNumB ){
result = +1;
}else {
result = strcmp(atext, btext);
}
return result;
}
| util.c | 626 |
INT | sqliteSortCompare(const char *a, const char *b)
int sqliteSortCompare(const char *a, const char *b){
int res = 0;
int isNumA, isNumB;
int dir = 0;
while( res==0 && *a && *b ){
if( a[0]=='N' || b[0]=='N' ){
if( a[0]==b[0] ){
a += 2;
b += 2;
continue;
}
if( a[0]=='N' ){
dir = b[0];
res = -1;
}else{
dir = a[0];
res = +1;
}
break;
}
assert( a[0]==b[0] );
if( (dir=a[0])=='A' || a[0]=='D' ){
res = strcmp(&a[1],&b[1]);
if( res ) break;
}else{
isNumA = sqliteIsNumber(&a[1]);
isNumB = sqliteIsNumber(&b[1]);
if( isNumA ){
double rA, rB;
if( !isNumB ){
res = -1;
break;
}
rA = sqliteAtoF(&a[1], 0);
rB = sqliteAtoF(&b[1], 0);
if( rArB ){
res = +1;
break;
}
}else if( isNumB ){
res = +1;
break;
}else{
res = strcmp(&a[1],&b[1]);
if( res ) break;
}
}
a += strlen(&a[1]) + 2;
b += strlen(&b[1]) + 2;
}
if( dir=='-' || dir=='D' ) res = -res;
return res;
}
| util.c | 672 |
VOID | sqliteRealToSortable(double r, char *z)
void sqliteRealToSortable(double r, char *z){
int neg;
int exp;
int cnt = 0;
/* This array maps integers between 0 and 63 into base-64 digits.
** The digits must be chosen such at their ASCII codes are increasing.
** This means we can not use the traditional base-64 digit set. */
static const char zDigit[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"|~";
if( r<0.0 ){
neg = 1;
r = -r;
*z++ = '-';
} else {
neg = 0;
*z++ = '0';
}
exp = 0;
if( r==0.0 ){
exp = -1024;
}else if( r<(0.5/64.0) ){
while( r < 0.5/_64e64 && exp > -961 ){ r *= _64e64; exp -= 64; }
while( r < 0.5/_64e16 && exp > -1009 ){ r *= _64e16; exp -= 16; }
while( r < 0.5/_64e4 && exp > -1021 ){ r *= _64e4; exp -= 4; }
while( r < 0.5/64.0 && exp > -1024 ){ r *= 64.0; exp -= 1; }
}else if( r>=0.5 ){
while( r >= 0.5*_64e63 && exp < 960 ){ r *= 1.0/_64e64; exp += 64; }
while( r >= 0.5*_64e15 && exp < 1008 ){ r *= 1.0/_64e16; exp += 16; }
while( r >= 0.5*_64e3 && exp < 1020 ){ r *= 1.0/_64e4; exp += 4; }
while( r >= 0.5 && exp < 1023 ){ r *= 1.0/64.0; exp += 1; }
}
if( neg ){
exp = -exp;
r = -r;
}
exp += 1024;
r += 0.5;
if( exp<0 ) return;
if( exp>=2048 || r>=1.0 ){
strcpy(z, "~~~~~~~~~~~~");
return;
}
*z++ = zDigit[(exp>>6)&0x3f];
*z++ = zDigit[exp & 0x3f];
while( r>0.0 && cnt<10 ){
int digit;
r *= 64.0;
digit = (int)r;
assert( digit>=0 && digit<64 );
*z++ = zDigit[digit & 0x3f];
r -= digit;
cnt++;
}
*z = 0;
}
#ifdef SQLITE_UTF8
/*
** X is a pointer to the first byte of a UTF-8 character. Increment
** X so that it points to the next character. This only works right
** if X points to a well-formed UTF-8 string.
*/
#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
#define sqliteCharVal(X) sqlite_utf8_to_int(X)
#else /* !defined(SQLITE_UTF8) */
| util.c | 783 |
STATIC INT | sqlite_utf8_to_int(const unsigned char *z)
static int sqlite_utf8_to_int(const unsigned char *z){
int c;
static const int initVal[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254,
255,
};
c = initVal[*(z++)];
while( (0xc0&*z)==0x80 ){
c = (c<<6) | (0x3f&*(z++));
}
return c;
}
| util.c | 879 |
INT | sqliteGlobCompare(const unsigned char *zPattern, const unsigned char *zString)
int
sqliteGlobCompare(const unsigned char *zPattern, const unsigned char *zString){
register int c;
int invert;
int seen;
int c2;
while( (c = *zPattern)!=0 ){
switch( c ){
case '*':
while( (c=zPattern[1]) == '*' || c == '?' ){
if( c=='?' ){
if( *zString==0 ) return 0;
sqliteNextChar(zString);
}
zPattern++;
}
if( c==0 ) return 1;
if( c=='[' ){
while( *zString && sqliteGlobCompare(&zPattern[1],zString)==0 ){
sqliteNextChar(zString);
}
return *zString!=0;
}else{
while( (c2 = *zString)!=0 ){
while( c2 != 0 && c2 != c ){ c2 = *++zString; }
if( c2==0 ) return 0;
if( sqliteGlobCompare(&zPattern[1],zString) ) return 1;
sqliteNextChar(zString);
}
return 0;
}
case '?': {
if( *zString==0 ) return 0;
sqliteNextChar(zString);
zPattern++;
break;
}
case '[': {
int prior_c = 0;
seen = 0;
invert = 0;
c = sqliteCharVal(zString);
if( c==0 ) return 0;
c2 = *++zPattern;
if( c2=='^' ){ invert = 1; c2 = *++zPattern; }
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = *++zPattern;
}
while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){
if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){
zPattern++;
c2 = sqliteCharVal(zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else if( c==c2 ){
seen = 1;
prior_c = c2;
}else{
prior_c = c2;
}
sqliteNextChar(zPattern);
}
if( c2==0 || (seen ^ invert)==0 ) return 0;
sqliteNextChar(zString);
zPattern++;
break;
}
default: {
if( c != *zString ) return 0;
zPattern++;
zString++;
break;
}
}
}
return *zString==0;
}
| util.c | 914 |
INT | sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString)
int
sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){
register int c;
int c2;
while( (c = UpperToLower[*zPattern])!=0 ){
switch( c ){
case '%': {
while( (c=zPattern[1]) == '%' || c == '_' ){
if( c=='_' ){
if( *zString==0 ) return 0;
sqliteNextChar(zString);
}
zPattern++;
}
if( c==0 ) return 1;
c = UpperToLower[c];
while( (c2=UpperToLower[*zString])!=0 ){
while( c2 != 0 && c2 != c ){ c2 = UpperToLower[*++zString]; }
if( c2==0 ) return 0;
if( sqliteLikeCompare(&zPattern[1],zString) ) return 1;
sqliteNextChar(zString);
}
return 0;
}
case '_': {
if( *zString==0 ) return 0;
sqliteNextChar(zString);
zPattern++;
break;
}
default: {
if( c != UpperToLower[*zString] ) return 0;
zPattern++;
zString++;
break;
}
}
}
return *zString==0;
}
| util.c | 1022 |
INT | sqliteSafetyOn(sqlite *db)
int sqliteSafetyOn(sqlite *db){
if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_BUSY;
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR
|| db->want_to_close ){
db->magic = SQLITE_MAGIC_ERROR;
db->flags |= SQLITE_Interrupt;
}
return 1;
}
| util.c | 1073 |
INT | sqliteSafetyOff(sqlite *db)
int sqliteSafetyOff(sqlite *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
return 0;
}else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR
|| db->want_to_close ){
db->magic = SQLITE_MAGIC_ERROR;
db->flags |= SQLITE_Interrupt;
}
return 1;
}
| util.c | 1103 |
INT | sqliteSafetyCheck(sqlite *db)
int sqliteSafetyCheck(sqlite *db){
if( db->pVdbe!=0 ){
db->magic = SQLITE_MAGIC_ERROR;
return 1;
}
return 0;
}
| util.c | 1120 |
vacuum.c |
Type | Function | Source | Line |
STATIC VOID | appendText(dynStr *p, const char *zText, int nText)
static void appendText(dynStr *p, const char *zText, int nText){
if( nText<0 ) nText = strlen(zText);
if( p->z==0 || p->nUsed + nText + 1 >= p->nAlloc ){
char *zNew;
p->nAlloc = p->nUsed + nText + 1000;
zNew = sqliteRealloc(p->z, p->nAlloc);
if( zNew==0 ){
sqliteFree(p->z);
memset(p, 0, sizeof(*p));
return;
}
p->z = zNew;
}
memcpy(&p->z[p->nUsed], zText, nText+1);
p->nUsed += nText;
}
| vacuum.c | 48 |
STATIC VOID | appendQuoted(dynStr *p, const char *zText)
static void appendQuoted(dynStr *p, const char *zText){
int i, j;
appendText(p, "'", 1);
for(i=j=0; zText[i]; i++){
if( zText[i]=='\'' ){
appendText(p, &zText[j], i-j+1);
j = i + 1;
appendText(p, "'", 1);
}
}
| vacuum.c | 68 |
IF( | j
if( j | vacuum.c | 81 |
} STATIC INT | execsql(char **pzErrMsg, sqlite *db, const char *zSql)
static int execsql(char **pzErrMsg, sqlite *db, const char *zSql){
char *zErrMsg = 0;
int rc;
/* printf("***** executing *****\n%s\n", zSql); */
rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
sqliteSetString(pzErrMsg, zErrMsg, (char*)0);
sqlite_freemem(zErrMsg);
}
return rc;
}
| vacuum.c | 87 |
STATIC INT | vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed)
static int vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed){
vacuumStruct *p = (vacuumStruct*)pArg;
const char *zSep = "(";
int i;
if( argv==0 ) return 0;
p->s2.nUsed = 0;
appendText(&p->s2, "INSERT INTO ", -1);
appendQuoted(&p->s2, p->zTable);
appendText(&p->s2, " VALUES", -1);
for(i=0; is2, zSep, 1);
zSep = ",";
if( argv[i]==0 ){
appendText(&p->s2, "NULL", 4);
}else{
appendQuoted(&p->s2, argv[i]);
}
}
appendText(&p->s2,")", 1);
p->rc = execsql(p->pzErrMsg, p->dbNew, p->s2.z);
return p->rc;
}
| vacuum.c | 104 |
STATIC INT | vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed)
static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){
vacuumStruct *p = (vacuumStruct*)pArg;
int rc = 0;
assert( argc==3 );
if( argv==0 ) return 0;
assert( argv[0]!=0 );
assert( argv[1]!=0 );
assert( argv[2]!=0 );
rc = execsql(p->pzErrMsg, p->dbNew, argv[2]);
if( rc==SQLITE_OK && strcmp(argv[0],"table")==0 ){
char *zErrMsg = 0;
p->s1.nUsed = 0;
appendText(&p->s1, "SELECT * FROM ", -1);
appendQuoted(&p->s1, argv[1]);
p->zTable = argv[1];
rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg);
if( zErrMsg ){
sqliteSetString(p->pzErrMsg, zErrMsg, (char*)0);
sqlite_freemem(zErrMsg);
}
}
if( rc!=SQLITE_ABORT ) p->rc = rc;
return rc;
}
| vacuum.c | 133 |
STATIC VOID | randomName(unsigned char *zBuf)
static void randomName(unsigned char *zBuf){
static const unsigned char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"0123456789";
int i;
sqliteRandomness(20, zBuf);
for(i=0; i<20; i++){
zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
}
}
| vacuum.c | 166 |
VOID | sqliteVacuum(Parse *pParse, Token *pTableName)
void sqliteVacuum(Parse *pParse, Token *pTableName){
Vdbe *v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Vacuum, 0, 0);
return;
}
| vacuum.c | 181 |
INT | sqliteRunVacuum(char **pzErrMsg, sqlite *db)
int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
const char *zFilename; /* full pathname of the database file */
int nFilename; /* number of characters in zFilename[] */
char *zTemp = 0; /* a temporary file in same directory as zFilename */
sqlite *dbNew = 0; /* The new vacuumed database */
int rc = SQLITE_OK; /* Return code from service routines */
int i; /* Loop counter */
char *zErrMsg; /* Error message */
vacuumStruct sVac; /* Information passed to callbacks */
if( db->flags & SQLITE_InTrans ){
sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
return SQLITE_ERROR;
}
if( db->flags & SQLITE_Interrupt ){
return SQLITE_INTERRUPT;
}
memset(&sVac, 0, sizeof(sVac));
/* Get the full pathname of the database file and create two
** temporary filenames in the same directory as the original file.
*/
zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);
if( zFilename==0 ){
/* This only happens with the in-memory database. VACUUM is a no-op
** there, so just return */
return SQLITE_OK;
}
nFilename = strlen(zFilename);
zTemp = sqliteMalloc( nFilename+100 );
if( zTemp==0 ) return SQLITE_NOMEM;
strcpy(zTemp, zFilename);
for(i=0; i<10; i++){
zTemp[nFilename] = '-';
randomName((unsigned char*)&zTemp[nFilename+1]);
if( !sqliteOsFileExists(zTemp) ) break;
}
if( i>=10 ){
sqliteSetString(pzErrMsg, "unable to create a temporary database file "
"in the same directory as the original database", (char*)0);
goto end_of_vacuum;
}
dbNew = sqlite_open(zTemp, 0, &zErrMsg);
if( dbNew==0 ){
sqliteSetString(pzErrMsg, "unable to open a temporary database at ",
zTemp, " - ", zErrMsg, (char*)0);
goto end_of_vacuum;
}
if( (rc = execsql(pzErrMsg, db, "BEGIN"))!=0 ) goto end_of_vacuum;
if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
goto end_of_vacuum;
}
sVac.dbOld = db;
sVac.dbNew = dbNew;
sVac.pzErrMsg = pzErrMsg;
if( rc==SQLITE_OK ){
rc = sqlite_exec(db,
"SELECT type, name, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type!='view' "
"UNION ALL "
"SELECT type, name, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='view'",
vacuumCallback1, &sVac, &zErrMsg);
}
if( rc==SQLITE_OK ){
int meta1[SQLITE_N_BTREE_META];
int meta2[SQLITE_N_BTREE_META];
sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
meta2[1] = meta1[1]+1;
meta2[3] = meta1[3];
meta2[4] = meta1[4];
meta2[6] = meta1[6];
rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
}
if( rc==SQLITE_OK ){
rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
sqlite_exec(db, "COMMIT", 0, 0, 0);
sqliteResetInternalSchema(db, 0);
}
end_of_vacuum:
if( rc && zErrMsg!=0 ){
sqliteSetString(pzErrMsg, "unable to vacuum database - ",
zErrMsg, (char*)0);
}
sqlite_exec(db, "ROLLBACK", 0, 0, 0);
if( (dbNew && (dbNew->flags & SQLITE_Interrupt))
|| (db->flags & SQLITE_Interrupt) ){
rc = SQLITE_INTERRUPT;
}
if( dbNew ) sqlite_close(dbNew);
sqliteOsDelete(zTemp);
sqliteFree(zTemp);
sqliteFree(sVac.s1.z);
sqliteFree(sVac.s2.z);
if( zErrMsg ) sqlite_freemem(zErrMsg);
if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
return sVac.rc;
#endif
}
| vacuum.c | 197 |
vdbe.c |
Type | Function | Source | Line |
INT | sqlite_step( sqlite_vm *pVm, int *pN, const char ***pazValue, const char ***pazColName )
int sqlite_step(
sqlite_vm *pVm, /* The virtual machine to execute */
int *pN, /* OUT: Number of columns in result */
const char ***pazValue, /* OUT: Column data */
const char ***pazColName /* OUT: Column names and datatypes */
){
Vdbe *p = (Vdbe*)pVm;
sqlite *db;
int rc;
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
}
db = p->db;
if( sqliteSafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
if( p->explain ){
rc = sqliteVdbeList(p);
}else{
rc = sqliteVdbeExec(p);
}
if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
if( pazColName ) *pazColName = (const char**)p->azColName;
if( pN ) *pN = p->nResColumn;
}else{
if( pazColName) *pazColName = 0;
if( pN ) *pN = 0;
}
if( pazValue ){
if( rc==SQLITE_ROW ){
*pazValue = (const char**)p->azResColumn;
}else{
*pazValue = 0;
}
}
if( sqliteSafetyOff(db) ){
return SQLITE_MISUSE;
}
return rc;
}
| vdbe.c | 72 |
STATIC INT | AggInsert(Agg *p, char *zKey, int nKey)
static int AggInsert(Agg *p, char *zKey, int nKey){
AggElem *pElem, *pOld;
int i;
Mem *pMem;
pElem = sqliteMalloc( sizeof(AggElem) + nKey +
(p->nMem-1)*sizeof(pElem->aMem[0]) );
if( pElem==0 ) return 1;
pElem->zKey = (char*)&pElem->aMem[p->nMem];
memcpy(pElem->zKey, zKey, nKey);
pElem->nKey = nKey;
pOld = sqliteHashInsert(&p->hash, pElem->zKey, pElem->nKey, pElem);
if( pOld!=0 ){
assert( pOld==pElem ); /* Malloc failed on insert */
sqliteFree(pOld);
return 0;
}
for(i=0, pMem=pElem->aMem; inMem; i++, pMem++){
pMem->flags = MEM_Null;
}
p->pCurrent = pElem;
return 0;
}
| vdbe.c | 150 |
STATIC AGGELEM | _AggInFocus(Agg *p)
static AggElem *_AggInFocus(Agg *p){
HashElem *pElem = sqliteHashFirst(&p->hash);
if( pElem==0 ){
AggInsert(p,"",1);
pElem = sqliteHashFirst(&p->hash);
}
return pElem ? sqliteHashData(pElem) : 0;
}
| vdbe.c | 183 |
STATIC INT | hardStringify(Mem *pStack)
static int hardStringify(Mem *pStack){
int fg = pStack->flags;
if( fg & MEM_Real ){
sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%.15g",pStack->r);
}else if( fg & MEM_Int ){
sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%d",pStack->i);
}else{
pStack->zShort[0] = 0;
}
pStack->z = pStack->zShort;
pStack->n = strlen(pStack->zShort)+1;
pStack->flags = MEM_Str | MEM_Short;
return 0;
}
| vdbe.c | 197 |
STATIC INT | hardDynamicify(Mem *pStack)
static int hardDynamicify(Mem *pStack){
int fg = pStack->flags;
char *z;
if( (fg & MEM_Str)==0 ){
hardStringify(pStack);
}
assert( (fg & MEM_Dyn)==0 );
z = sqliteMallocRaw( pStack->n );
if( z==0 ) return 1;
memcpy(z, pStack->z, pStack->n);
pStack->z = z;
pStack->flags |= MEM_Dyn;
return 0;
}
/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string. Because the stack entry
** does not control the string, it might be deleted without the stack
** entry knowing it.
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the stack entry itself controls. In other words, it
** converts an MEM_Ephem string into an MEM_Dyn string.
*/
#define Deephemeralize(P) \
if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
| vdbe.c | 220 |
} STATIC INT | hardDeephem(Mem *pStack)
static int hardDeephem(Mem *pStack){
char *z;
assert( (pStack->flags & MEM_Ephem)!=0 );
z = sqliteMallocRaw( pStack->n );
if( z==0 ) return 1;
memcpy(z, pStack->z, pStack->n);
pStack->z = z;
pStack->flags &= ~MEM_Ephem;
pStack->flags |= MEM_Dyn;
return 0;
}
| vdbe.c | 248 |
STATIC VOID | popStack(Mem **ppTos, int N)
static void popStack(Mem **ppTos, int N){
Mem *pTos = *ppTos;
while( N>0 ){
N--;
Release(pTos);
pTos--;
}
*ppTos = pTos;
}
| vdbe.c | 266 |
STATIC INT | toInt(const char *zNum, int *pNum)
static int toInt(const char *zNum, int *pNum){
int v = 0;
int neg;
int i, c;
if( *zNum=='-' ){
neg = 1;
zNum++;
}else if( *zNum=='+' ){
neg = 0;
zNum++;
}else{
neg = 0;
}
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
v = v*10 + c - '0';
}
*pNum = neg ? -v : v;
return c==0 && i>0 && (i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0));
}
| vdbe.c | 279 |
STATIC VOID | hardIntegerify(Mem *pStack)
static void hardIntegerify(Mem *pStack){
if( pStack->flags & MEM_Real ){
pStack->i = (int)pStack->r;
Release(pStack);
}else if( pStack->flags & MEM_Str ){
toInt(pStack->z, &pStack->i);
Release(pStack);
}else{
pStack->i = 0;
}
pStack->flags = MEM_Int;
}
| vdbe.c | 316 |
STATIC VOID | hardRealify(Mem *pStack)
static void hardRealify(Mem *pStack){
if( pStack->flags & MEM_Str ){
pStack->r = sqliteAtoF(pStack->z, 0);
}else if( pStack->flags & MEM_Int ){
pStack->r = pStack->i;
}else{
pStack->r = 0.0;
}
pStack->flags |= MEM_Real;
}
| vdbe.c | 336 |
STATIC SORTER | Merge(Sorter *pLeft, Sorter *pRight)
static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
Sorter sHead;
Sorter *pTail;
pTail = &sHead;
pTail->pNext = 0;
while( pLeft && pRight ){
int c = sqliteSortCompare(pLeft->zKey, pRight->zKey);
if( c<=0 ){
pTail->pNext = pLeft;
pLeft = pLeft->pNext;
}else{
pTail->pNext = pRight;
pRight = pRight->pNext;
}
pTail = pTail->pNext;
}
if( pLeft ){
pTail->pNext = pLeft;
}else if( pRight ){
pTail->pNext = pRight;
}
return sHead.pNext;
}
| vdbe.c | 347 |
STATIC CHAR | vdbe_fgets(char *zBuf, int nBuf, FILE *in)
static char *vdbe_fgets(char *zBuf, int nBuf, FILE *in){
int i, c;
for(i=0; i0 ? zBuf : 0;
}
| vdbe.c | 379 |
STATIC INT | expandCursorArraySize(Vdbe *p, int mxCursor)
static int expandCursorArraySize(Vdbe *p, int mxCursor){
if( mxCursor>=p->nCursor ){
Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) );
if( aCsr==0 ) return 1;
p->aCsr = aCsr;
memset(&p->aCsr[p->nCursor], 0, sizeof(Cursor)*(mxCursor+1-p->nCursor));
p->nCursor = mxCursor+1;
}
return 0;
}
| vdbe.c | 405 |
__INLINE__ UNSIGNED LONG LONG INT | hwtime(void)
__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;
}
#endif
/*
** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
** sqlite_interrupt() routine has been called. If it has been, then
** processing of the VDBE program is interrupted.
**
** This macro added to every instruction that does a jump in order to
** implement a loop. This test used to be on every single instruction,
** but that meant we more testing that we needed. By only testing the
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
| vdbe.c | 425 |
INT | sqliteVdbeExec( Vdbe *p )
int sqliteVdbeExec(
Vdbe *p /* The VDBE */
){
int pc; /* The program counter */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite *db = p->db; /* The database */
Mem *pTos; /* Top entry in the operand stack */
char zBuf[100]; /* Space to sprintf() an integer */
#ifdef VDBE_PROFILE
unsigned long long start; /* CPU clock count at start of opcode */
int origPc; /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
assert( db->magic==SQLITE_MAGIC_BUSY );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
p->rc = SQLITE_OK;
assert( p->explain==0 );
if( sqlite_malloc_failed ) goto no_mem;
pTos = p->pTos;
if( p->popStack ){
popStack(&pTos, p->popStack);
p->popStack = 0;
}
CHECK_FOR_INTERRUPT;
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pcnOp );
assert( pTos<=&p->aStack[pc] );
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
#endif
pOp = &p->aOp[pc];
/* Only allow tracing if NDEBUG is not defined.
*/
#ifndef NDEBUG
if( p->trace ){
sqliteVdbePrintOp(p->trace, pc, pOp);
}
#endif
/* Check to see if we need to simulate an interrupt. This only happens
** if we have a special test build.
*/
#ifdef SQLITE_TEST
if( sqlite_interrupt_count>0 ){
sqlite_interrupt_count--;
if( sqlite_interrupt_count==0 ){
sqlite_interrupt(db);
}
}
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqliteVdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress ){
if( db->nProgressOps==nProgressOps ){
if( db->xProgress(db->pProgressArg)!=0 ){
rc = SQLITE_ABORT;
continue; /* skip to the next iteration of the for loop */
}
nProgressOps = 0;
}
nProgressOps++;
}
#endif
switch( pOp->opcode ){
/*****************************************************************************
** What follows is a massive switch statement where each case implements a
** separate instruction in the virtual machine. If we follow the usual
** indentation conventions, each case should be indented by 6 spaces. But
** that is a lot of wasted space on the left margin. So the code within
** the switch statement will break with convention and be flush-left. Another
** big comment (similar to this one) will mark the point in the code where
** we transition back to normal indentation.
**
** The formatting of each case is important. The makefile for SQLite
** generates two C files "opcodes.h" and "opcodes.c" by scanning this
** file looking for lines that begin with "case OP_". The opcodes.h files
** will be filled with #defines that give unique integer values to each
** opcode and the opcodes.c file is filled with an array of strings where
** each string is the symbolic name for the corresponding opcode.
**
** Documentation about VDBE opcodes is generated by scanning this file
** for lines of that contain "Opcode:". That line and all subsequent
** comment lines are used in the generation of the opcode.html documentation
** file.
**
** SUMMARY:
**
** Formatting is important to scripts that scan this file.
** Do not deviate from the formatting style currently in use.
**
*****************************************************************************/
/* Opcode: Goto * P2 *
**
** An unconditional jump to address P2.
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
case OP_Goto: {
CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1;
break;
}
/* Opcode: Gosub * P2 *
**
** Push the current address plus 1 onto the return address stack
** and then jump to address P2.
**
** The return address stack is of limited depth. If too many
** OP_Gosub operations occur without intervening OP_Returns, then
** the return address stack will fill up and processing will abort
** with a fatal error.
*/
case OP_Gosub: {
if( p->returnDepth>=sizeof(p->returnStack)/sizeof(p->returnStack[0]) ){
sqliteSetString(&p->zErrMsg, "return address stack overflow", (char*)0);
p->rc = SQLITE_INTERNAL;
return SQLITE_ERROR;
}
p->returnStack[p->returnDepth++] = pc+1;
pc = pOp->p2 - 1;
break;
}
/* Opcode: Return * * *
**
** Jump immediately to the next instruction after the last unreturned
** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then
** processing aborts with a fatal error.
*/
case OP_Return: {
if( p->returnDepth<=0 ){
sqliteSetString(&p->zErrMsg, "return address stack underflow", (char*)0);
p->rc = SQLITE_INTERNAL;
return SQLITE_ERROR;
}
p->returnDepth--;
pc = p->returnStack[p->returnDepth] - 1;
break;
}
/* Opcode: Halt P1 P2 *
**
** Exit immediately. All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite_exec(). For a normal
** halt, this should be SQLITE_OK (0). For errors, it can be some
** other value. If P1!=0 then P2 will determine whether or not to
** rollback the current transaction. Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
p->magic = VDBE_MAGIC_HALT;
p->pTos = pTos;
if( pOp->p1!=SQLITE_OK ){
p->rc = pOp->p1;
p->errorAction = pOp->p2;
if( pOp->p3 ){
sqliteSetString(&p->zErrMsg, pOp->p3, (char*)0);
}
return SQLITE_ERROR;
}else{
p->rc = SQLITE_OK;
return SQLITE_DONE;
}
}
/* Opcode: Integer P1 * P3
**
** The integer value P1 is pushed onto the stack. If P3 is not zero
** then it is assumed to be a string representation of the same integer.
*/
case OP_Integer: {
pTos++;
pTos->i = pOp->p1;
pTos->flags = MEM_Int;
if( pOp->p3 ){
pTos->z = pOp->p3;
pTos->flags |= MEM_Str | MEM_Static;
pTos->n = strlen(pOp->p3)+1;
}
break;
}
/* Opcode: String * * P3
**
** The string value P3 is pushed onto the stack. If P3==0 then a
** NULL is pushed onto the stack.
*/
case OP_String: {
char *z = pOp->p3;
pTos++;
if( z==0 ){
pTos->flags = MEM_Null;
}else{
pTos->z = z;
pTos->n = strlen(z) + 1;
pTos->flags = MEM_Str | MEM_Static;
}
break;
}
/* Opcode: Variable P1 * *
**
** Push the value of variable P1 onto the stack. A variable is
** an unknown in the original SQL string as handed to sqlite_compile().
** Any occurance of the '?' character in the original SQL is considered
** a variable. Variables in the SQL string are number from left to
** right beginning with 1. The values of variables are set using the
** sqlite_bind() API.
*/
case OP_Variable: {
int j = pOp->p1 - 1;
pTos++;
if( j>=0 && jnVar && p->azVar[j]!=0 ){
pTos->z = p->azVar[j];
pTos->n = p->anVar[j];
pTos->flags = MEM_Str | MEM_Static;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: Pop P1 * *
**
** P1 elements are popped off of the top of stack and discarded.
*/
case OP_Pop: {
assert( pOp->p1>=0 );
popStack(&pTos, pOp->p1);
assert( pTos>=&p->aStack[-1] );
break;
}
/* Opcode: Dup P1 P2 *
**
** A copy of the P1-th element of the stack
** is made and pushed onto the top of the stack.
** The top of the stack is element 0. So the
** instruction "Dup 0 0 0" will make a copy of the
** top of the stack.
**
** If the content of the P1-th element is a dynamically
** allocated string, then a new copy of that string
** is made if P2==0. If P2!=0, then just a pointer
** to the string is copied.
**
** Also see the Pull instruction.
*/
case OP_Dup: {
Mem *pFrom = &pTos[-pOp->p1];
assert( pFrom<=pTos && pFrom>=p->aStack );
pTos++;
memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
if( pTos->flags & MEM_Str ){
if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
pTos->flags &= ~MEM_Dyn;
pTos->flags |= MEM_Ephem;
}else if( pTos->flags & MEM_Short ){
memcpy(pTos->zShort, pFrom->zShort, pTos->n);
pTos->z = pTos->zShort;
}else if( (pTos->flags & MEM_Static)==0 ){
pTos->z = sqliteMallocRaw(pFrom->n);
if( sqlite_malloc_failed ) goto no_mem;
memcpy(pTos->z, pFrom->z, pFrom->n);
pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
pTos->flags |= MEM_Dyn;
}
}
break;
}
/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on
** the stack and pushed back on top of the stack. The
** top of the stack is element 0, so "Pull 0 0 0" is
** a no-op. "Pull 1 0 0" swaps the top two elements of
** the stack.
**
** See also the Dup instruction.
*/
case OP_Pull: {
Mem *pFrom = &pTos[-pOp->p1];
int i;
Mem ts;
ts = *pFrom;
Deephemeralize(pTos);
for(i=0; ip1; i++, pFrom++){
Deephemeralize(&pFrom[1]);
*pFrom = pFrom[1];
assert( (pFrom->flags & MEM_Ephem)==0 );
if( pFrom->flags & MEM_Short ){
assert( pFrom->flags & MEM_Str );
assert( pFrom->z==pFrom[1].zShort );
pFrom->z = pFrom->zShort;
}
}
*pTos = ts;
if( pTos->flags & MEM_Short ){
assert( pTos->flags & MEM_Str );
assert( pTos->z==pTos[-pOp->p1].zShort );
pTos->z = pTos->zShort;
}
break;
}
/* Opcode: Push P1 * *
**
** Overwrite the value of the P1-th element down on the
** stack (P1==0 is the top of the stack) with the value
** of the top of the stack. Then pop the top of the stack.
*/
case OP_Push: {
Mem *pTo = &pTos[-pOp->p1];
assert( pTo>=p->aStack );
Deephemeralize(pTos);
Release(pTo);
*pTo = *pTos;
if( pTo->flags & MEM_Short ){
assert( pTo->z==pTos->zShort );
pTo->z = pTo->zShort;
}
pTos--;
break;
}
/* Opcode: ColumnName P1 P2 P3
**
** P3 becomes the P1-th column name (first is 0). An array of pointers
** to all column names is passed as the 4th parameter to the callback.
** If P2==1 then this is the last column in the result set and thus the
** number of columns in the result set will be P1. There must be at least
** one OP_ColumnName with a P2==1 before invoking OP_Callback and the
** number of columns specified in OP_Callback must one more than the P1
** value of the OP_ColumnName that has P2==1.
*/
case OP_ColumnName: {
assert( pOp->p1>=0 && pOp->p1nOp );
p->azColName[pOp->p1] = pOp->p3;
p->nCallback = 0;
if( pOp->p2 ) p->nResColumn = pOp->p1+1;
break;
}
/* Opcode: Callback P1 * *
**
** Pop P1 values off the stack and form them into an array. Then
** invoke the callback function using the newly formed array as the
** 3rd parameter.
*/
case OP_Callback: {
int i;
char **azArgv = p->zArgv;
Mem *pCol;
pCol = &pTos[1-pOp->p1];
assert( pCol>=p->aStack );
for(i=0; ip1; i++, pCol++){
if( pCol->flags & MEM_Null ){
azArgv[i] = 0;
}else{
Stringify(pCol);
azArgv[i] = pCol->z;
}
}
azArgv[i] = 0;
p->nCallback++;
p->azResColumn = azArgv;
assert( p->nResColumn==pOp->p1 );
p->popStack = pOp->p1;
p->pc = pc + 1;
p->pTos = pTos;
return SQLITE_ROW;
}
/* Opcode: Concat P1 P2 P3
**
** Look at the first P1 elements of the stack. Append them all
** together with the lowest element first. Use P3 as a separator.
** Put the result on the top of the stack. The original P1 elements
** are popped from the stack if P2==0 and retained if P2==1. If
** any element of the stack is NULL, then the result is NULL.
**
** If P3 is NULL, then use no separator. When P1==1, this routine
** makes a copy of the top stack element into memory obtained
** from sqliteMalloc().
*/
case OP_Concat: {
char *zNew;
int nByte;
int nField;
int i, j;
char *zSep;
int nSep;
Mem *pTerm;
nField = pOp->p1;
zSep = pOp->p3;
if( zSep==0 ) zSep = "";
nSep = strlen(zSep);
assert( &pTos[1-nField] >= p->aStack );
nByte = 1 - nSep;
pTerm = &pTos[1-nField];
for(i=0; iflags & MEM_Null ){
nByte = -1;
break;
}else{
Stringify(pTerm);
nByte += pTerm->n - 1 + nSep;
}
}
if( nByte<0 ){
if( pOp->p2==0 ){
popStack(&pTos, nField);
}
pTos++;
pTos->flags = MEM_Null;
break;
}
zNew = sqliteMallocRaw( nByte );
if( zNew==0 ) goto no_mem;
j = 0;
pTerm = &pTos[1-nField];
for(i=j=0; iflags & MEM_Str );
memcpy(&zNew[j], pTerm->z, pTerm->n-1);
j += pTerm->n-1;
if( nSep>0 && ip2==0 ){
popStack(&pTos, nField);
}
pTos++;
pTos->n = nByte;
pTos->flags = MEM_Str|MEM_Dyn;
pTos->z = zNew;
break;
}
/* Opcode: Add * * *
**
** Pop the top two elements from the stack, add them together,
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the addition.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: Multiply * * *
**
** Pop the top two elements from the stack, multiply them together,
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the multiplication.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: Subtract * * *
**
** Pop the top two elements from the stack, subtract the
** first (what was on top of the stack) from the second (the
** next on stack)
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the subtraction.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: Divide * * *
**
** Pop the top two elements from the stack, divide the
** first (what was on top of the stack) from the second (the
** next on stack)
** and push the result back onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: Remainder * * *
**
** Pop the top two elements from the stack, divide the
** first (what was on top of the stack) from the second (the
** next on stack)
** and push the remainder after division onto the stack. If either element
** is a string then it is converted to a double using the atof()
** function before the division. Division by zero returns NULL.
** If either operand is NULL, the result is NULL.
*/
case OP_Add:
case OP_Subtract:
case OP_Multiply:
case OP_Divide:
case OP_Remainder: {
Mem *pNos = &pTos[-1];
assert( pNos>=p->aStack );
if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
Release(pTos);
pTos--;
Release(pTos);
pTos->flags = MEM_Null;
}else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){
int a, b;
a = pTos->i;
b = pNos->i;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
case OP_Multiply: b *= a; break;
case OP_Divide: {
if( a==0 ) goto divide_by_zero;
b /= a;
break;
}
default: {
if( a==0 ) goto divide_by_zero;
b %= a;
break;
}
}
Release(pTos);
pTos--;
Release(pTos);
pTos->i = b;
pTos->flags = MEM_Int;
}else{
double a, b;
Realify(pTos);
Realify(pNos);
a = pTos->r;
b = pNos->r;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
case OP_Multiply: b *= a; break;
case OP_Divide: {
if( a==0.0 ) goto divide_by_zero;
b /= a;
break;
}
default: {
int ia = (int)a;
int ib = (int)b;
if( ia==0.0 ) goto divide_by_zero;
b = ib % ia;
break;
}
}
Release(pTos);
pTos--;
Release(pTos);
pTos->r = b;
pTos->flags = MEM_Real;
}
break;
divide_by_zero:
Release(pTos);
pTos--;
Release(pTos);
pTos->flags = MEM_Null;
break;
}
/* Opcode: Function P1 * P3
**
** Invoke a user function (P3 is a pointer to a Function structure that
** defines the function) with P1 string arguments taken from the stack.
** Pop all arguments from the stack and push back the result.
**
** See also: AggFunc
*/
case OP_Function: {
int n, i;
Mem *pArg;
char **azArgv;
sqlite_func ctx;
n = pOp->p1;
pArg = &pTos[1-n];
azArgv = p->zArgv;
for(i=0; iflags & MEM_Null ){
azArgv[i] = 0;
}else{
Stringify(pArg);
azArgv[i] = pArg->z;
}
}
ctx.pFunc = (FuncDef*)pOp->p3;
ctx.s.flags = MEM_Null;
ctx.s.z = 0;
ctx.isError = 0;
ctx.isStep = 0;
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv);
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
popStack(&pTos, n);
pTos++;
*pTos = ctx.s;
if( pTos->flags & MEM_Short ){
pTos->z = pTos->zShort;
}
if( ctx.isError ){
sqliteSetString(&p->zErrMsg,
(pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0);
rc = SQLITE_ERROR;
}
break;
}
/* Opcode: BitAnd * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise AND of the
** two elements.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: BitOr * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the bit-wise OR of the
** two elements.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: ShiftLeft * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the top element shifted
** left by N bits where N is the second element on the stack.
** If either operand is NULL, the result is NULL.
*/
/* Opcode: ShiftRight * * *
**
** Pop the top two elements from the stack. Convert both elements
** to integers. Push back onto the stack the top element shifted
** right by N bits where N is the second element on the stack.
** If either operand is NULL, the result is NULL.
*/
case OP_BitAnd:
case OP_BitOr:
case OP_ShiftLeft:
case OP_ShiftRight: {
Mem *pNos = &pTos[-1];
int a, b;
assert( pNos>=p->aStack );
if( (pTos->flags | pNos->flags) & MEM_Null ){
popStack(&pTos, 2);
pTos++;
pTos->flags = MEM_Null;
break;
}
Integerify(pTos);
Integerify(pNos);
a = pTos->i;
b = pNos->i;
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
case OP_ShiftLeft: a <<= b; break;
case OP_ShiftRight: a >>= b; break;
default: /* CANT HAPPEN */ break;
}
assert( (pTos->flags & MEM_Dyn)==0 );
assert( (pNos->flags & MEM_Dyn)==0 );
pTos--;
Release(pTos);
pTos->i = a;
pTos->flags = MEM_Int;
break;
}
/* Opcode: AddImm P1 * *
**
** Add the value P1 to whatever is on top of the stack. The result
** is always an integer.
**
** To force the top of the stack to be an integer, just add 0.
*/
case OP_AddImm: {
assert( pTos>=p->aStack );
Integerify(pTos);
pTos->i += pOp->p1;
break;
}
/* Opcode: ForceInt P1 P2 *
**
** Convert the top of the stack into an integer. If the current top of
** the stack is not numeric (meaning that is is a NULL or a string that
** does not look like an integer or floating point number) then pop the
** stack and jump to P2. If the top of the stack is numeric then
** convert it into the least integer that is greater than or equal to its
** current value if P1==0, or to the least integer that is strictly
** greater than its current value if P1==1.
*/
case OP_ForceInt: {
int v;
assert( pTos>=p->aStack );
if( (pTos->flags & (MEM_Int|MEM_Real))==0
&& ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){
Release(pTos);
pTos--;
pc = pOp->p2 - 1;
break;
}
if( pTos->flags & MEM_Int ){
v = pTos->i + (pOp->p1!=0);
}else{
Realify(pTos);
v = (int)pTos->r;
if( pTos->r>(double)v ) v++;
if( pOp->p1 && pTos->r==(double)v ) v++;
}
Release(pTos);
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: MustBeInt P1 P2 *
**
** Force the top of the stack to be an integer. If the top of the
** stack is not an integer and cannot be converted into an integer
** with out data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE_MISMATCH exception.
**
** If the top of the stack is not an integer and P2 is not zero and
** P1 is 1, then the stack is popped. In all other cases, the depth
** of the stack is unchanged.
*/
case OP_MustBeInt: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Int ){
/* Do nothing */
}else if( pTos->flags & MEM_Real ){
int i = (int)pTos->r;
double r = (double)i;
if( r!=pTos->r ){
goto mismatch;
}
pTos->i = i;
}else if( pTos->flags & MEM_Str ){
int v;
if( !toInt(pTos->z, &v) ){
double r;
if( !sqliteIsNumber(pTos->z) ){
goto mismatch;
}
Realify(pTos);
v = (int)pTos->r;
r = (double)v;
if( r!=pTos->r ){
goto mismatch;
}
}
pTos->i = v;
}else{
goto mismatch;
}
Release(pTos);
pTos->flags = MEM_Int;
break;
mismatch:
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
if( pOp->p1 ) popStack(&pTos, 1);
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: Eq P1 P2 *
**
** Pop the top two elements from the stack. If they are equal, then
** jump to instruction P2. Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** If both values are numeric, they are converted to doubles using atof()
** and compared for equality that way. Otherwise the strcmp() library
** routine is used for the comparison. For a pure text comparison
** use OP_StrEq.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: Ne P1 P2 *
**
** Pop the top two elements from the stack. If they are not equal, then
** jump to instruction P2. Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** If both values are numeric, they are converted to doubles using atof()
** and compared in that format. Otherwise the strcmp() library
** routine is used for the comparison. For a pure text comparison
** use OP_StrNe.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: Lt P1 P2 *
**
** Pop the top two elements from the stack. If second element (the
** next on stack) is less than the first (the top of stack), then
** jump to instruction P2. Otherwise, continue to the next instruction.
** In other words, jump if NOSTOS.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** If both values are numeric, they are converted to doubles using atof()
** and compared in that format. Numeric values are always less than
** non-numeric values. If both operands are non-numeric, the strcmp() library
** routine is used for the comparison. For a pure text comparison
** use OP_StrGt.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: Ge P1 P2 *
**
** Pop the top two elements from the stack. If second element (the next
** on stack) is greater than or equal to the first (the top of stack),
** then jump to instruction P2. In other words, jump if NOS>=TOS.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** If both values are numeric, they are converted to doubles using atof()
** and compared in that format. Numeric values are always less than
** non-numeric values. If both operands are non-numeric, the strcmp() library
** routine is used for the comparison. For a pure text comparison
** use OP_StrGe.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
case OP_Eq:
case OP_Ne:
case OP_Lt:
case OP_Le:
case OP_Gt:
case OP_Ge: {
Mem *pNos = &pTos[-1];
int c, v;
int ft, fn;
assert( pNos>=p->aStack );
ft = pTos->flags;
fn = pNos->flags;
if( (ft | fn) & MEM_Null ){
popStack(&pTos, 2);
if( pOp->p2 ){
if( pOp->p1 ) pc = pOp->p2-1;
}else{
pTos++;
pTos->flags = MEM_Null;
}
break;
}else if( (ft & fn & MEM_Int)==MEM_Int ){
c = pNos->i - pTos->i;
}else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(pNos->z,&v) ){
c = v - pTos->i;
}else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(pTos->z,&v) ){
c = pNos->i - v;
}else{
Stringify(pTos);
Stringify(pNos);
c = sqliteCompare(pNos->z, pTos->z);
}
switch( pOp->opcode ){
case OP_Eq: c = c==0; break;
case OP_Ne: c = c!=0; break;
case OP_Lt: c = c<0; break;
case OP_Le: c = c<=0; break;
case OP_Gt: c = c>0; break;
default: c = c>=0; break;
}
popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
pTos++;
pTos->i = c;
pTos->flags = MEM_Int;
}
break;
}
/* INSERT NO CODE HERE!
**
** The opcode numbers are extracted from this source file by doing
**
** grep '^case OP_' vdbe.c | ... >opcodes.h
**
** The opcodes are numbered in the order that they appear in this file.
** But in order for the expression generating code to work right, the
** string comparison operators that follow must be numbered exactly 6
** greater than the numeric comparison opcodes above. So no other
** cases can appear between the two.
*/
/* Opcode: StrEq P1 P2 *
**
** Pop the top two elements from the stack. If they are equal, then
** jump to instruction P2. Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** The strcmp() library routine is used for the comparison. For a
** numeric comparison, use OP_Eq.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: StrNe P1 P2 *
**
** Pop the top two elements from the stack. If they are not equal, then
** jump to instruction P2. Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** The strcmp() library routine is used for the comparison. For a
** numeric comparison, use OP_Ne.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: StrLt P1 P2 *
**
** Pop the top two elements from the stack. If second element (the
** next on stack) is less than the first (the top of stack), then
** jump to instruction P2. Otherwise, continue to the next instruction.
** In other words, jump if NOSTOS.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** The strcmp() library routine is used for the comparison. For a
** numeric comparison, use OP_Gt.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
/* Opcode: StrGe P1 P2 *
**
** Pop the top two elements from the stack. If second element (the next
** on stack) is greater than or equal to the first (the top of stack),
** then jump to instruction P2. In other words, jump if NOS>=TOS.
**
** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**
** The strcmp() library routine is used for the comparison. For a
** numeric comparison, use OP_Ge.
**
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not. Push a
** NULL if either operand was NULL.
*/
case OP_StrEq:
case OP_StrNe:
case OP_StrLt:
case OP_StrLe:
case OP_StrGt:
case OP_StrGe: {
Mem *pNos = &pTos[-1];
int c;
assert( pNos>=p->aStack );
if( (pNos->flags | pTos->flags) & MEM_Null ){
popStack(&pTos, 2);
if( pOp->p2 ){
if( pOp->p1 ) pc = pOp->p2-1;
}else{
pTos++;
pTos->flags = MEM_Null;
}
break;
}else{
Stringify(pTos);
Stringify(pNos);
c = strcmp(pNos->z, pTos->z);
}
/* The asserts on each case of the following switch are there to verify
** that string comparison opcodes are always exactly 6 greater than the
** corresponding numeric comparison opcodes. The code generator depends
** on this fact.
*/
switch( pOp->opcode ){
case OP_StrEq: c = c==0; assert( pOp->opcode-6==OP_Eq ); break;
case OP_StrNe: c = c!=0; assert( pOp->opcode-6==OP_Ne ); break;
case OP_StrLt: c = c<0; assert( pOp->opcode-6==OP_Lt ); break;
case OP_StrLe: c = c<=0; assert( pOp->opcode-6==OP_Le ); break;
case OP_StrGt: c = c>0; assert( pOp->opcode-6==OP_Gt ); break;
default: c = c>=0; assert( pOp->opcode-6==OP_Ge ); break;
}
popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
pTos++;
pTos->flags = MEM_Int;
pTos->i = c;
}
break;
}
/* Opcode: And * * *
**
** Pop two values off the stack. Take the logical AND of the
** two values and push the resulting boolean value back onto the
** stack.
*/
/* Opcode: Or * * *
**
** Pop two values off the stack. Take the logical OR of the
** two values and push the resulting boolean value back onto the
** stack.
*/
case OP_And:
case OP_Or: {
Mem *pNos = &pTos[-1];
int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
assert( pNos>=p->aStack );
if( pTos->flags & MEM_Null ){
v1 = 2;
}else{
Integerify(pTos);
v1 = pTos->i==0;
}
if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
Integerify(pNos);
v2 = pNos->i==0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
v1 = and_logic[v1*3+v2];
}else{
static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
v1 = or_logic[v1*3+v2];
}
popStack(&pTos, 2);
pTos++;
if( v1==2 ){
pTos->flags = MEM_Null;
}else{
pTos->i = v1==0;
pTos->flags = MEM_Int;
}
break;
}
/* Opcode: Negative * * *
**
** Treat the top of the stack as a numeric quantity. Replace it
** with its additive inverse. If the top of the stack is NULL
** its value is unchanged.
*/
/* Opcode: AbsValue * * *
**
** Treat the top of the stack as a numeric quantity. Replace it
** with its absolute value. If the top of the stack is NULL
** its value is unchanged.
*/
case OP_Negative:
case OP_AbsValue: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Real ){
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
}
pTos->flags = MEM_Real;
}else if( pTos->flags & MEM_Int ){
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->i<0 ){
pTos->i = -pTos->i;
}
pTos->flags = MEM_Int;
}else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
Realify(pTos);
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
}
pTos->flags = MEM_Real;
}
break;
}
/* Opcode: Not * * *
**
** Interpret the top of the stack as a boolean value. Replace it
** with its complement. If the top of the stack is NULL its value
** is unchanged.
*/
case OP_Not: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
Integerify(pTos);
Release(pTos);
pTos->i = !pTos->i;
pTos->flags = MEM_Int;
break;
}
/* Opcode: BitNot * * *
**
** Interpret the top of the stack as an value. Replace it
** with its ones-complement. If the top of the stack is NULL its
** value is unchanged.
*/
case OP_BitNot: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
Integerify(pTos);
Release(pTos);
pTos->i = ~pTos->i;
pTos->flags = MEM_Int;
break;
}
/* Opcode: Noop * * *
**
** Do nothing. This instruction is often useful as a jump
** destination.
*/
case OP_Noop: {
break;
}
/* Opcode: If P1 P2 *
**
** Pop a single boolean from the stack. If the boolean popped is
** true, then jump to p2. Otherwise continue to the next instruction.
** An integer is false if zero and true otherwise. A string is
** false if it has zero length and true otherwise.
**
** If the value popped of the stack is NULL, then take the jump if P1
** is true and fall through if P1 is false.
*/
/* Opcode: IfNot P1 P2 *
**
** Pop a single boolean from the stack. If the boolean popped is
** false, then jump to p2. Otherwise continue to the next instruction.
** An integer is false if zero and true otherwise. A string is
** false if it has zero length and true otherwise.
**
** If the value popped of the stack is NULL, then take the jump if P1
** is true and fall through if P1 is false.
*/
case OP_If:
case OP_IfNot: {
int c;
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ){
c = pOp->p1;
}else{
Integerify(pTos);
c = pTos->i;
if( pOp->opcode==OP_IfNot ) c = !c;
}
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
if( c ) pc = pOp->p2-1;
break;
}
/* Opcode: IsNull P1 P2 *
**
** If any of the top abs(P1) values on the stack are NULL, then jump
** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
** unchanged.
*/
case OP_IsNull: {
int i, cnt;
Mem *pTerm;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
pTerm = &pTos[1-cnt];
assert( pTerm>=p->aStack );
for(i=0; iflags & MEM_Null ){
pc = pOp->p2-1;
break;
}
}
if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
/* Opcode: NotNull P1 P2 *
**
** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the
** stack if P1 times if P1 is greater than zero. If P1 is less than
** zero then leave the stack unchanged.
*/
case OP_NotNull: {
int i, cnt;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
assert( &pTos[1-cnt] >= p->aStack );
for(i=0; i=cnt ) pc = pOp->p2-1;
if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
/* Opcode: MakeRecord P1 P2 *
**
** Convert the top P1 entries of the stack into a single entry
** suitable for use as a data record in a database table. The
** details of the format are irrelavant as long as the OP_Column
** opcode can decode the record later. Refer to source code
** comments for the details of the record format.
**
** If P2 is true (non-zero) and one or more of the P1 entries
** that go into building the record is NULL, then add some extra
** bytes to the record to make it distinct for other entries created
** during the same run of the VDBE. The extra bytes added are a
** counter that is reset with each run of the VDBE, so records
** created this way will not necessarily be distinct across runs.
** But they should be distinct for transient tables (created using
** OP_OpenTemp) which is what they are intended for.
**
** (Later:) The P2==1 option was intended to make NULLs distinct
** for the UNION operator. But I have since discovered that NULLs
** are indistinct for UNION. So this option is never used.
*/
case OP_MakeRecord: {
char *zNewRecord;
int nByte;
int nField;
int i, j;
int idxWidth;
u32 addr;
Mem *pRec;
int addUnique = 0; /* True to cause bytes to be added to make the
** generated record distinct */
char zTemp[NBFS]; /* Temp space for small records */
/* Assuming the record contains N fields, the record format looks
** like this:
**
** -------------------------------------------------------------------
** | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |
** -------------------------------------------------------------------
**
** All data fields are converted to strings before being stored and
** are stored with their null terminators. NULL entries omit the
** null terminator. Thus an empty string uses 1 byte and a NULL uses
** zero bytes. Data(0) is taken from the lowest element of the stack
** and data(N-1) is the top of the stack.
**
** Each of the idx() entries is either 1, 2, or 3 bytes depending on
** how big the total record is. Idx(0) contains the offset to the start
** of data(0). Idx(k) contains the offset to the start of data(k).
** Idx(N) contains the total number of bytes in the record.
*/
nField = pOp->p1;
pRec = &pTos[1-nField];
assert( pRec>=p->aStack );
nByte = 0;
for(i=0; iflags & MEM_Null ){
addUnique = pOp->p2;
}else{
Stringify(pRec);
nByte += pRec->n;
}
}
if( addUnique ) nByte += sizeof(p->uniqueCnt);
if( nByte + nField + 1 < 256 ){
idxWidth = 1;
}else if( nByte + 2*nField + 2 < 65536 ){
idxWidth = 2;
}else{
idxWidth = 3;
}
nByte += idxWidth*(nField + 1);
if( nByte>MAX_BYTES_PER_ROW ){
rc = SQLITE_TOOBIG;
goto abort_due_to_error;
}
if( nByte<=NBFS ){
zNewRecord = zTemp;
}else{
zNewRecord = sqliteMallocRaw( nByte );
if( zNewRecord==0 ) goto no_mem;
}
j = 0;
addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt);
for(i=0, pRec=&pTos[1-nField]; i1 ){
zNewRecord[j++] = (addr>>8)&0xff;
if( idxWidth>2 ){
zNewRecord[j++] = (addr>>16)&0xff;
}
}
if( (pRec->flags & MEM_Null)==0 ){
addr += pRec->n;
}
}
zNewRecord[j++] = addr & 0xff;
if( idxWidth>1 ){
zNewRecord[j++] = (addr>>8)&0xff;
if( idxWidth>2 ){
zNewRecord[j++] = (addr>>16)&0xff;
}
}
if( addUnique ){
memcpy(&zNewRecord[j], &p->uniqueCnt, sizeof(p->uniqueCnt));
p->uniqueCnt++;
j += sizeof(p->uniqueCnt);
}
for(i=0, pRec=&pTos[1-nField]; iflags & MEM_Null)==0 ){
memcpy(&zNewRecord[j], pRec->z, pRec->n);
j += pRec->n;
}
}
popStack(&pTos, nField);
pTos++;
pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewRecord==zTemp );
memcpy(pTos->zShort, zTemp, nByte);
pTos->z = pTos->zShort;
pTos->flags = MEM_Str | MEM_Short;
}else{
assert( zNewRecord!=zTemp );
pTos->z = zNewRecord;
pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
/* Opcode: MakeKey P1 P2 P3
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index. The top P1 records are
** converted to strings and merged. The null-terminators
** are retained and used as separators.
** The lowest entry in the stack is the first field and the top of the
** stack becomes the last.
**
** If P2 is not zero, then the original entries remain on the stack
** and the new key is pushed on top. If P2 is zero, the original
** data is popped off the stack first then the new key is pushed
** back in its place.
**
** P3 is a string that is P1 characters long. Each character is either
** an 'n' or a 't' to indicates if the argument should be intepreted as
** numeric or text type. The first character of P3 corresponds to the
** lowest element on the stack. If P3 is NULL then all arguments are
** assumed to be of the numeric type.
**
** The type makes a difference in that text-type fields may not be
** introduced by 'b' (as described in the next paragraph). The
** first character of a text-type field must be either 'a' (if it is NULL)
** or 'c'. Numeric fields will be introduced by 'b' if their content
** looks like a well-formed number. Otherwise the 'a' or 'c' will be
** used.
**
** The key is a concatenation of fields. Each field is terminated by
** a single 0x00 character. A NULL field is introduced by an 'a' and
** is followed immediately by its 0x00 terminator. A numeric field is
** introduced by a single character 'b' and is followed by a sequence
** of characters that represent the number such that a comparison of
** the character string using memcpy() sorts the numbers in numerical
** order. The character strings for numbers are generated using the
** sqliteRealToSortable() function. A text field is introduced by a
** 'c' character and is followed by the exact text of the field. The
** use of an 'a', 'b', or 'c' character at the beginning of each field
** guarantees that NULLs sort before numbers and that numbers sort
** before text. 0x00 characters do not occur except as separators
** between fields.
**
** See also: MakeIdxKey, SortMakeKey
*/
/* Opcode: MakeIdxKey P1 P2 P3
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index. In addition, take one additional integer
** off of the stack, treat that integer as a four-byte record number, and
** append the four bytes to the key. Thus a total of P1+1 entries are
** popped from the stack for this instruction and a single entry is pushed
** back. The first P1 entries that are popped are strings and the last
** entry (the lowest on the stack) is an integer record number.
**
** The converstion of the first P1 string entries occurs just like in
** MakeKey. Each entry is separated from the others by a null.
** The entire concatenation is null-terminated. The lowest entry
** in the stack is the first field and the top of the stack becomes the
** last.
**
** If P2 is not zero and one or more of the P1 entries that go into the
** generated key is NULL, then jump to P2 after the new key has been
** pushed on the stack. In other words, jump to P2 if the key is
** guaranteed to be unique. This jump can be used to skip a subsequent
** uniqueness test.
**
** P3 is a string that is P1 characters long. Each character is either
** an 'n' or a 't' to indicates if the argument should be numeric or
** text. The first character corresponds to the lowest element on the
** stack. If P3 is null then all arguments are assumed to be numeric.
**
** See also: MakeKey, SortMakeKey
*/
case OP_MakeIdxKey:
case OP_MakeKey: {
char *zNewKey;
int nByte;
int nField;
int addRowid;
int i, j;
int containsNull = 0;
Mem *pRec;
char zTemp[NBFS];
addRowid = pOp->opcode==OP_MakeIdxKey;
nField = pOp->p1;
pRec = &pTos[1-nField];
assert( pRec>=p->aStack );
nByte = 0;
for(j=0, i=0; iflags;
int len;
char *z;
if( flags & MEM_Null ){
nByte += 2;
containsNull = 1;
}else if( pOp->p3 && pOp->p3[j]=='t' ){
Stringify(pRec);
pRec->flags &= ~(MEM_Int|MEM_Real);
nByte += pRec->n+1;
}else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){
if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){
pRec->r = pRec->i;
}else if( (flags & (MEM_Real|MEM_Int))==0 ){
pRec->r = sqliteAtoF(pRec->z, 0);
}
Release(pRec);
z = pRec->zShort;
sqliteRealToSortable(pRec->r, z);
len = strlen(z);
pRec->z = 0;
pRec->flags = MEM_Real;
pRec->n = len+1;
nByte += pRec->n+1;
}else{
nByte += pRec->n+1;
}
}
if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
rc = SQLITE_TOOBIG;
goto abort_due_to_error;
}
if( addRowid ) nByte += sizeof(u32);
if( nByte<=NBFS ){
zNewKey = zTemp;
}else{
zNewKey = sqliteMallocRaw( nByte );
if( zNewKey==0 ) goto no_mem;
}
j = 0;
pRec = &pTos[1-nField];
for(i=0; iflags & MEM_Null ){
zNewKey[j++] = 'a';
zNewKey[j++] = 0;
}else if( pRec->flags==MEM_Real ){
zNewKey[j++] = 'b';
memcpy(&zNewKey[j], pRec->zShort, pRec->n);
j += pRec->n;
}else{
assert( pRec->flags & MEM_Str );
zNewKey[j++] = 'c';
memcpy(&zNewKey[j], pRec->z, pRec->n);
j += pRec->n;
}
}
if( addRowid ){
u32 iKey;
pRec = &pTos[-nField];
assert( pRec>=p->aStack );
Integerify(pRec);
iKey = intToKey(pRec->i);
memcpy(&zNewKey[j], &iKey, sizeof(u32));
popStack(&pTos, nField+1);
if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
}else{
if( pOp->p2==0 ) popStack(&pTos, nField);
}
pTos++;
pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewKey==zTemp );
pTos->z = pTos->zShort;
memcpy(pTos->zShort, zTemp, nByte);
pTos->flags = MEM_Str | MEM_Short;
}else{
pTos->z = zNewKey;
pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
/* Opcode: IncrKey * * *
**
** The top of the stack should contain an index key generated by
** The MakeKey opcode. This routine increases the least significant
** byte of that key by one. This is used so that the MoveTo opcode
** will move to the first entry greater than the key rather than to
** the key itself.
*/
case OP_IncrKey: {
assert( pTos>=p->aStack );
/* The IncrKey opcode is only applied to keys generated by
** MakeKey or MakeIdxKey and the results of those operands
** are always dynamic strings or zShort[] strings. So we
** are always free to modify the string in place.
*/
assert( pTos->flags & (MEM_Dyn|MEM_Short) );
pTos->z[pTos->n-1]++;
break;
}
/* Opcode: Checkpoint P1 * *
**
** Begin a checkpoint. A checkpoint is the beginning of a operation that
** is part of a larger transaction but which might need to be rolled back
** itself without effecting the containing transaction. A checkpoint will
** be automatically committed or rollback when the VDBE halts.
**
** The checkpoint is begun on the database file with index P1. The main
** database file has an index of 0 and the file used for temporary tables
** has an index of 1.
*/
case OP_Checkpoint: {
int i = pOp->p1;
if( i>=0 && inDb && db->aDb[i].pBt && db->aDb[i].inTrans==1 ){
rc = sqliteBtreeBeginCkpt(db->aDb[i].pBt);
if( rc==SQLITE_OK ) db->aDb[i].inTrans = 2;
}
break;
}
/* Opcode: Transaction P1 * *
**
** Begin a transaction. The transaction ends when a Commit or Rollback
** opcode is encountered. Depending on the ON CONFLICT setting, the
** transaction might also be rolled back if an error is encountered.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
** file used for temporary tables.
**
** A write lock is obtained on the database file when a transaction is
** started. No other process can read or write the file while the
** transaction is underway. Starting a transaction also creates a
** rollback journal. A transaction must be started before any changes
** can be made to the database.
*/
case OP_Transaction: {
int busy = 1;
int i = pOp->p1;
assert( i>=0 && inDb );
if( db->aDb[i].inTrans ) break;
while( db->aDb[i].pBt!=0 && busy ){
rc = sqliteBtreeBeginTrans(db->aDb[i].pBt);
switch( rc ){
case SQLITE_BUSY: {
if( db->xBusyCallback==0 ){
p->pc = pc;
p->undoTransOnError = 1;
p->rc = SQLITE_BUSY;
p->pTos = pTos;
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
busy = 0;
}
break;
}
case SQLITE_READONLY: {
rc = SQLITE_OK;
/* Fall thru into the next case */
}
case SQLITE_OK: {
p->inTempTrans = 0;
busy = 0;
break;
}
default: {
goto abort_due_to_error;
}
}
}
db->aDb[i].inTrans = 1;
p->undoTransOnError = 1;
break;
}
/* Opcode: Commit * * *
**
** Cause all modifications to the database that have been made since the
** last Transaction to actually take effect. No additional modifications
** are allowed until another transaction is started. The Commit instruction
** deletes the journal file and releases the write lock on the database.
** A read lock continues to be held if there are still cursors open.
*/
case OP_Commit: {
int i;
if( db->xCommitCallback!=0 ){
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
if( db->xCommitCallback(db->pCommitArg)!=0 ){
rc = SQLITE_CONSTRAINT;
}
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
}
for(i=0; rc==SQLITE_OK && inDb; i++){
if( db->aDb[i].inTrans ){
rc = sqliteBtreeCommit(db->aDb[i].pBt);
db->aDb[i].inTrans = 0;
}
}
if( rc==SQLITE_OK ){
sqliteCommitInternalChanges(db);
}else{
sqliteRollbackAll(db);
}
break;
}
/* Opcode: Rollback P1 * *
**
** Cause all modifications to the database that have been made since the
** last Transaction to be undone. The database is restored to its state
** before the Transaction opcode was executed. No additional modifications
** are allowed until another transaction is started.
**
** P1 is the index of the database file that is committed. An index of 0
** is used for the main database and an index of 1 is used for the file used
** to hold temporary tables.
**
** This instruction automatically closes all cursors and releases both
** the read and write locks on the indicated database.
*/
case OP_Rollback: {
sqliteRollbackAll(db);
break;
}
/* Opcode: ReadCookie P1 P2 *
**
** Read cookie number P2 from database P1 and push it onto the stack.
** P2==0 is the schema version. P2==1 is the database format.
** P2==2 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: {
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p2p1>=0 && pOp->p1nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
pTos++;
pTos->i = aMeta[1+pOp->p2];
pTos->flags = MEM_Int;
break;
}
/* Opcode: SetCookie P1 P2 *
**
** Write the top of the stack into cookie number P2 of database P1.
** P2==0 is the schema version. P2==1 is the database format.
** P2==2 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: {
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p2p1>=0 && pOp->p1nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
assert( pTos>=p->aStack );
Integerify(pTos)
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK ){
aMeta[1+pOp->p2] = pTos->i;
rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta);
}
Release(pTos);
pTos--;
break;
}
/* Opcode: VerifyCookie P1 P2 *
**
** Check the value of global database parameter number 0 (the
** schema version) and make sure it is equal to P2.
** P1 is the database number which is 0 for the main database file
** and 1 for the file holding temporary tables and some higher number
** for auxiliary databases.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p1>=0 && pOp->p1nDb );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK && aMeta[1]!=pOp->p2 ){
sqliteSetString(&p->zErrMsg, "database schema has changed", (char*)0);
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: OpenRead P1 P2 P3
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by an
** integer from the top of the stack. 0 means the main database and
** 1 means the database used for temporary tables. Give the new
** cursor an identifier of P1. The P1 values need not be contiguous
** but all P1 values should be small integers. It is an error for
** P1 to be negative.
**
** If P2==0 then take the root page number from the next of the stack.
**
** There will be a read lock on the database whenever there is an
** open cursor. If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction. A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database. The read lock is
** released when all cursors are closed. If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE_BUSY error code.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. If P2==0 then take the root page number from the stack.
**
** The P3 value is the name of the table or index being opened.
** The P3 value is not actually used by this opcode and may be
** omitted. But the code generator usually inserts the index or
** table name into P3 to make the code easier to read.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode. For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
int busy = 0;
int i = pOp->p1;
int p2 = pOp->p2;
int wrFlag;
Btree *pX;
int iDb;
assert( pTos>=p->aStack );
Integerify(pTos);
iDb = pTos->i;
pTos--;
assert( iDb>=0 && iDbnDb );
pX = db->aDb[iDb].pBt;
assert( pX!=0 );
wrFlag = pOp->opcode==OP_OpenWrite;
if( p2<=0 ){
assert( pTos>=p->aStack );
Integerify(pTos);
p2 = pTos->i;
pTos--;
if( p2<2 ){
sqliteSetString(&p->zErrMsg, "root page number less than 2", (char*)0);
rc = SQLITE_INTERNAL;
break;
}
}
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
sqliteVdbeCleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
p->aCsr[i].nullRow = 1;
if( pX==0 ) break;
do{
rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
switch( rc ){
case SQLITE_BUSY: {
if( db->xBusyCallback==0 ){
p->pc = pc;
p->rc = SQLITE_BUSY;
p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
busy = 0;
}
break;
}
case SQLITE_OK: {
busy = 0;
break;
}
default: {
goto abort_due_to_error;
}
}
}while( busy );
break;
}
/* Opcode: OpenTemp P1 P2 *
**
** Open a new cursor to a transient table.
** The transient cursor is always opened read/write even if
** the main database is read-only. The transient table is deleted
** automatically when the cursor is closed.
**
** The cursor points to a BTree table if P2==0 and to a BTree index
** if P2==1. A BTree table must have an integer key and can have arbitrary
** data. A BTree index has no data but can have an arbitrary key.
**
** This opcode is used for tables that exist for the duration of a single
** SQL statement only. Tables created using CREATE TEMPORARY TABLE
** are opened using OP_OpenRead or OP_OpenWrite. "Temporary" in the
** context of this opcode means for the duration of a single SQL statement
** whereas "Temporary" in the context of CREATE TABLE means for the duration
** of the connection to the database. Same word; different meanings.
*/
case OP_OpenTemp: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
pCx->nullRow = 1;
rc = sqliteBtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);
if( rc==SQLITE_OK ){
rc = sqliteBtreeBeginTrans(pCx->pBt);
}
if( rc==SQLITE_OK ){
if( pOp->p2 ){
int pgno;
rc = sqliteBtreeCreateIndex(pCx->pBt, &pgno);
if( rc==SQLITE_OK ){
rc = sqliteBtreeCursor(pCx->pBt, pgno, 1, &pCx->pCursor);
}
}else{
rc = sqliteBtreeCursor(pCx->pBt, 2, 1, &pCx->pCursor);
}
}
break;
}
/* Opcode: OpenPseudo P1 * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data. Any attempt to write a second row of data causes the
** first row to be deleted. All data is deleted when the cursor is
** closed.
**
** A pseudo-table created by this opcode is useful for holding the
** NEW or OLD tables in a trigger.
*/
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
pCx->nullRow = 1;
pCx->pseudoTable = 1;
break;
}
/* Opcode: Close P1 * *
**
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
int i = pOp->p1;
if( i>=0 && inCursor ){
sqliteVdbeCleanupCursor(&p->aCsr[i]);
}
break;
}
/* Opcode: MoveTo P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to an entry with a matching key. If
** the table contains no record with a matching key, then the cursor
** is left pointing at the first record that is greater than the key.
** If there are no records greater than the key and P2 is not zero,
** then an immediate jump to P2 is made.
**
** See also: Found, NotFound, Distinct, MoveLt
*/
/* Opcode: MoveLt P1 P2 *
**
** Pop the top of the stack and use its value as a key. Reposition
** cursor P1 so that it points to the entry with the largest key that is
** less than the key popped from the stack.
** If there are no records less than than the key and P2
** is not zero then an immediate jump to P2 is made.
**
** See also: MoveTo
*/
case OP_MoveLt:
case OP_MoveTo: {
int i = pOp->p1;
Cursor *pC;
assert( pTos>=p->aStack );
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
int res, oc;
pC->nullRow = 0;
if( pTos->flags & MEM_Int ){
int iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
Release(pTos);
pTos--;
break;
}
sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
}else{
Stringify(pTos);
sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
sqlite_search_count++;
oc = pOp->opcode;
if( oc==OP_MoveTo && res<0 ){
sqliteBtreeNext(pC->pCursor, &res);
pC->recnoIsValid = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else if( oc==OP_MoveLt ){
if( res>=0 ){
sqliteBtreePrevious(pC->pCursor, &res);
pC->recnoIsValid = 0;
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
*/
int keysize;
res = sqliteBtreeKeySize(pC->pCursor,&keysize)!=0 || keysize==0;
}
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key does
** not exist in the table of cursor P1, then jump to P2. If the record
** does already exist, then fall thru. The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
**
** This operation is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** See also: Found, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does exist in table of P1, then jump to P2. If the record
** does not exist, then fall thru. The cursor is left pointing
** to the record if it exists. The key is popped from the stack.
**
** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The key is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
**
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
*/
case OP_Distinct:
case OP_NotFound:
case OP_Found: {
int i = pOp->p1;
int alreadyExists = 0;
Cursor *pC;
assert( pTos>=p->aStack );
assert( i>=0 && inCursor );
if( (pC = &p->aCsr[i])->pCursor!=0 ){
int res, rx;
Stringify(pTos);
rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
}
if( pOp->opcode==OP_Found ){
if( alreadyExists ) pc = pOp->p2 - 1;
}else{
if( !alreadyExists ) pc = pOp->p2 - 1;
}
if( pOp->opcode!=OP_Distinct ){
Release(pTos);
pTos--;
}
break;
}
/* Opcode: IsUnique P1 P2 *
**
** The top of the stack is an integer record number. Call this
** record number R. The next on the stack is an index key created
** using MakeIdxKey. Call it K. This instruction pops R from the
** stack but it leaves K unchanged.
**
** P1 is an index. So all but the last four bytes of K are an
** index string. The last four bytes of K are a record number.
**
** This instruction asks if there is an entry in P1 where the
** index string matches K but the record number is different
** from R. If there is no such entry, then there is an immediate
** jump to P2. If any entry does exist where the index string
** matches K but the record number is not R, then the record
** number for that entry is pushed onto the stack and control
** falls through to the next instruction.
**
** See also: Distinct, NotFound, NotExists, Found
*/
case OP_IsUnique: {
int i = pOp->p1;
Mem *pNos = &pTos[-1];
BtCursor *pCrsr;
int R;
/* Pop the value R off the top of the stack
*/
assert( pNos>=p->aStack );
Integerify(pTos);
R = pTos->i;
pTos--;
assert( i>=0 && i<=p->nCursor );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
int v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
int nKey; /* Number of bytes in K */
/* Make sure K is a string and make zKey point to K
*/
Stringify(pNos);
zKey = pNos->z;
nKey = pNos->n;
assert( nKey >= 4 );
/* Search for an entry in P1 where all but the last four bytes match K.
** If there is no such entry, jump immediately to P2.
*/
assert( p->aCsr[i].deferredMoveto==0 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res<0 ){
rc = sqliteBtreeNext(pCrsr, &res);
if( res ){
pc = pOp->p2 - 1;
break;
}
}
rc = sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
break;
}
/* At this point, pCrsr is pointing to an entry in P1 where all but
** the last for bytes of the key match K. Check to see if the last
** four bytes of the key are different from R. If the last four
** bytes equal R then jump immediately to P2.
*/
sqliteBtreeKey(pCrsr, nKey - 4, 4, (char*)&v);
v = keyToInt(v);
if( v==R ){
pc = pOp->p2 - 1;
break;
}
/* The last four bytes of the key are different from R. Convert the
** last four bytes of the key into an integer and push it onto the
** stack. (These bytes are the record number of an entry that
** violates a UNIQUE constraint.)
*/
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
}
break;
}
/* Opcode: NotExists P1 P2 *
**
** Use the top of the stack as a integer key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The integer key is popped from the stack.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( i>=0 && inCursor );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rx, iKey;
assert( pTos->flags & MEM_Int );
iKey = intToKey(pTos->i);
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
p->aCsr[i].lastRecno = pTos->i;
p->aCsr[i].recnoIsValid = res==0;
p->aCsr[i].nullRow = 0;
if( rx!=SQLITE_OK || res!=0 ){
pc = pOp->p2 - 1;
p->aCsr[i].recnoIsValid = 0;
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: NewRecno P1 * *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
*/
case OP_NewRecno: {
int i = pOp->p1;
int v = 0;
Cursor *pC;
assert( i>=0 && inCursor );
if( (pC = &p->aCsr[i])->pCursor==0 ){
v = 0;
}else{
/* The next rowid or record number (different terms for the same
** thing) is obtained in a two-step algorithm.
**
** First we attempt to find the largest existing rowid and add one
** to that. But if the largest existing rowid is already the maximum
** positive integer, we have to fall through to the second
** probabilistic algorithm
**
** The second algorithm is to select a rowid at random and see if
** it already exists in the table. If it does not exist, we have
** succeeded. If the random rowid does exist, we select a new one
** and try again, up to 1000 times.
**
** For a table with less than 2 billion entries, the probability
** of not finding a unused rowid is about 1.0e-300. This is a
** non-zero probability, but it is still vanishingly small and should
** never cause a problem. You are much, much more likely to have a
** hardware failure than for this algorithm to fail.
**
** The analysis in the previous paragraph assumes that you have a good
** source of random numbers. Is a library function like lrand48()
** good enough? Maybe. Maybe not. It's hard to know whether there
** might be subtle bugs is some implementations of lrand48() that
** could cause problems. To avoid uncertainty, SQLite uses its own
** random number generator based on the RC4 algorithm.
**
** To promote locality of reference for repetitive inserts, the
** first few attempts at chosing a random rowid pick values just a little
** larger than the previous rowid. This has been shown experimentally
** to double the speed of the COPY operation.
*/
int res, rx, cnt, x;
cnt = 0;
if( !pC->useRandomRowid ){
if( pC->nextRowidValid ){
v = pC->nextRowid;
}else{
rx = sqliteBtreeLast(pC->pCursor, &res);
if( res ){
v = 1;
}else{
sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v);
v = keyToInt(v);
if( v==0x7fffffff ){
pC->useRandomRowid = 1;
}else{
v++;
}
}
}
if( v<0x7fffffff ){
pC->nextRowidValid = 1;
pC->nextRowid = v+1;
}else{
pC->nextRowidValid = 0;
}
}
if( pC->useRandomRowid ){
v = db->priorNewRowid;
cnt = 0;
do{
if( v==0 || cnt>2 ){
sqliteRandomness(sizeof(v), &v);
if( cnt<5 ) v &= 0xffffff;
}else{
unsigned char r;
sqliteRandomness(1, &r);
v += r + 1;
}
if( v==0 ) continue;
x = intToKey(v);
rx = sqliteBtreeMoveto(pC->pCursor, &x, sizeof(int), &res);
cnt++;
}while( cnt<1000 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
if( rx==SQLITE_OK && res==0 ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: PutIntKey P1 P2 *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be an integer. The stack is popped twice by this instruction.
**
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set,
** then the current statement change count is incremented (otherwise not).
** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is
** stored for subsequent return by the sqlite_last_insert_rowid() function
** (otherwise it's unmodified).
*/
/* Opcode: PutStrKey P1 * *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be a string. The stack is popped twice by this instruction.
**
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
Mem *pNos = &pTos[-1];
int i = pOp->p1;
Cursor *pC;
assert( pNos>=p->aStack );
assert( i>=0 && inCursor );
if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
char *zKey;
int nKey, iKey;
if( pOp->opcode==OP_PutStrKey ){
Stringify(pNos);
nKey = pNos->n;
zKey = pNos->z;
}else{
assert( pNos->flags & MEM_Int );
nKey = sizeof(int);
iKey = intToKey(pNos->i);
zKey = (char*)&iKey;
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
}
if( pTos->flags & MEM_Null ){
pTos->z = 0;
pTos->n = 0;
}else{
assert( pTos->flags & MEM_Str );
}
if( pC->pseudoTable ){
/* PutStrKey does not work for pseudo-tables.
** The following assert makes sure we are not trying to use
** PutStrKey on a pseudo-table
*/
assert( pOp->opcode==OP_PutIntKey );
sqliteFree(pC->pData);
pC->iKey = iKey;
pC->nData = pTos->n;
if( pTos->flags & MEM_Dyn ){
pC->pData = pTos->z;
pTos->flags = MEM_Null;
}else{
pC->pData = sqliteMallocRaw( pC->nData );
if( pC->pData ){
memcpy(pC->pData, pTos->z, pC->nData);
}
}
pC->nullRow = 0;
}else{
rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
popStack(&pTos, 2);
break;
}
/* Opcode: Delete P1 P2 *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op. Hence it is OK to delete
** a record from within an Next loop.
**
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set,
** then the current statement change count is incremented (otherwise not).
**
** If P1 is a pseudo-table, then this instruction is a no-op.
*/
case OP_Delete: {
int i = pOp->p1;
Cursor *pC;
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
sqliteVdbeCursorMoveto(pC);
rc = sqliteBtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
}
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
break;
}
/* Opcode: SetCounts * * *
**
** Called at end of statement. Updates lsChange (last statement change count)
** and resets csChange (current statement change count) to 0.
*/
case OP_SetCounts: {
db->lsChange=db->csChange;
db->csChange=0;
break;
}
/* Opcode: KeyAsData P1 P2 *
**
** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data. This is used for
** processing compound selects.
*/
case OP_KeyAsData: {
int i = pOp->p1;
assert( i>=0 && inCursor );
p->aCsr[i].keyAsData = pOp->p2;
break;
}
/* Opcode: RowData P1 * *
**
** Push onto the stack the complete row data for cursor P1.
** There is no interpretation of the data. It is just copied
** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
/* Opcode: RowKey P1 * *
**
** Push onto the stack the complete row key for cursor P1.
** There is no interpretation of the key. It is just copied
** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
Cursor *pC;
int n;
pTos++;
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
if( pC->nullRow ){
pTos->flags = MEM_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
sqliteVdbeCursorMoveto(pC);
if( pC->nullRow ){
pTos->flags = MEM_Null;
break;
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKeySize(pCrsr, &n);
}else{
sqliteBtreeDataSize(pCrsr, &n);
}
pTos->n = n;
if( n<=NBFS ){
pTos->flags = MEM_Str | MEM_Short;
pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( n );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
pTos->z = z;
}
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKey(pCrsr, 0, n, pTos->z);
}else{
sqliteBtreeData(pCrsr, 0, n, pTos->z);
}
}else if( pC->pseudoTable ){
pTos->n = pC->nData;
pTos->z = pC->pData;
pTos->flags = MEM_Str|MEM_Ephem;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as
** a structure built using the MakeRecord instruction.
** (See the MakeRecord opcode for additional information about
** the format of the data.)
** Push onto the stack the value of the P2-th column contained
** in the data.
**
** If the KeyAsData opcode has previously executed on this cursor,
** then the field might be extracted from the key rather than the
** data.
**
** If P1 is negative, then the record is stored on the stack rather
** than in a table. For P1==-1, the top of the stack is used.
** For P1==-2, the next on the stack is used. And so forth. The
** value pushed is always just a pointer into the record which is
** stored further down on the stack. The column value is not copied.
*/
case OP_Column: {
int amt, offset, end, payloadSize;
int i = pOp->p1;
int p2 = pOp->p2;
Cursor *pC;
char *zRec;
BtCursor *pCrsr;
int idxWidth;
unsigned char aHdr[10];
assert( inCursor );
pTos++;
if( i<0 ){
assert( &pTos[i]>=p->aStack );
assert( pTos[i].flags & MEM_Str );
zRec = pTos[i].z;
payloadSize = pTos[i].n;
}else if( (pC = &p->aCsr[i])->pCursor!=0 ){
sqliteVdbeCursorMoveto(pC);
zRec = 0;
pCrsr = pC->pCursor;
if( pC->nullRow ){
payloadSize = 0;
}else if( pC->keyAsData ){
sqliteBtreeKeySize(pCrsr, &payloadSize);
}else{
sqliteBtreeDataSize(pCrsr, &payloadSize);
}
}else if( pC->pseudoTable ){
payloadSize = pC->nData;
zRec = pC->pData;
assert( payloadSize==0 || zRec!=0 );
}else{
payloadSize = 0;
}
/* Figure out how many bytes in the column data and where the column
** data begins.
*/
if( payloadSize==0 ){
pTos->flags = MEM_Null;
break;
}else if( payloadSize<256 ){
idxWidth = 1;
}else if( payloadSize<65536 ){
idxWidth = 2;
}else{
idxWidth = 3;
}
/* Figure out where the requested column is stored and how big it is.
*/
if( payloadSize < idxWidth*(p2+1) ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
if( zRec ){
memcpy(aHdr, &zRec[idxWidth*p2], idxWidth*2);
}else if( pC->keyAsData ){
sqliteBtreeKey(pCrsr, idxWidth*p2, idxWidth*2, (char*)aHdr);
}else{
sqliteBtreeData(pCrsr, idxWidth*p2, idxWidth*2, (char*)aHdr);
}
offset = aHdr[0];
end = aHdr[idxWidth];
if( idxWidth>1 ){
offset |= aHdr[1]<<8;
end |= aHdr[idxWidth+1]<<8;
if( idxWidth>2 ){
offset |= aHdr[2]<<16;
end |= aHdr[idxWidth+2]<<16;
}
}
amt = end - offset;
if( amt<0 || offset<0 || end>payloadSize ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
/* amt and offset now hold the offset to the start of data and the
** amount of data. Go get the data and put it on the stack.
*/
pTos->n = amt;
if( amt==0 ){
pTos->flags = MEM_Null;
}else if( zRec ){
pTos->flags = MEM_Str | MEM_Ephem;
pTos->z = &zRec[offset];
}else{
if( amt<=NBFS ){
pTos->flags = MEM_Str | MEM_Short;
pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
pTos->z = z;
}
if( pC->keyAsData ){
sqliteBtreeKey(pCrsr, offset, amt, pTos->z);
}else{
sqliteBtreeData(pCrsr, offset, amt, pTos->z);
}
}
break;
}
/* Opcode: Recno P1 * *
**
** Push onto the stack an integer which is the first 4 bytes of the
** the key to the current entry in a sequential scan of the database
** file P1. The sequential scan should have been started using the
** Next opcode.
*/
case OP_Recno: {
int i = pOp->p1;
Cursor *pC;
int v;
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
sqliteVdbeCursorMoveto(pC);
pTos++;
if( pC->recnoIsValid ){
v = pC->lastRecno;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
}else if( pC->nullRow || pC->pCursor==0 ){
pTos->flags = MEM_Null;
break;
}else{
assert( pC->pCursor!=0 );
sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
}
pTos->i = v;
pTos->flags = MEM_Int;
break;
}
/* Opcode: FullKey P1 * *
**
** Extract the complete key from the record that cursor P1 is currently
** pointing to and push the key onto the stack as a string.
**
** Compare this opcode to Recno. The Recno opcode extracts the first
** 4 bytes of the key and pushes those bytes onto the stack as an
** integer. This instruction pushes the entire key as a string.
**
** This opcode may not be used on a pseudo-table.
*/
case OP_FullKey: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( p->aCsr[i].keyAsData );
assert( !p->aCsr[i].pseudoTable );
assert( i>=0 && inCursor );
pTos++;
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int amt;
char *z;
sqliteVdbeCursorMoveto(&p->aCsr[i]);
sqliteBtreeKeySize(pCrsr, &amt);
if( amt<=0 ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
if( amt>NBFS ){
z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Str | MEM_Dyn;
}else{
z = pTos->zShort;
pTos->flags = MEM_Str | MEM_Short;
}
sqliteBtreeKey(pCrsr, 0, amt, z);
pTos->z = z;
pTos->n = amt;
}
break;
}
/* Opcode: NullRow P1 * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always push
** a NULL onto the stack.
*/
case OP_NullRow: {
int i = pOp->p1;
assert( i>=0 && inCursor );
p->aCsr[i].nullRow = 1;
p->aCsr[i].recnoIsValid = 0;
break;
}
/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
rc = sqliteBtreeLast(pCrsr, &res);
pC->nullRow = res;
pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else{
pC->nullRow = 0;
}
break;
}
/* Opcode: Rewind P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && inCursor );
pC = &p->aCsr[i];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
rc = sqliteBtreeFirst(pCrsr, &res);
pC->atFirst = res==0;
pC->nullRow = res;
pC->deferredMoveto = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
}else{
pC->nullRow = 0;
}
break;
}
/* Opcode: Next P1 P2 *
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
** to the following instruction. But if the cursor advance was successful,
** jump immediately to P2.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 *
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2.
*/
case OP_Prev:
case OP_Next: {
Cursor *pC;
BtCursor *pCrsr;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = &p->aCsr[pOp->p1];
if( (pCrsr = pC->pCursor)!=0 ){
int res;
if( pC->nullRow ){
res = 1;
}else{
assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) :
sqliteBtreePrevious(pCrsr, &res);
pC->nullRow = res;
}
if( res==0 ){
pc = pOp->p2 - 1;
sqlite_search_count++;
}
}else{
pC->nullRow = 1;
}
pC->recnoIsValid = 0;
break;
}
/* Opcode: IdxPut P1 P2 P3
**
** The top of the stack holds a SQL index key made using the
** MakeIdxKey instruction. This opcode writes that key into the
** index P1. Data for the entry is nil.
**
** If P2==1, then the key must be unique. If the key is not unique,
** the program aborts with a SQLITE_CONSTRAINT error and the database
** is rolled back. If P3 is not null, then it becomes part of the
** error message returned with the SQLITE_CONSTRAINT.
*/
case OP_IdxPut: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( i>=0 && inCursor );
assert( pTos->flags & MEM_Str );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int nKey = pTos->n;
const char *zKey = pTos->z;
if( pOp->p2 ){
int res, n;
assert( nKey >= 4 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
while( res!=0 ){
int c;
sqliteBtreeKeySize(pCrsr, &n);
if( n==nKey
&& sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &c)==SQLITE_OK
&& c==0
){
rc = SQLITE_CONSTRAINT;
if( pOp->p3 && pOp->p3[0] ){
sqliteSetString(&p->zErrMsg, pOp->p3, (char*)0);
}
goto abort_due_to_error;
}
if( res<0 ){
sqliteBtreeNext(pCrsr, &res);
res = +1;
}else{
break;
}
}
}
rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( p->aCsr[i].deferredMoveto==0 );
}
Release(pTos);
pTos--;
break;
}
/* Opcode: IdxDelete P1 * *
**
** The top of the stack is an index key built using the MakeIdxKey opcode.
** This opcode removes that entry from the index.
*/
case OP_IdxDelete: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( pTos->flags & MEM_Str );
assert( i>=0 && inCursor );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int rx, res;
rx = sqliteBtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
if( rx==SQLITE_OK && res==0 ){
rc = sqliteBtreeDelete(pCrsr);
}
assert( p->aCsr[i].deferredMoveto==0 );
}
Release(pTos);
pTos--;
break;
}
/* Opcode: IdxRecno P1 * *
**
** Push onto the stack an integer which is the last 4 bytes of the
** the key to the current entry in index P1. These 4 bytes should
** be the record number of the table entry to which this index entry
** points.
**
** See also: Recno, MakeIdxKey.
*/
case OP_IdxRecno: {
int i = pOp->p1;
BtCursor *pCrsr;
assert( i>=0 && inCursor );
pTos++;
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int v;
int sz;
assert( p->aCsr[i].deferredMoveto==0 );
sqliteBtreeKeySize(pCrsr, &sz);
if( szflags = MEM_Null;
}else{
sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
v = keyToInt(v);
pTos->i = v;
pTos->flags = MEM_Int;
}
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: IdxGT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxGE P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is greater than or equal to
** the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
/* Opcode: IdxLT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
** index entry. If the index entry is less than the top of the stack
** then jump to P2. Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
int i= pOp->p1;
BtCursor *pCrsr;
assert( i>=0 && inCursor );
assert( pTos>=p->aStack );
if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
Stringify(pTos);
assert( p->aCsr[i].deferredMoveto==0 );
rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
if( rc!=SQLITE_OK ){
break;
}
if( pOp->opcode==OP_IdxLT ){
res = -res;
}else if( pOp->opcode==OP_IdxGE ){
res++;
}
if( res>0 ){
pc = pOp->p2 - 1 ;
}
}
Release(pTos);
pTos--;
break;
}
/* Opcode: IdxIsNull P1 P2 *
**
** The top of the stack contains an index entry such as might be generated
** by the MakeIdxKey opcode. This routine looks at the first P1 fields of
** that key. If any of the first P1 fields are NULL, then a jump is made
** to address P2. Otherwise we fall straight through.
**
** The index entry is always popped from the stack.
*/
case OP_IdxIsNull: {
int i = pOp->p1;
int k, n;
const char *z;
assert( pTos>=p->aStack );
assert( pTos->flags & MEM_Str );
z = pTos->z;
n = pTos->n;
for(k=0; k0; i--){
if( z[k]=='a' ){
pc = pOp->p2-1;
break;
}
while( kaDb[pOp->p2].pBt, pOp->p1);
break;
}
/* Opcode: Clear P1 P2 *
**
** Delete all contents of the database table or index whose root page
** in the database file is given by P1. But, unlike Destroy, do not
** remove the table or index from the database file.
**
** The table being clear is in the main database file if P2==0. If
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** See also: Destroy
*/
case OP_Clear: {
rc = sqliteBtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
break;
}
/* Opcode: CreateTable * P2 P3
**
** Allocate a new table in the main database file if P2==0 or in the
** auxiliary database file if P2==1. Push the page number
** for the root page of the new table onto the stack.
**
** The root page number is also written to a memory location that P3
** points to. This is the mechanism is used to write the root page
** number into the parser's internal data structures that describe the
** new table.
**
** The difference between a table and an index is this: A table must
** have a 4-byte integer key and can have arbitrary data. An index
** has an arbitrary key but no data.
**
** See also: CreateIndex
*/
/* Opcode: CreateIndex * P2 P3
**
** Allocate a new index in the main database file if P2==0 or in the
** auxiliary database file if P2==1. Push the page number of the
** root page of the new index onto the stack.
**
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex:
case OP_CreateTable: {
int pgno;
assert( pOp->p3!=0 && pOp->p3type==P3_POINTER );
assert( pOp->p2>=0 && pOp->p2nDb );
assert( db->aDb[pOp->p2].pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
rc = sqliteBtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno);
}else{
rc = sqliteBtreeCreateIndex(db->aDb[pOp->p2].pBt, &pgno);
}
pTos++;
if( rc==SQLITE_OK ){
pTos->i = pgno;
pTos->flags = MEM_Int;
*(u32*)pOp->p3 = pgno;
pOp->p3 = 0;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: IntegrityCk P1 P2 *
**
** Do an analysis of the currently open database. Push onto the
** stack the text of an error message describing any problems.
** If there are no errors, push a "ok" onto the stack.
**
** P1 is the index of a set that contains the root page numbers
** for all tables and indices in the main database file. The set
** is cleared by this opcode. In other words, after this opcode
** has executed, the set will be empty.
**
** If P2 is not zero, the check is done on the auxiliary database
** file, not the main database file.
**
** This opcode is used for testing purposes only.
*/
case OP_IntegrityCk: {
int nRoot;
int *aRoot;
int iSet = pOp->p1;
Set *pSet;
int j;
HashElem *i;
char *z;
assert( iSet>=0 && iSetnSet );
pTos++;
pSet = &p->aSet[iSet];
nRoot = sqliteHashCount(&pSet->hash);
aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
for(j=0, i=sqliteHashFirst(&pSet->hash); i; i=sqliteHashNext(i), j++){
toInt((char*)sqliteHashKey(i), &aRoot[j]);
}
aRoot[j] = 0;
sqliteHashClear(&pSet->hash);
pSet->prev = 0;
z = sqliteBtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
if( z==0 || z[0]==0 ){
if( z ) sqliteFree(z);
pTos->z = "ok";
pTos->n = 3;
pTos->flags = MEM_Str | MEM_Static;
}else{
pTos->z = z;
pTos->n = strlen(z) + 1;
pTos->flags = MEM_Str | MEM_Dyn;
}
sqliteFree(aRoot);
break;
}
/* Opcode: ListWrite * * *
**
** Write the integer on the top of the stack
** into the temporary storage list.
*/
case OP_ListWrite: {
Keylist *pKeylist;
assert( pTos>=p->aStack );
pKeylist = p->pList;
if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
if( pKeylist==0 ) goto no_mem;
pKeylist->nKey = 1000;
pKeylist->nRead = 0;
pKeylist->nUsed = 0;
pKeylist->pNext = p->pList;
p->pList = pKeylist;
}
Integerify(pTos);
pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
Release(pTos);
pTos--;
break;
}
/* Opcode: ListRewind * * *
**
** Rewind the temporary buffer back to the beginning.
*/
case OP_ListRewind: {
/* What this opcode codes, really, is reverse the order of the
** linked list of Keylist structures so that they are read out
** in the same order that they were read in. */
Keylist *pRev, *pTop;
pRev = 0;
while( p->pList ){
pTop = p->pList;
p->pList = pTop->pNext;
pTop->pNext = pRev;
pRev = pTop;
}
p->pList = pRev;
break;
}
/* Opcode: ListRead * P2 *
**
** Attempt to read an integer from the temporary storage buffer
** and push it onto the stack. If the storage buffer is empty,
** push nothing but instead jump to P2.
*/
case OP_ListRead: {
Keylist *pKeylist;
CHECK_FOR_INTERRUPT;
pKeylist = p->pList;
if( pKeylist!=0 ){
assert( pKeylist->nRead>=0 );
assert( pKeylist->nReadnUsed );
assert( pKeylist->nReadnKey );
pTos++;
pTos->i = pKeylist->aKey[pKeylist->nRead++];
pTos->flags = MEM_Int;
if( pKeylist->nRead>=pKeylist->nUsed ){
p->pList = pKeylist->pNext;
sqliteFree(pKeylist);
}
}else{
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: ListReset * * *
**
** Reset the temporary storage buffer so that it holds nothing.
*/
case OP_ListReset: {
if( p->pList ){
sqliteVdbeKeylistFree(p->pList);
p->pList = 0;
}
break;
}
/* Opcode: ListPush * * *
**
** Save the current Vdbe list such that it can be restored by a ListPop
** opcode. The list is empty after this is executed.
*/
case OP_ListPush: {
p->keylistStackDepth++;
assert(p->keylistStackDepth > 0);
p->keylistStack = sqliteRealloc(p->keylistStack,
sizeof(Keylist *) * p->keylistStackDepth);
if( p->keylistStack==0 ) goto no_mem;
p->keylistStack[p->keylistStackDepth - 1] = p->pList;
p->pList = 0;
break;
}
/* Opcode: ListPop * * *
**
** Restore the Vdbe list to the state it was in when ListPush was last
** executed.
*/
case OP_ListPop: {
assert(p->keylistStackDepth > 0);
p->keylistStackDepth--;
sqliteVdbeKeylistFree(p->pList);
p->pList = p->keylistStack[p->keylistStackDepth];
p->keylistStack[p->keylistStackDepth] = 0;
if( p->keylistStackDepth == 0 ){
sqliteFree(p->keylistStack);
p->keylistStack = 0;
}
break;
}
/* Opcode: ContextPush * * *
**
** Save the current Vdbe context such that it can be restored by a ContextPop
** opcode. The context stores the last insert row id, the last statement change
** count, and the current statement change count.
*/
case OP_ContextPush: {
p->contextStackDepth++;
assert(p->contextStackDepth > 0);
p->contextStack = sqliteRealloc(p->contextStack,
sizeof(Context) * p->contextStackDepth);
if( p->contextStack==0 ) goto no_mem;
p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid;
p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange;
p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange;
break;
}
/* Opcode: ContextPop * * *
**
** Restore the Vdbe context to the state it was in when contextPush was last
** executed. The context stores the last insert row id, the last statement
** change count, and the current statement change count.
*/
case OP_ContextPop: {
assert(p->contextStackDepth > 0);
p->contextStackDepth--;
p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid;
p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange;
p->db->csChange = p->contextStack[p->contextStackDepth].csChange;
if( p->contextStackDepth == 0 ){
sqliteFree(p->contextStack);
p->contextStack = 0;
}
break;
}
/* Opcode: SortPut * * *
**
** The TOS is the key and the NOS is the data. Pop both from the stack
** and put them on the sorter. The key and data should have been
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
Mem *pNos = &pTos[-1];
Sorter *pSorter;
assert( pNos>=p->aStack );
if( Dynamicify(pTos) || Dynamicify(pNos) ) goto no_mem;
pSorter = sqliteMallocRaw( sizeof(Sorter) );
if( pSorter==0 ) goto no_mem;
pSorter->pNext = p->pSort;
p->pSort = pSorter;
assert( pTos->flags & MEM_Dyn );
pSorter->nKey = pTos->n;
pSorter->zKey = pTos->z;
assert( pNos->flags & MEM_Dyn );
pSorter->nData = pNos->n;
pSorter->pData = pNos->z;
pTos -= 2;
break;
}
/* Opcode: SortMakeRec P1 * *
**
** The top P1 elements are the arguments to a callback. Form these
** elements into a single data entry that can be stored on a sorter
** using SortPut and later fed to a callback using SortCallback.
*/
case OP_SortMakeRec: {
char *z;
char **azArg;
int nByte;
int nField;
int i;
Mem *pRec;
nField = pOp->p1;
pRec = &pTos[1-nField];
assert( pRec>=p->aStack );
nByte = 0;
for(i=0; iflags & MEM_Null)==0 ){
Stringify(pRec);
nByte += pRec->n;
}
}
nByte += sizeof(char*)*(nField+1);
azArg = sqliteMallocRaw( nByte );
if( azArg==0 ) goto no_mem;
z = (char*)&azArg[nField+1];
for(pRec=&pTos[1-nField], i=0; iflags & MEM_Null ){
azArg[i] = 0;
}else{
azArg[i] = z;
memcpy(z, pRec->z, pRec->n);
z += pRec->n;
}
}
popStack(&pTos, nField);
pTos++;
pTos->n = nByte;
pTos->z = (char*)azArg;
pTos->flags = MEM_Str | MEM_Dyn;
break;
}
/* Opcode: SortMakeKey * * P3
**
** Convert the top few entries of the stack into a sort key. The
** number of stack entries consumed is the number of characters in
** the string P3. One character from P3 is prepended to each entry.
** The first character of P3 is prepended to the element lowest in
** the stack and the last character of P3 is prepended to the top of
** the stack. All stack entries are separated by a \000 character
** in the result. The whole key is terminated by two \000 characters
** in a row.
**
** "N" is substituted in place of the P3 character for NULL values.
**
** See also the MakeKey and MakeIdxKey opcodes.
*/
case OP_SortMakeKey: {
char *zNewKey;
int nByte;
int nField;
int i, j, k;
Mem *pRec;
nField = strlen(pOp->p3);
pRec = &pTos[1-nField];
nByte = 1;
for(i=0; iflags & MEM_Null ){
nByte += 2;
}else{
Stringify(pRec);
nByte += pRec->n+2;
}
}
zNewKey = sqliteMallocRaw( nByte );
if( zNewKey==0 ) goto no_mem;
j = 0;
k = 0;
for(pRec=&pTos[1-nField], i=0; iflags & MEM_Null ){
zNewKey[j++] = 'N';
zNewKey[j++] = 0;
k++;
}else{
zNewKey[j++] = pOp->p3[k++];
memcpy(&zNewKey[j], pRec->z, pRec->n-1);
j += pRec->n-1;
zNewKey[j++] = 0;
}
}
zNewKey[j] = 0;
assert( jn = nByte;
pTos->flags = MEM_Str|MEM_Dyn;
pTos->z = zNewKey;
break;
}
/* Opcode: Sort * * *
**
** Sort all elements on the sorter. The algorithm is a
** mergesort.
*/
case OP_Sort: {
int i;
Sorter *pElem;
Sorter *apSorter[NSORT];
for(i=0; ipSort ){
pElem = p->pSort;
p->pSort = pElem->pNext;
pElem->pNext = 0;
for(i=0; i=NSORT-1 ){
apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem);
}
}
pElem = 0;
for(i=0; ipSort = pElem;
break;
}
/* Opcode: SortNext * P2 *
**
** Push the data for the topmost element in the sorter onto the
** stack, then remove the element from the sorter. If the sorter
** is empty, push nothing on the stack and instead jump immediately
** to instruction P2.
*/
case OP_SortNext: {
Sorter *pSorter = p->pSort;
CHECK_FOR_INTERRUPT;
if( pSorter!=0 ){
p->pSort = pSorter->pNext;
pTos++;
pTos->z = pSorter->pData;
pTos->n = pSorter->nData;
pTos->flags = MEM_Str|MEM_Dyn;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter);
}else{
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: SortCallback P1 * *
**
** The top of the stack contains a callback record built using
** the SortMakeRec operation with the same P1 value as this
** instruction. Pop this record from the stack and invoke the
** callback on it.
*/
case OP_SortCallback: {
assert( pTos>=p->aStack );
assert( pTos->flags & MEM_Str );
p->nCallback++;
p->pc = pc+1;
p->azResColumn = (char**)pTos->z;
assert( p->nResColumn==pOp->p1 );
p->popStack = 1;
p->pTos = pTos;
return SQLITE_ROW;
}
/* Opcode: SortReset * * *
**
** Remove any elements that remain on the sorter.
*/
case OP_SortReset: {
sqliteVdbeSorterReset(p);
break;
}
/* Opcode: FileOpen * * P3
**
** Open the file named by P3 for reading using the FileRead opcode.
** If P3 is "stdin" then open standard input for reading.
*/
case OP_FileOpen: {
assert( pOp->p3!=0 );
if( p->pFile ){
if( p->pFile!=stdin ) fclose(p->pFile);
p->pFile = 0;
}
if( sqliteStrICmp(pOp->p3,"stdin")==0 ){
p->pFile = stdin;
}else{
p->pFile = fopen(pOp->p3, "r");
}
if( p->pFile==0 ){
sqliteSetString(&p->zErrMsg,"unable to open file: ", pOp->p3, (char*)0);
rc = SQLITE_ERROR;
}
break;
}
/* Opcode: FileRead P1 P2 P3
**
** Read a single line of input from the open file (the file opened using
** FileOpen). If we reach end-of-file, jump immediately to P2. If
** we are able to get another line, split the line apart using P3 as
** a delimiter. There should be P1 fields. If the input line contains
** more than P1 fields, ignore the excess. If the input line contains
** fewer than P1 fields, assume the remaining fields contain NULLs.
**
** Input ends if a line consists of just "\.". A field containing only
** "\N" is a null field. The backslash \ character can be used be used
** to escape newlines or the delimiter.
*/
case OP_FileRead: {
int n, eol, nField, i, c, nDelim;
char *zDelim, *z;
CHECK_FOR_INTERRUPT;
if( p->pFile==0 ) goto fileread_jump;
nField = pOp->p1;
if( nField<=0 ) goto fileread_jump;
if( nField!=p->nField || p->azField==0 ){
char **azField = sqliteRealloc(p->azField, sizeof(char*)*nField+1);
if( azField==0 ){ goto no_mem; }
p->azField = azField;
p->nField = nField;
}
n = 0;
eol = 0;
while( eol==0 ){
if( p->zLine==0 || n+200>p->nLineAlloc ){
char *zLine;
p->nLineAlloc = p->nLineAlloc*2 + 300;
zLine = sqliteRealloc(p->zLine, p->nLineAlloc);
if( zLine==0 ){
p->nLineAlloc = 0;
sqliteFree(p->zLine);
p->zLine = 0;
goto no_mem;
}
p->zLine = zLine;
}
if( vdbe_fgets(&p->zLine[n], p->nLineAlloc-n, p->pFile)==0 ){
eol = 1;
p->zLine[n] = 0;
}else{
int c;
while( (c = p->zLine[n])!=0 ){
if( c=='\\' ){
if( p->zLine[n+1]==0 ) break;
n += 2;
}else if( c=='\n' ){
p->zLine[n] = 0;
eol = 1;
break;
}else{
n++;
}
}
}
}
if( n==0 ) goto fileread_jump;
z = p->zLine;
if( z[0]=='\\' && z[1]=='.' && z[2]==0 ){
goto fileread_jump;
}
zDelim = pOp->p3;
if( zDelim==0 ) zDelim = "\t";
c = zDelim[0];
nDelim = strlen(zDelim);
p->azField[0] = z;
for(i=1; *z!=0 && i<=nField; i++){
int from, to;
from = to = 0;
if( z[0]=='\\' && z[1]=='N'
&& (z[2]==0 || strncmp(&z[2],zDelim,nDelim)==0) ){
if( i<=nField ) p->azField[i-1] = 0;
z += 2 + nDelim;
if( iazField[i] = z;
continue;
}
while( z[from] ){
if( z[from]=='\\' && z[from+1]!=0 ){
int tx = z[from+1];
switch( tx ){
case 'b': tx = '\b'; break;
case 'f': tx = '\f'; break;
case 'n': tx = '\n'; break;
case 'r': tx = '\r'; break;
case 't': tx = '\t'; break;
case 'v': tx = '\v'; break;
default: break;
}
z[to++] = tx;
from += 2;
continue;
}
if( z[from]==c && strncmp(&z[from],zDelim,nDelim)==0 ) break;
z[to++] = z[from++];
}
if( z[from] ){
z[to] = 0;
z += from + nDelim;
if( iazField[i] = z;
}else{
z[to] = 0;
z = "";
}
}
while( iazField[i++] = 0;
}
break;
/* If we reach end-of-file, or if anything goes wrong, jump here.
** This code will cause a jump to P2 */
fileread_jump:
pc = pOp->p2 - 1;
break;
}
/* Opcode: FileColumn P1 * *
**
** Push onto the stack the P1-th column of the most recently read line
** from the input file.
*/
case OP_FileColumn: {
int i = pOp->p1;
char *z;
assert( i>=0 && inField );
if( p->azField ){
z = p->azField[i];
}else{
z = 0;
}
pTos++;
if( z ){
pTos->n = strlen(z) + 1;
pTos->z = z;
pTos->flags = MEM_Str | MEM_Ephem;
}else{
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: MemStore P1 P2 *
**
** Write the top of the stack into memory location P1.
** P1 should be a small integer since space is allocated
** for all memory locations between 0 and P1 inclusive.
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1. If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {
int i = pOp->p1;
Mem *pMem;
assert( pTos>=p->aStack );
if( i>=p->nMem ){
int nOld = p->nMem;
Mem *aMem;
p->nMem = i + 5;
aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
if( aMem==0 ) goto no_mem;
if( aMem!=p->aMem ){
int j;
for(j=0; jaMem = aMem;
if( nOldnMem ){
memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
}
}
Deephemeralize(pTos);
pMem = &p->aMem[i];
Release(pMem);
*pMem = *pTos;
if( pMem->flags & MEM_Dyn ){
if( pOp->p2 ){
pTos->flags = MEM_Null;
}else{
pMem->z = sqliteMallocRaw( pMem->n );
if( pMem->z==0 ) goto no_mem;
memcpy(pMem->z, pTos->z, pMem->n);
}
}else if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
if( pOp->p2 ){
Release(pTos);
pTos--;
}
break;
}
/* Opcode: MemLoad P1 * *
**
** Push a copy of the value in memory location P1 onto the stack.
**
** If the value is a string, then the value pushed is a pointer to
** the string that is stored in the memory location. If the memory
** location is subsequently changed (using OP_MemStore) then the
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
int i = pOp->p1;
assert( i>=0 && inMem );
pTos++;
memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
if( pTos->flags & MEM_Str ){
pTos->flags |= MEM_Ephem;
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
}
break;
}
/* Opcode: MemIncr P1 P2 *
**
** Increment the integer valued memory cell P1 by 1. If P2 is not zero
** and the result after the increment is greater than zero, then jump
** to P2.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemIncr: {
int i = pOp->p1;
Mem *pMem;
assert( i>=0 && inMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
pMem->i++;
if( pOp->p2>0 && pMem->i>0 ){
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: AggReset * P2 *
**
** Reset the aggregator so that it no longer contains any data.
** Future aggregator elements will contain P2 values each.
*/
case OP_AggReset: {
sqliteVdbeAggReset(&p->agg);
p->agg.nMem = pOp->p2;
p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) );
if( p->agg.apFunc==0 ) goto no_mem;
break;
}
/* Opcode: AggInit * P2 P3
**
** Initialize the function parameters for an aggregate function.
** The aggregate will operate out of aggregate column P2.
** P3 is a pointer to the FuncDef structure for the function.
*/
case OP_AggInit: {
int i = pOp->p2;
assert( i>=0 && iagg.nMem );
p->agg.apFunc[i] = (FuncDef*)pOp->p3;
break;
}
/* Opcode: AggFunc * P2 P3
**
** Execute the step function for an aggregate. The
** function has P2 arguments. P3 is a pointer to the FuncDef
** structure that specifies the function.
**
** The top of the stack must be an integer which is the index of
** the aggregate column that corresponds to this aggregate function.
** Ideally, this index would be another parameter, but there are
** no free parameters left. The integer is popped from the stack.
*/
case OP_AggFunc: {
int n = pOp->p2;
int i;
Mem *pMem, *pRec;
char **azArgv = p->zArgv;
sqlite_func ctx;
assert( n>=0 );
assert( pTos->flags==MEM_Int );
pRec = &pTos[-n];
assert( pRec>=p->aStack );
for(i=0; iflags & MEM_Null ){
azArgv[i] = 0;
}else{
Stringify(pRec);
azArgv[i] = pRec->z;
}
}
i = pTos->i;
assert( i>=0 && iagg.nMem );
ctx.pFunc = (FuncDef*)pOp->p3;
pMem = &p->agg.pCurrent->aMem[i];
ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */
ctx.pAgg = pMem->z;
ctx.cnt = ++pMem->i;
ctx.isError = 0;
ctx.isStep = 1;
(ctx.pFunc->xStep)(&ctx, n, (const char**)azArgv);
pMem->z = ctx.pAgg;
pMem->flags = MEM_AggCtx;
popStack(&pTos, n+1);
if( ctx.isError ){
rc = SQLITE_ERROR;
}
break;
}
/* Opcode: AggFocus * P2 *
**
** Pop the top of the stack and use that as an aggregator key. If
** an aggregator with that same key already exists, then make the
** aggregator the current aggregator and jump to P2. If no aggregator
** with the given key exists, create one and make it current but
** do not jump.
**
** The order of aggregator opcodes is important. The order is:
** AggReset AggFocus AggNext. In other words, you must execute
** AggReset first, then zero or more AggFocus operations, then
** zero or more AggNext operations. You must not execute an AggFocus
** in between an AggNext and an AggReset.
*/
case OP_AggFocus: {
AggElem *pElem;
char *zKey;
int nKey;
assert( pTos>=p->aStack );
Stringify(pTos);
zKey = pTos->z;
nKey = pTos->n;
pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
if( pElem ){
p->agg.pCurrent = pElem;
pc = pOp->p2 - 1;
}else{
AggInsert(&p->agg, zKey, nKey);
if( sqlite_malloc_failed ) goto no_mem;
}
Release(pTos);
pTos--;
break;
}
/* Opcode: AggSet * P2 *
**
** Move the top of the stack into the P2-th field of the current
** aggregate. String values are duplicated into new memory.
*/
case OP_AggSet: {
AggElem *pFocus = AggInFocus(p->agg);
Mem *pMem;
int i = pOp->p2;
assert( pTos>=p->aStack );
if( pFocus==0 ) goto no_mem;
assert( i>=0 && iagg.nMem );
Deephemeralize(pTos);
pMem = &pFocus->aMem[i];
Release(pMem);
*pMem = *pTos;
if( pMem->flags & MEM_Dyn ){
pTos->flags = MEM_Null;
}else if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
Release(pTos);
pTos--;
break;
}
/* Opcode: AggGet * P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate. Strings are not duplicated so
** string values will be ephemeral.
*/
case OP_AggGet: {
AggElem *pFocus = AggInFocus(p->agg);
Mem *pMem;
int i = pOp->p2;
if( pFocus==0 ) goto no_mem;
assert( i>=0 && iagg.nMem );
pTos++;
pMem = &pFocus->aMem[i];
*pTos = *pMem;
if( pTos->flags & MEM_Str ){
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
pTos->flags |= MEM_Ephem;
}
if( pTos->flags & MEM_AggCtx ){
Release(pTos);
pTos->flags = MEM_Null;
}
break;
}
/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate. The prior
** aggregate is deleted. If all aggregate values have been consumed,
** jump to P2.
**
** The order of aggregator opcodes is important. The order is:
** AggReset AggFocus AggNext. In other words, you must execute
** AggReset first, then zero or more AggFocus operations, then
** zero or more AggNext operations. You must not execute an AggFocus
** in between an AggNext and an AggReset.
*/
case OP_AggNext: {
CHECK_FOR_INTERRUPT;
if( p->agg.pSearch==0 ){
p->agg.pSearch = sqliteHashFirst(&p->agg.hash);
}else{
p->agg.pSearch = sqliteHashNext(p->agg.pSearch);
}
if( p->agg.pSearch==0 ){
pc = pOp->p2 - 1;
} else {
int i;
sqlite_func ctx;
Mem *aMem;
p->agg.pCurrent = sqliteHashData(p->agg.pSearch);
aMem = p->agg.pCurrent->aMem;
for(i=0; iagg.nMem; i++){
int freeCtx;
if( p->agg.apFunc[i]==0 ) continue;
if( p->agg.apFunc[i]->xFinalize==0 ) continue;
ctx.s.flags = MEM_Null;
ctx.s.z = aMem[i].zShort;
ctx.pAgg = (void*)aMem[i].z;
freeCtx = aMem[i].z && aMem[i].z!=aMem[i].zShort;
ctx.cnt = aMem[i].i;
ctx.isStep = 0;
ctx.pFunc = p->agg.apFunc[i];
(*p->agg.apFunc[i]->xFinalize)(&ctx);
if( freeCtx ){
sqliteFree( aMem[i].z );
}
aMem[i] = ctx.s;
if( aMem[i].flags & MEM_Short ){
aMem[i].z = aMem[i].zShort;
}
}
}
break;
}
/* Opcode: SetInsert P1 * P3
**
** If Set P1 does not exist then create it. Then insert value
** P3 into that set. If P3 is NULL, then insert the top of the
** stack into the set.
*/
case OP_SetInsert: {
int i = pOp->p1;
if( p->nSet<=i ){
int k;
Set *aSet = sqliteRealloc(p->aSet, (i+1)*sizeof(p->aSet[0]) );
if( aSet==0 ) goto no_mem;
p->aSet = aSet;
for(k=p->nSet; k<=i; k++){
sqliteHashInit(&p->aSet[k].hash, SQLITE_HASH_BINARY, 1);
}
p->nSet = i+1;
}
if( pOp->p3 ){
sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
}else{
assert( pTos>=p->aStack );
Stringify(pTos);
sqliteHashInsert(&p->aSet[i].hash, pTos->z, pTos->n, p);
Release(pTos);
pTos--;
}
if( sqlite_malloc_failed ) goto no_mem;
break;
}
/* Opcode: SetFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1. If the element popped exists in set P1,
** then jump to P2. Otherwise fall through.
*/
case OP_SetFound: {
int i = pOp->p1;
assert( pTos>=p->aStack );
Stringify(pTos);
if( i>=0 && inSet && sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)){
pc = pOp->p2 - 1;
}
Release(pTos);
pTos--;
break;
}
/* Opcode: SetNotFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1. If the element popped does not exists in
** set P1, then jump to P2. Otherwise fall through.
*/
case OP_SetNotFound: {
int i = pOp->p1;
assert( pTos>=p->aStack );
Stringify(pTos);
if( i<0 || i>=p->nSet ||
sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)==0 ){
pc = pOp->p2 - 1;
}
Release(pTos);
pTos--;
break;
}
/* Opcode: SetFirst P1 P2 *
**
** Read the first element from set P1 and push it onto the stack. If the
** set is empty, push nothing and jump immediately to P2. This opcode is
** used in combination with OP_SetNext to loop over all elements of a set.
*/
/* Opcode: SetNext P1 P2 *
**
** Read the next element from set P1 and push it onto the stack. If there
** are no more elements in the set, do not do the push and fall through.
** Otherwise, jump to P2 after pushing the next set element.
*/
case OP_SetFirst:
case OP_SetNext: {
Set *pSet;
CHECK_FOR_INTERRUPT;
if( pOp->p1<0 || pOp->p1>=p->nSet ){
if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1;
break;
}
pSet = &p->aSet[pOp->p1];
if( pOp->opcode==OP_SetFirst ){
pSet->prev = sqliteHashFirst(&pSet->hash);
if( pSet->prev==0 ){
pc = pOp->p2 - 1;
break;
}
}else{
if( pSet->prev ){
pSet->prev = sqliteHashNext(pSet->prev);
}
if( pSet->prev==0 ){
break;
}else{
pc = pOp->p2 - 1;
}
}
pTos++;
pTos->z = sqliteHashKey(pSet->prev);
pTos->n = sqliteHashKeysize(pSet->prev);
pTos->flags = MEM_Str | MEM_Ephem;
break;
}
/* Opcode: Vacuum * * *
**
** Vacuum the entire database. This opcode will cause other virtual
** machines to be created and run. It may not be called from within
** a transaction.
*/
case OP_Vacuum: {
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
rc = sqliteRunVacuum(&p->zErrMsg, db);
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
break;
}
/* Opcode: StackDepth * * *
**
** Push an integer onto the stack which is the depth of the stack prior
** to that integer being pushed.
*/
case OP_StackDepth: {
int depth = (&pTos[1]) - p->aStack;
pTos++;
pTos->i = depth;
pTos->flags = MEM_Int;
break;
}
/* Opcode: StackReset * * *
**
** Pop a single integer off of the stack. Then pop the stack
** as many times as necessary to get the depth of the stack down
** to the value of the integer that was popped.
*/
case OP_StackReset: {
int depth, goal;
assert( pTos>=p->aStack );
Integerify(pTos);
goal = pTos->i;
depth = (&pTos[1]) - p->aStack;
assert( goalopcode);
sqliteSetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
rc = SQLITE_INTERNAL;
break;
}
/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces. But the left-most 6 spaces have been removed to improve the
** readability. From this point on down, the normal indentation rules are
** restored.
*****************************************************************************/
}
#ifdef VDBE_PROFILE
{
long long elapse = hwtime() - start;
pOp->cycles += elapse;
pOp->cnt++;
#if 0
fprintf(stdout, "%10lld ", elapse);
sqliteVdbePrintOp(stdout, origPc, &p->aOp[origPc]);
#endif
}
#endif
/* The following code adds nothing to the actual functionality
** of the program. It is only here for testing and debugging.
** On the other hand, it does burn CPU cycles every time through
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
/* Sanity checking on the top element of the stack */
if( pTos>=p->aStack ){
assert( pTos->flags!=0 ); /* Must define some type */
if( pTos->flags & MEM_Str ){
int x = pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
assert( x!=0 ); /* Strings must define a string subtype */
assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */
assert( pTos->z!=0 ); /* Strings must have a value */
/* Mem.z points to Mem.zShort iff the subtype is MEM_Short */
assert( (pTos->flags & MEM_Short)==0 || pTos->z==pTos->zShort );
assert( (pTos->flags & MEM_Short)!=0 || pTos->z!=pTos->zShort );
}else{
/* Cannot define a string subtype for non-string objects */
assert( (pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 );
}
/* MEM_Null excludes all other types */
assert( pTos->flags==MEM_Null || (pTos->flags&MEM_Null)==0 );
}
if( pc<-1 || pc>=p->nOp ){
sqliteSetString(&p->zErrMsg, "jump destination out of range", (char*)0);
rc = SQLITE_INTERNAL;
}
if( p->trace && pTos>=p->aStack ){
int i;
fprintf(p->trace, "Stack:");
for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){
if( pTos[i].flags & MEM_Null ){
fprintf(p->trace, " NULL");
}else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
fprintf(p->trace, " si:%d", pTos[i].i);
}else if( pTos[i].flags & MEM_Int ){
fprintf(p->trace, " i:%d", pTos[i].i);
}else if( pTos[i].flags & MEM_Real ){
fprintf(p->trace, " r:%g", pTos[i].r);
}else if( pTos[i].flags & MEM_Str ){
int j, k;
char zBuf[100];
zBuf[0] = ' ';
if( pTos[i].flags & MEM_Dyn ){
zBuf[1] = 'z';
assert( (pTos[i].flags & (MEM_Static|MEM_Ephem))==0 );
}else if( pTos[i].flags & MEM_Static ){
zBuf[1] = 't';
assert( (pTos[i].flags & (MEM_Dyn|MEM_Ephem))==0 );
}else if( pTos[i].flags & MEM_Ephem ){
zBuf[1] = 'e';
assert( (pTos[i].flags & (MEM_Static|MEM_Dyn))==0 );
}else{
zBuf[1] = 's';
}
zBuf[2] = '[';
k = 3;
for(j=0; j<20 && jtrace, "%s", zBuf);
}else{
fprintf(p->trace, " ???");
}
}
if( rc!=0 ) fprintf(p->trace," rc=%d",rc);
fprintf(p->trace,"\n");
}
#endif
} /* The end of the for(;;) loop the loops through opcodes */
/* If we reach this point, it means that execution is finished.
*/
vdbe_halt:
CHECK_FOR_INTERRUPT
if( rc ){
p->rc = rc;
rc = SQLITE_ERROR;
}else{
rc = SQLITE_DONE;
}
p->magic = VDBE_MAGIC_HALT;
p->pTos = pTos;
return rc;
/* Jump to here if a malloc() fails. It's hard to get a malloc()
** to fail on a modern VM computer, so this code is untested.
*/
no_mem:
sqliteSetString(&p->zErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
goto vdbe_halt;
/* Jump to here for an SQLITE_MISUSE error.
*/
abort_due_to_misuse:
rc = SQLITE_MISUSE;
/* Fall thru into abort_due_to_error */
/* Jump to here for any other kind of fatal error. The "rc" variable
** should hold the error number.
*/
abort_due_to_error:
if( p->zErrMsg==0 ){
if( sqlite_malloc_failed ) rc = SQLITE_NOMEM;
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
}
goto vdbe_halt;
/* Jump to here if the sqlite_interrupt() API sets the interrupt
** flag.
*/
abort_due_to_interrupt:
assert( db->flags & SQLITE_Interrupt );
db->flags &= ~SQLITE_Interrupt;
if( db->magic!=SQLITE_MAGIC_BUSY ){
rc = SQLITE_MISUSE;
}else{
rc = SQLITE_INTERRUPT;
}
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
goto vdbe_halt;
}
| vdbe.c | 454 |
vdbeaux.c |
Type | Function | Source | Line |
VDBE | sqliteVdbeCreate(sqlite *db)
Vdbe *sqliteVdbeCreate(sqlite *db){
Vdbe *p;
p = sqliteMalloc( sizeof(Vdbe) );
if( p==0 ) return 0;
p->db = db;
if( db->pVdbe ){
db->pVdbe->pPrev = p;
}
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
p->magic = VDBE_MAGIC_INIT;
return p;
}
| vdbeaux.c | 33 |
VOID | sqliteVdbeTrace(Vdbe *p, FILE *trace)
void sqliteVdbeTrace(Vdbe *p, FILE *trace){
p->trace = trace;
}
| vdbeaux.c | 51 |
INT | sqliteVdbeAddOp(Vdbe *p, int op, int p1, int p2)
int sqliteVdbeAddOp(Vdbe *p, int op, int p1, int p2){
int i;
VdbeOp *pOp;
i = p->nOp;
p->nOp++;
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nOpAlloc ){
int oldSize = p->nOpAlloc;
Op *aNew;
p->nOpAlloc = p->nOpAlloc*2 + 100;
aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
if( aNew==0 ){
p->nOpAlloc = oldSize;
return 0;
}
p->aOp = aNew;
memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
}
pOp = &p->aOp[i];
pOp->opcode = op;
pOp->p1 = p1;
if( p2<0 && (-1-p2)nLabel && p->aLabel[-1-p2]>=0 ){
p2 = p->aLabel[-1-p2];
}
pOp->p2 = p2;
pOp->p3 = 0;
pOp->p3type = P3_NOTUSED;
#ifndef NDEBUG
if( sqlite_vdbe_addop_trace ) sqliteVdbePrintOp(0, i, &p->aOp[i]);
#endif
return i;
}
| vdbeaux.c | 58 |
INT | sqliteVdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3, int p3type)
int sqliteVdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3, int p3type){
int addr = sqliteVdbeAddOp(p, op, p1, p2);
sqliteVdbeChangeP3(p, addr, zP3, p3type);
return addr;
}
| vdbeaux.c | 108 |
INT | sqliteVdbeCode(Vdbe *p, ...)
int sqliteVdbeCode(Vdbe *p, ...){
int addr;
va_list ap;
int opcode, p1, p2;
va_start(ap, p);
addr = p->nOp;
while( (opcode = va_arg(ap,int))!=0 ){
p1 = va_arg(ap,int);
p2 = va_arg(ap,int);
sqliteVdbeAddOp(p, opcode, p1, p2);
}
va_end(ap);
return addr;
}
| vdbeaux.c | 117 |
INT | sqliteVdbeMakeLabel(Vdbe *p)
int sqliteVdbeMakeLabel(Vdbe *p){
int i;
i = p->nLabel++;
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nLabelAlloc ){
int *aNew;
p->nLabelAlloc = p->nLabelAlloc*2 + 10;
aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
if( aNew==0 ){
sqliteFree(p->aLabel);
}
p->aLabel = aNew;
}
if( p->aLabel==0 ){
p->nLabel = 0;
p->nLabelAlloc = 0;
return 0;
}
p->aLabel[i] = -1;
return -1-i;
}
| vdbeaux.c | 137 |
VOID | sqliteVdbeResolveLabel(Vdbe *p, int x)
void sqliteVdbeResolveLabel(Vdbe *p, int x){
int j;
assert( p->magic==VDBE_MAGIC_INIT );
if( x<0 && (-x)<=p->nLabel && p->aOp ){
if( p->aLabel[-1-x]==p->nOp ) return;
assert( p->aLabel[-1-x]<0 );
p->aLabel[-1-x] = p->nOp;
for(j=0; jnOp; j++){
if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp;
}
}
}
| vdbeaux.c | 171 |
INT | sqliteVdbeCurrentAddr(Vdbe *p)
int sqliteVdbeCurrentAddr(Vdbe *p){
assert( p->magic==VDBE_MAGIC_INIT );
return p->nOp;
}
| vdbeaux.c | 189 |
INT | sqliteVdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
int sqliteVdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOp + nOp >= p->nOpAlloc ){
int oldSize = p->nOpAlloc;
Op *aNew;
p->nOpAlloc = p->nOpAlloc*2 + nOp + 10;
aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
if( aNew==0 ){
p->nOpAlloc = oldSize;
return 0;
}
p->aOp = aNew;
memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
}
addr = p->nOp;
if( nOp>0 ){
int i;
VdbeOpList const *pIn = aOp;
for(i=0; ip2;
VdbeOp *pOut = &p->aOp[i+addr];
pOut->opcode = pIn->opcode;
pOut->p1 = pIn->p1;
pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
pOut->p3 = pIn->p3;
pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
#ifndef NDEBUG
if( sqlite_vdbe_addop_trace ){
sqliteVdbePrintOp(0, i+addr, &p->aOp[i+addr]);
}
#endif
}
p->nOp += nOp;
}
return addr;
}
| vdbeaux.c | 197 |
VOID | sqliteVdbeChangeP1(Vdbe *p, int addr, int val)
void sqliteVdbeChangeP1(Vdbe *p, int addr, int val){
assert( p->magic==VDBE_MAGIC_INIT );
if( p && addr>=0 && p->nOp>addr && p->aOp ){
p->aOp[addr].p1 = val;
}
}
| vdbeaux.c | 239 |
VOID | sqliteVdbeChangeP2(Vdbe *p, int addr, int val)
void sqliteVdbeChangeP2(Vdbe *p, int addr, int val){
assert( val>=0 );
assert( p->magic==VDBE_MAGIC_INIT );
if( p && addr>=0 && p->nOp>addr && p->aOp ){
p->aOp[addr].p2 = val;
}
}
| vdbeaux.c | 252 |
VOID | sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n)
void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p==0 || p->aOp==0 ) return;
if( addr<0 || addr>=p->nOp ){
addr = p->nOp - 1;
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){
sqliteFree(pOp->p3);
pOp->p3 = 0;
}
if( zP3==0 ){
pOp->p3 = 0;
pOp->p3type = P3_NOTUSED;
}else if( n<0 ){
pOp->p3 = (char*)zP3;
pOp->p3type = n;
}else{
sqliteSetNString(&pOp->p3, zP3, n, 0);
pOp->p3type = P3_DYNAMIC;
}
}
| vdbeaux.c | 264 |
VOID | sqliteVdbeDequoteP3(Vdbe *p, int addr)
void sqliteVdbeDequoteP3(Vdbe *p, int addr){
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->aOp==0 ) return;
if( addr<0 || addr>=p->nOp ){
addr = p->nOp - 1;
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
if( pOp->p3==0 || pOp->p3[0]==0 ) return;
if( pOp->p3type==P3_POINTER ) return;
if( pOp->p3type!=P3_DYNAMIC ){
pOp->p3 = sqliteStrDup(pOp->p3);
pOp->p3type = P3_DYNAMIC;
}
sqliteDequote(pOp->p3);
}
| vdbeaux.c | 306 |
VOID | sqliteVdbeCompressSpace(Vdbe *p, int addr)
void sqliteVdbeCompressSpace(Vdbe *p, int addr){
unsigned char *z;
int i, j;
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->aOp==0 || addr<0 || addr>=p->nOp ) return;
pOp = &p->aOp[addr];
if( pOp->p3type==P3_POINTER ){
return;
}
if( pOp->p3type!=P3_DYNAMIC ){
pOp->p3 = sqliteStrDup(pOp->p3);
pOp->p3type = P3_DYNAMIC;
}
z = (unsigned char*)pOp->p3;
if( z==0 ) return;
i = j = 0;
while( isspace(z[i]) ){ i++; }
while( z[i] ){
if( isspace(z[i]) ){
z[j++] = ' ';
while( isspace(z[++i]) ){}
}else{
z[j++] = z[i++];
}
}
while( j>0 && isspace(z[j-1]) ){ j--; }
z[j] = 0;
}
| vdbeaux.c | 333 |
INT | sqliteVdbeFindOp(Vdbe *p, int op, int p2)
int sqliteVdbeFindOp(Vdbe *p, int op, int p2){
int i;
assert( p->magic==VDBE_MAGIC_INIT );
for(i=0; inOp; i++){
if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
}
return 0;
}
| vdbeaux.c | 368 |
VDBEOP | sqliteVdbeGetOp(Vdbe *p, int addr)
VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){
assert( p->magic==VDBE_MAGIC_INIT );
assert( addr>=0 && addrnOp );
return &p->aOp[addr];
}
| vdbeaux.c | 381 |
CHAR | sqlite_set_result_string(sqlite_func *p, const char *zResult, int n)
char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){
assert( !p->isStep );
if( p->s.flags & MEM_Dyn ){
sqliteFree(p->s.z);
}
if( zResult==0 ){
p->s.flags = MEM_Null;
n = 0;
p->s.z = 0;
p->s.n = 0;
}else{
if( n<0 ) n = strlen(zResult);
if( ns.zShort, zResult, n);
p->s.zShort[n] = 0;
p->s.flags = MEM_Str | MEM_Short;
p->s.z = p->s.zShort;
}else{
p->s.z = sqliteMallocRaw( n+1 );
if( p->s.z ){
memcpy(p->s.z, zResult, n);
p->s.z[n] = 0;
}
p->s.flags = MEM_Str | MEM_Dyn;
}
p->s.n = n+1;
}
return p->s.z;
}
| vdbeaux.c | 390 |
VOID | sqlite_set_result_int(sqlite_func *p, int iResult)
void sqlite_set_result_int(sqlite_func *p, int iResult){
assert( !p->isStep );
if( p->s.flags & MEM_Dyn ){
sqliteFree(p->s.z);
}
p->s.i = iResult;
p->s.flags = MEM_Int;
}
| vdbeaux.c | 440 |
VOID | sqlite_set_result_double(sqlite_func *p, double rResult)
void sqlite_set_result_double(sqlite_func *p, double rResult){
assert( !p->isStep );
if( p->s.flags & MEM_Dyn ){
sqliteFree(p->s.z);
}
p->s.r = rResult;
p->s.flags = MEM_Real;
}
| vdbeaux.c | 448 |
VOID | sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n)
void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){
assert( !p->isStep );
sqlite_set_result_string(p, zMsg, n);
p->isError = 1;
}
| vdbeaux.c | 456 |
VOID | sqlite_user_data(sqlite_func *p)
void *sqlite_user_data(sqlite_func *p){
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
| vdbeaux.c | 462 |
VOID | sqlite_aggregate_context(sqlite_func *p, int nByte)
void *sqlite_aggregate_context(sqlite_func *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep );
if( p->pAgg==0 ){
if( nByte<=NBFS ){
p->pAgg = (void*)p->s.z;
memset(p->pAgg, 0, nByte);
}else{
p->pAgg = sqliteMalloc( nByte );
}
}
return p->pAgg;
}
| vdbeaux.c | 471 |
INT | sqlite_aggregate_count(sqlite_func *p)
int sqlite_aggregate_count(sqlite_func *p){
assert( p && p->pFunc && p->pFunc->xStep );
return p->cnt;
}
| vdbeaux.c | 493 |
VOID | sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp)
void sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp){
char *zP3;
char zPtr[40];
if( pOp->p3type==P3_POINTER ){
sprintf(zPtr, "ptr(%#lx)", (long)pOp->p3);
zP3 = zPtr;
}else{
zP3 = pOp->p3;
}
if( pOut==0 ) pOut = stdout;
fprintf(pOut,"%4d %-12s %4d %4d %s\n",
pc, sqliteOpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");
fflush(pOut);
}
| vdbeaux.c | 507 |
INT | sqliteVdbeList( Vdbe *p )
int sqliteVdbeList(
Vdbe *p /* The VDBE */
){
sqlite *db = p->db;
int i;
int rc = SQLITE_OK;
static char *azColumnNames[] = {
"addr", "opcode", "p1", "p2", "p3",
"int", "text", "int", "int", "text",
0
};
assert( p->popStack==0 );
assert( p->explain );
p->azColName = azColumnNames;
p->azResColumn = p->zArgv;
for(i=0; i<5; i++) p->zArgv[i] = p->aStack[i].zShort;
i = p->pc;
if( i>=p->nOp ){
p->rc = SQLITE_OK;
rc = SQLITE_DONE;
}else if( db->flags & SQLITE_Interrupt ){
db->flags &= ~SQLITE_Interrupt;
if( db->magic!=SQLITE_MAGIC_BUSY ){
p->rc = SQLITE_MISUSE;
}else{
p->rc = SQLITE_INTERRUPT;
}
rc = SQLITE_ERROR;
sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
}else{
sprintf(p->zArgv[0],"%d",i);
sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
if( p->aOp[i].p3type==P3_POINTER ){
sprintf(p->aStack[4].zShort, "ptr(%#lx)", (long)p->aOp[i].p3);
p->zArgv[4] = p->aStack[4].zShort;
}else{
p->zArgv[4] = p->aOp[i].p3;
}
p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
p->pc = i+1;
p->azResColumn = p->zArgv;
p->nResColumn = 5;
p->rc = SQLITE_OK;
rc = SQLITE_ROW;
}
return rc;
}
| vdbeaux.c | 526 |
VOID | sqliteVdbeMakeReady( Vdbe *p, int nVar, int isExplain )
void sqliteVdbeMakeReady(
Vdbe *p, /* The VDBE */
int nVar, /* Number of '?' see in the SQL statement */
int isExplain /* True if the EXPLAIN keywords is present */
){
int n;
assert( p!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
/* Add a HALT instruction to the very end of the program.
*/
if( p->nOp==0 || (p->aOp && p->aOp[p->nOp-1].opcode!=OP_Halt) ){
sqliteVdbeAddOp(p, OP_Halt, 0, 0);
}
/* No instruction ever pushes more than a single element onto the
** stack. And the stack never grows on successive executions of the
** same loop. So the total number of instructions is an upper bound
** on the maximum stack depth required.
**
** Allocation all the stack space we will ever need.
*/
if( p->aStack==0 ){
p->nVar = nVar;
assert( nVar>=0 );
n = isExplain ? 10 : p->nOp;
p->aStack = sqliteMalloc(
n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */
+ p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */
);
p->zArgv = (char**)&p->aStack[n];
p->azColName = (char**)&p->zArgv[n];
p->azVar = (char**)&p->azColName[n];
p->anVar = (int*)&p->azVar[p->nVar];
p->abVar = (u8*)&p->anVar[p->nVar];
}
sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0);
p->agg.pSearch = 0;
#ifdef MEMORY_DEBUG
if( sqliteOsFileExists("vdbe_trace") ){
p->trace = stdout;
}
#endif
p->pTos = &p->aStack[-1];
p->pc = 0;
p->rc = SQLITE_OK;
p->uniqueCnt = 0;
p->returnDepth = 0;
p->errorAction = OE_Abort;
p->undoTransOnError = 0;
p->popStack = 0;
p->explain |= isExplain;
p->magic = VDBE_MAGIC_RUN;
#ifdef VDBE_PROFILE
{
int i;
for(i=0; inOp; i++){
p->aOp[i].cnt = 0;
p->aOp[i].cycles = 0;
}
}
#endif
}
| vdbeaux.c | 583 |
VOID | sqliteVdbeSorterReset(Vdbe *p)
void sqliteVdbeSorterReset(Vdbe *p){
while( p->pSort ){
Sorter *pSorter = p->pSort;
p->pSort = pSorter->pNext;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter->pData);
sqliteFree(pSorter);
}
}
| vdbeaux.c | 656 |
VOID | sqliteVdbeAggReset(Agg *pAgg)
void sqliteVdbeAggReset(Agg *pAgg){
int i;
HashElem *p;
for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){
AggElem *pElem = sqliteHashData(p);
assert( pAgg->apFunc!=0 );
for(i=0; inMem; i++){
Mem *pMem = &pElem->aMem[i];
if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
sqlite_func ctx;
ctx.pFunc = pAgg->apFunc[i];
ctx.s.flags = MEM_Null;
ctx.pAgg = pMem->z;
ctx.cnt = pMem->i;
ctx.isStep = 0;
ctx.isError = 0;
(*pAgg->apFunc[i]->xFinalize)(&ctx);
if( pMem->z!=0 && pMem->z!=pMem->zShort ){
sqliteFree(pMem->z);
}
if( ctx.s.flags & MEM_Dyn ){
sqliteFree(ctx.s.z);
}
}else if( pMem->flags & MEM_Dyn ){
sqliteFree(pMem->z);
}
}
sqliteFree(pElem);
}
sqliteHashClear(&pAgg->hash);
sqliteFree(pAgg->apFunc);
pAgg->apFunc = 0;
pAgg->pCurrent = 0;
pAgg->pSearch = 0;
pAgg->nMem = 0;
}
| vdbeaux.c | 669 |
VOID | sqliteVdbeKeylistFree(Keylist *p)
void sqliteVdbeKeylistFree(Keylist *p){
while( p ){
Keylist *pNext = p->pNext;
sqliteFree(p);
p = pNext;
}
}
| vdbeaux.c | 715 |
VOID | sqliteVdbeCleanupCursor(Cursor *pCx)
void sqliteVdbeCleanupCursor(Cursor *pCx){
if( pCx->pCursor ){
sqliteBtreeCloseCursor(pCx->pCursor);
}
if( pCx->pBt ){
sqliteBtreeClose(pCx->pBt);
}
sqliteFree(pCx->pData);
memset(pCx, 0, sizeof(Cursor));
}
| vdbeaux.c | 726 |
STATIC VOID | closeAllCursors(Vdbe *p)
static void closeAllCursors(Vdbe *p){
int i;
for(i=0; inCursor; i++){
sqliteVdbeCleanupCursor(&p->aCsr[i]);
}
sqliteFree(p->aCsr);
p->aCsr = 0;
p->nCursor = 0;
}
| vdbeaux.c | 741 |
STATIC VOID | Cleanup(Vdbe *p)
static void Cleanup(Vdbe *p){
int i;
if( p->aStack ){
Mem *pTos = p->pTos;
while( pTos>=p->aStack ){
if( pTos->flags & MEM_Dyn ){
sqliteFree(pTos->z);
}
pTos--;
}
p->pTos = pTos;
}
closeAllCursors(p);
if( p->aMem ){
for(i=0; inMem; i++){
if( p->aMem[i].flags & MEM_Dyn ){
sqliteFree(p->aMem[i].z);
}
}
}
sqliteFree(p->aMem);
p->aMem = 0;
p->nMem = 0;
if( p->pList ){
sqliteVdbeKeylistFree(p->pList);
p->pList = 0;
}
sqliteVdbeSorterReset(p);
if( p->pFile ){
if( p->pFile!=stdin ) fclose(p->pFile);
p->pFile = 0;
}
if( p->azField ){
sqliteFree(p->azField);
p->azField = 0;
}
p->nField = 0;
if( p->zLine ){
sqliteFree(p->zLine);
p->zLine = 0;
}
p->nLineAlloc = 0;
sqliteVdbeAggReset(&p->agg);
if( p->aSet ){
for(i=0; inSet; i++){
sqliteHashClear(&p->aSet[i].hash);
}
}
sqliteFree(p->aSet);
p->aSet = 0;
p->nSet = 0;
if( p->keylistStack ){
int ii;
for(ii = 0; ii < p->keylistStackDepth; ii++){
sqliteVdbeKeylistFree(p->keylistStack[ii]);
}
sqliteFree(p->keylistStack);
p->keylistStackDepth = 0;
p->keylistStack = 0;
}
sqliteFree(p->contextStack);
p->contextStack = 0;
sqliteFree(p->zErrMsg);
p->zErrMsg = 0;
}
| vdbeaux.c | 754 |
INT | sqliteVdbeReset(Vdbe *p, char **pzErrMsg)
int sqliteVdbeReset(Vdbe *p, char **pzErrMsg){
sqlite *db = p->db;
int i;
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
return SQLITE_MISUSE;
}
if( p->zErrMsg ){
if( pzErrMsg && *pzErrMsg==0 ){
*pzErrMsg = p->zErrMsg;
}else{
sqliteFree(p->zErrMsg);
}
p->zErrMsg = 0;
}else if( p->rc ){
sqliteSetString(pzErrMsg, sqlite_error_string(p->rc), (char*)0);
}
Cleanup(p);
if( p->rc!=SQLITE_OK ){
switch( p->errorAction ){
case OE_Abort: {
if( !p->undoTransOnError ){
for(i=0; inDb; i++){
if( db->aDb[i].pBt ){
sqliteBtreeRollbackCkpt(db->aDb[i].pBt);
}
}
break;
}
/* Fall through to ROLLBACK */
}
case OE_Rollback: {
sqliteRollbackAll(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
break;
}
default: {
if( p->undoTransOnError ){
sqliteRollbackAll(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
break;
}
}
sqliteRollbackInternalChanges(db);
}
for(i=0; inDb; i++){
if( db->aDb[i].pBt && db->aDb[i].inTrans==2 ){
sqliteBtreeCommitCkpt(db->aDb[i].pBt);
db->aDb[i].inTrans = 1;
}
}
assert( p->pTos<&p->aStack[p->pc] || sqlite_malloc_failed==1 );
#ifdef VDBE_PROFILE
{
FILE *out = fopen("vdbe_profile.out", "a");
if( out ){
int i;
fprintf(out, "---- ");
for(i=0; inOp; i++){
fprintf(out, "%02x", p->aOp[i].opcode);
}
fprintf(out, "\n");
for(i=0; inOp; i++){
fprintf(out, "%6d %10lld %8lld ",
p->aOp[i].cnt,
p->aOp[i].cycles,
p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
);
sqliteVdbePrintOp(out, i, &p->aOp[i]);
}
fclose(out);
}
}
#endif
p->magic = VDBE_MAGIC_INIT;
return p->rc;
}
| vdbeaux.c | 827 |
INT | sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg)
int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
int rc;
sqlite *db;
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
return SQLITE_MISUSE;
}
db = p->db;
rc = sqliteVdbeReset(p, pzErrMsg);
sqliteVdbeDelete(p);
if( db->want_to_close && db->pVdbe==0 ){
sqlite_close(db);
}
if( rc==SQLITE_SCHEMA ){
sqliteResetInternalSchema(db, 0);
}
return rc;
}
| vdbeaux.c | 916 |
INT | sqlite_bind(sqlite_vm *pVm, int i, const char *zVal, int len, int copy)
int sqlite_bind(sqlite_vm *pVm, int i, const char *zVal, int len, int copy){
Vdbe *p = (Vdbe*)pVm;
if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){
return SQLITE_MISUSE;
}
if( i<1 || i>p->nVar ){
return SQLITE_RANGE;
}
i--;
if( p->abVar[i] ){
sqliteFree(p->azVar[i]);
}
if( zVal==0 ){
copy = 0;
len = 0;
}
if( len<0 ){
len = strlen(zVal)+1;
}
if( copy ){
p->azVar[i] = sqliteMalloc( len );
if( p->azVar[i] ) memcpy(p->azVar[i], zVal, len);
}else{
p->azVar[i] = (char*)zVal;
}
p->abVar[i] = copy;
p->anVar[i] = len;
return SQLITE_OK;
}
| vdbeaux.c | 940 |
VOID | sqliteVdbeDelete(Vdbe *p)
void sqliteVdbeDelete(Vdbe *p){
int i;
if( p==0 ) return;
Cleanup(p);
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
assert( p->db->pVdbe==p );
p->db->pVdbe = p->pNext;
}
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
p->pPrev = p->pNext = 0;
if( p->nOpAlloc==0 ){
p->aOp = 0;
p->nOp = 0;
}
for(i=0; inOp; i++){
if( p->aOp[i].p3type==P3_DYNAMIC ){
sqliteFree(p->aOp[i].p3);
}
}
for(i=0; inVar; i++){
if( p->abVar[i] ) sqliteFree(p->azVar[i]);
}
sqliteFree(p->aOp);
sqliteFree(p->aLabel);
sqliteFree(p->aStack);
p->magic = VDBE_MAGIC_DEAD;
sqliteFree(p);
}
| vdbeaux.c | 979 |
INT | sqliteVdbeByteSwap(int x)
int sqliteVdbeByteSwap(int x){
union {
char zBuf[sizeof(int)];
int i;
} ux;
ux.zBuf[3] = x&0xff;
ux.zBuf[2] = (x>>8)&0xff;
ux.zBuf[1] = (x>>16)&0xff;
ux.zBuf[0] = (x>>24)&0xff;
return ux.i;
}
| vdbeaux.c | 1015 |
INT | sqliteVdbeCursorMoveto(Cursor *p)
int sqliteVdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
int res;
extern int sqlite_search_count;
sqliteBtreeMoveto(p->pCursor, (char*)&p->movetoTarget, sizeof(int), &res);
p->lastRecno = keyToInt(p->movetoTarget);
p->recnoIsValid = res==0;
if( res<0 ){
sqliteBtreeNext(p->pCursor, &res);
}
sqlite_search_count++;
p->deferredMoveto = 0;
}
return SQLITE_OK;
}
| vdbeaux.c | 1042 |
where.c |
Type | Function | Source | Line |
STATIC INT | exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr)
static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
int cnt = 0;
if( pExpr==0 || nSlot<1 ) return 0;
if( nSlot==1 || pExpr->op!=TK_AND ){
aSlot[0].p = pExpr;
return 1;
}
if( pExpr->pLeft->op!=TK_AND ){
aSlot[0].p = pExpr->pLeft;
cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight);
}else{
cnt = exprSplit(nSlot, aSlot, pExpr->pLeft);
cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight);
}
return cnt;
}
| where.c | 57 |
STATIC INT | getMask(ExprMaskSet *pMaskSet, int iCursor)
static int getMask(ExprMaskSet *pMaskSet, int iCursor){
int i;
for(i=0; in; i++){
if( pMaskSet->ix[i]==iCursor ) return 1<n && iix) ){
pMaskSet->n++;
pMaskSet->ix[i] = iCursor;
return 1<where.c | 88 | |
STATIC INT | exprTableUsage(ExprMaskSet *pMaskSet, Expr *p)
static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
unsigned int mask = 0;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
mask = getMask(pMaskSet, p->iTable);
if( mask==0 ) mask = -1;
return mask;
}
if( p->pRight ){
mask = exprTableUsage(pMaskSet, p->pRight);
}
if( p->pLeft ){
mask |= exprTableUsage(pMaskSet, p->pLeft);
}
if( p->pList ){
int i;
for(i=0; ipList->nExpr; i++){
mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr);
}
}
return mask;
}
| where.c | 110 |
STATIC INT | allowedOp(int op)
static int allowedOp(int op){
switch( op ){
case TK_LT:
case TK_LE:
case TK_GT:
case TK_GE:
case TK_EQ:
case TK_IN:
return 1;
default:
return 0;
}
}
| where.c | 145 |
STATIC VOID | exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo)
static void exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo){
Expr *pExpr = pInfo->p;
pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr);
pInfo->indexable = 0;
pInfo->idxLeft = -1;
pInfo->idxRight = -1;
if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){
if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){
pInfo->idxRight = pExpr->pRight->iTable;
pInfo->indexable = 1;
}
if( pExpr->pLeft->op==TK_COLUMN ){
pInfo->idxLeft = pExpr->pLeft->iTable;
pInfo->indexable = 1;
}
}
}
| where.c | 164 |
STATIC INDEX | findSortingIndex( Table *pTab, int base, ExprList *pOrderBy, Index *pPreferredIdx, int nEqCol, int *pbRev )
static Index *findSortingIndex(
Table *pTab, /* The table to be sorted */
int base, /* Cursor number for pTab */
ExprList *pOrderBy, /* The ORDER BY clause */
Index *pPreferredIdx, /* Use this index, if possible and not NULL */
int nEqCol, /* Number of index columns used with == constraints */
int *pbRev /* Set to 1 if ORDER BY is DESC */
){
int i, j;
Index *pMatch;
Index *pIdx;
int sortOrder;
assert( pOrderBy!=0 );
assert( pOrderBy->nExpr>0 );
sortOrder = pOrderBy->a[0].sortOrder & SQLITE_SO_DIRMASK;
for(i=0; inExpr; i++){
Expr *p;
if( (pOrderBy->a[i].sortOrder & SQLITE_SO_DIRMASK)!=sortOrder ){
/* Indices can only be used if all ORDER BY terms are either
** DESC or ASC. Indices cannot be used on a mixture. */
return 0;
}
if( (pOrderBy->a[i].sortOrder & SQLITE_SO_TYPEMASK)!=SQLITE_SO_UNK ){
/* Do not sort by index if there is a COLLATE clause */
return 0;
}
p = pOrderBy->a[i].pExpr;
if( p->op!=TK_COLUMN || p->iTable!=base ){
/* Can not use an index sort on anything that is not a column in the
** left-most table of the FROM clause */
return 0;
}
}
/* If we get this far, it means the ORDER BY clause consists only of
** ascending columns in the left-most table of the FROM clause. Now
** check for a matching index.
*/
pMatch = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int nExpr = pOrderBy->nExpr;
if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
for(i=j=0; iaiColumn[i]!=pIdx->aiColumn[i] ) break;
if( ja[j].pExpr->iColumn==pIdx->aiColumn[i] ){ j++; }
}
if( ia[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] ) break;
}
if( i+j>=nExpr ){
pMatch = pIdx;
if( pIdx==pPreferredIdx ) break;
}
}
if( pMatch && pbRev ){
*pbRev = sortOrder==SQLITE_SO_DESC;
}
return pMatch;
}
| where.c | 190 |
STATIC VOID | disableTerm(WhereLevel *pLevel, Expr **ppExpr)
static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
Expr *pExpr = *ppExpr;
if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
*ppExpr = 0;
}
}
| where.c | 274 |
WHEREINFO | sqliteWhereBegin( Parse *pParse, SrcList *pTabList, Expr *pWhere, int pushKey, ExprList **ppOrderBy )
WhereInfo *sqliteWhereBegin(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
int pushKey, /* If TRUE, leave the table key on the stack */
ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
){
int i; /* Loop counter */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
int brk, cont = 0; /* Addresses used during code generation */
int nExpr; /* Number of subexpressions in the WHERE clause */
int loopMask; /* One bit set for each outer loop */
int haveKey; /* True if KEY is on the stack */
ExprMaskSet maskSet; /* The expression mask set */
int iDirectEq[32]; /* Term of the form ROWID==X for the N-th table */
int iDirectLt[32]; /* Term of the form ROWIDX or ROWID>=X */
ExprInfo aExpr[101]; /* The WHERE clause is divided into these expressions */
/* pushKey is only allowed if there is a single table (as in an INSERT or
** UPDATE statement)
*/
assert( pushKey==0 || pTabList->nSrc==1 );
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator. If the aExpr[]
** array fills up, the last entry might point to an expression which
** contains additional unfactored AND operators.
*/
initMaskSet(&maskSet);
memset(aExpr, 0, sizeof(aExpr));
nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
if( nExpr==ARRAYSIZE(aExpr) ){
sqliteErrorMsg(pParse, "WHERE clause too complex - no more "
"than %d terms allowed", (int)ARRAYSIZE(aExpr)-1);
return 0;
}
/* Allocate and initialize the WhereInfo structure that will become the
** return value.
*/
pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( sqlite_malloc_failed ){
sqliteFree(pWInfo);
return 0;
}
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab;
pWInfo->iBreak = sqliteVdbeMakeLabel(v);
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
*/
if( pWhere && (pTabList->nSrc==0 || sqliteExprIsConstant(pWhere)) ){
sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
pWhere = 0;
}
/* Analyze all of the subexpressions.
*/
for(i=0; itrigStack ){
int x;
if( (x = pParse->trigStack->newIdx) >= 0 ){
int mask = ~getMask(&maskSet, x);
aExpr[i].prereqRight &= mask;
aExpr[i].prereqLeft &= mask;
aExpr[i].prereqAll &= mask;
}
if( (x = pParse->trigStack->oldIdx) >= 0 ){
int mask = ~getMask(&maskSet, x);
aExpr[i].prereqRight &= mask;
aExpr[i].prereqLeft &= mask;
aExpr[i].prereqAll &= mask;
}
}
}
/* Figure out what index to use (if any) for each nested loop.
** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested
** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner
** loop.
**
** If terms exist that use the ROWID of any table, then set the
** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table
** to the index of the term containing the ROWID. We always prefer
** to use a ROWID which can directly access a table rather than an
** index which requires reading an index first to get the rowid then
** doing a second read of the actual database table.
**
** Actually, if there are more than 32 tables in the join, only the
** first 32 tables are candidates for indices. This is (again) due
** to the limit of 32 bits in an integer bitmask.
*/
loopMask = 0;
for(i=0; inSrc && ia[i].iCursor; /* The cursor for this table */
int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
Table *pTab = pTabList->a[i].pTab;
Index *pIdx;
Index *pBestIdx = 0;
int bestScore = 0;
/* Check to see if there is an expression that uses only the
** ROWID field of this table. For terms of the form ROWID==expr
** set iDirectEq[i] to the index of the term. For terms of the
** form ROWIDexpr or ROWID>=expr set iDirectGt[i].
**
** (Added:) Treat ROWID IN expr like ROWID=expr.
*/
pWInfo->a[i].iCur = -1;
iDirectEq[i] = -1;
iDirectLt[i] = -1;
iDirectGt[i] = -1;
for(j=0; jpLeft->iColumn<0
&& (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
switch( aExpr[j].p->op ){
case TK_IN:
case TK_EQ: iDirectEq[i] = j; break;
case TK_LE:
case TK_LT: iDirectLt[i] = j; break;
case TK_GE:
case TK_GT: iDirectGt[i] = j; break;
}
}
if( aExpr[j].idxRight==iCur && aExpr[j].p->pRight->iColumn<0
&& (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
switch( aExpr[j].p->op ){
case TK_EQ: iDirectEq[i] = j; break;
case TK_LE:
case TK_LT: iDirectGt[i] = j; break;
case TK_GE:
case TK_GT: iDirectLt[i] = j; break;
}
}
}
if( iDirectEq[i]>=0 ){
loopMask |= mask;
pWInfo->a[i].pIdx = 0;
continue;
}
/* Do a search for usable indices. Leave pBestIdx pointing to
** the "best" index. pBestIdx is left set to NULL if no indices
** are usable.
**
** The best index is determined as follows. For each of the
** left-most terms that is fixed by an equality operator, add
** 8 to the score. The right-most term of the index may be
** constrained by an inequality. Add 1 if for an "x<..." constraint
** and add 2 for an "x>..." constraint. Chose the index that
** gives the best score.
**
** This scoring system is designed so that the score can later be
** used to determine how the index is used. If the score&7 is 0
** then all constraints are equalities. If score&1 is not 0 then
** there is an inequality used as a termination key. (ex: "x<...")
** If score&2 is not 0 then there is an inequality used as the
** start key. (ex: "x>..."). A score or 4 is the special case
** of an IN operator constraint. (ex: "x IN ...").
**
** The IN operator (as in " IN (...)") is treated the same as
** an equality comparison except that it can only be used on the
** left-most column of an index and other terms of the WHERE clause
** cannot be used in conjunction with the IN operator to help satisfy
** other columns of the index.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int eqMask = 0; /* Index columns covered by an x=... term */
int ltMask = 0; /* Index columns covered by an x<... term */
int gtMask = 0; /* Index columns covered by an x>... term */
int inMask = 0; /* Index columns covered by an x IN .. term */
int nEq, m, score;
if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */
for(j=0; jpLeft->iColumn;
int k;
for(k=0; knColumn; k++){
if( pIdx->aiColumn[k]==iColumn ){
switch( aExpr[j].p->op ){
case TK_IN: {
if( k==0 ) inMask |= 1;
break;
}
case TK_EQ: {
eqMask |= 1<pRight->iColumn;
int k;
for(k=0; knColumn; k++){
if( pIdx->aiColumn[k]==iColumn ){
switch( aExpr[j].p->op ){
case TK_EQ: {
eqMask |= 1<nColumn; nEq++){
m = (1<<(nEq+1))-1;
if( (m & eqMask)!=m ) break;
}
score = nEq*8; /* Base score is 8 times number of == constraints */
m = 1< constraint */
if( score==0 && inMask ) score = 4; /* Default score for IN constraint */
if( score>bestScore ){
pBestIdx = pIdx;
bestScore = score;
}
}
pWInfo->a[i].pIdx = pBestIdx;
pWInfo->a[i].score = bestScore;
pWInfo->a[i].bRev = 0;
loopMask |= mask;
if( pBestIdx ){
pWInfo->a[i].iCur = pParse->nTab++;
pWInfo->peakNTab = pParse->nTab;
}
}
/* Check to see if the ORDER BY clause is or can be satisfied by the
** use of an index on the first table.
*/
if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
Index *pSortIdx;
Index *pIdx;
Table *pTab;
int bRev = 0;
pTab = pTabList->a[0].pTab;
pIdx = pWInfo->a[0].pIdx;
if( pIdx && pWInfo->a[0].score==4 ){
/* If there is already an IN index on the left-most table,
** it will not give the correct sort order.
** So, pretend that no suitable index is found.
*/
pSortIdx = 0;
}else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
/* If the left-most column is accessed using its ROWID, then do
** not try to sort by index.
*/
pSortIdx = 0;
}else{
int nEqCol = (pWInfo->a[0].score+4)/8;
pSortIdx = findSortingIndex(pTab, pTabList->a[0].iCursor,
*ppOrderBy, pIdx, nEqCol, &bRev);
}
if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
if( pIdx==0 ){
pWInfo->a[0].pIdx = pSortIdx;
pWInfo->a[0].iCur = pParse->nTab++;
pWInfo->peakNTab = pParse->nTab;
}
pWInfo->a[0].bRev = bRev;
*ppOrderBy = 0;
}
}
/* Open all tables in the pTabList and all indices used by those tables.
*/
for(i=0; inSrc; i++){
Table *pTab;
Index *pIx;
pTab = pTabList->a[i].pTab;
if( pTab->isTransient || pTab->pSelect ) continue;
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, pTabList->a[i].iCursor, pTab->tnum,
pTab->zName, P3_STATIC);
sqliteCodeVerifySchema(pParse, pTab->iDb);
if( (pIx = pWInfo->a[i].pIdx)!=0 ){
sqliteVdbeAddOp(v, OP_Integer, pIx->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, pWInfo->a[i].iCur, pIx->tnum, pIx->zName,0);
}
}
/* Generate the code to do the search
*/
loopMask = 0;
for(i=0; inSrc; i++){
int j, k;
int iCur = pTabList->a[i].iCursor;
Index *pIdx;
WhereLevel *pLevel = &pWInfo->a[i];
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
*/
if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
if( !pParse->nMem ) pParse->nMem++;
pLevel->iLeftJoin = pParse->nMem++;
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
}
pIdx = pLevel->pIdx;
pLevel->inOp = OP_Noop;
if( i=0 ){
/* Case 1: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
** we reference multiple rows using a "rowid IN (...)"
** construct.
*/
k = iDirectEq[i];
assert( kbrk = sqliteVdbeMakeLabel(v);
if( aExpr[k].idxLeft==iCur ){
Expr *pX = aExpr[k].p;
if( pX->op!=TK_IN ){
sqliteExprCode(pParse, aExpr[k].p->pRight);
}else if( pX->pList ){
sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
pLevel->inOp = OP_SetNext;
pLevel->inP1 = pX->iTable;
pLevel->inP2 = sqliteVdbeCurrentAddr(v);
}else{
assert( pX->pSelect );
sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
pLevel->inOp = OP_Next;
pLevel->inP1 = pX->iTable;
}
}else{
sqliteExprCode(pParse, aExpr[k].p->pLeft);
}
disableTerm(pLevel, &aExpr[k].p);
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
haveKey = 0;
sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
pLevel->op = OP_Noop;
}else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
/* Case 2: There is an index and all terms of the WHERE clause that
** refer to the index use the "==" or "IN" operators.
*/
int start;
int testOp;
int nColumn = (pLevel->score+4)/8;
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
for(j=0; jpLeft->iColumn==pIdx->aiColumn[j]
){
if( pX->op==TK_EQ ){
sqliteExprCode(pParse, pX->pRight);
disableTerm(pLevel, &aExpr[k].p);
break;
}
if( pX->op==TK_IN && nColumn==1 ){
if( pX->pList ){
sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
pLevel->inOp = OP_SetNext;
pLevel->inP1 = pX->iTable;
pLevel->inP2 = sqliteVdbeCurrentAddr(v);
}else{
assert( pX->pSelect );
sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
pLevel->inOp = OP_Next;
pLevel->inP1 = pX->iTable;
}
disableTerm(pLevel, &aExpr[k].p);
break;
}
}
if( aExpr[k].idxRight==iCur
&& aExpr[k].p->op==TK_EQ
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pLeft);
disableTerm(pLevel, &aExpr[k].p);
break;
}
}
}
pLevel->iMem = pParse->nMem++;
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, brk);
sqliteVdbeAddOp(v, OP_MakeKey, nColumn, 0);
sqliteAddIdxKeyType(v, pIdx);
if( nColumn==pIdx->nColumn || pLevel->bRev ){
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
testOp = OP_IdxGT;
}else{
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
testOp = OP_IdxGE;
}
if( pLevel->bRev ){
/* Scan in reverse order */
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqliteVdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
pLevel->op = OP_Prev;
}else{
/* Scan in the forward order */
sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
pLevel->op = OP_Next;
}
sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
sqliteVdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
if( i==pTabList->nSrc-1 && pushKey ){
haveKey = 1;
}else{
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
haveKey = 0;
}
pLevel->p1 = pLevel->iCur;
pLevel->p2 = start;
}else if( i=0 || iDirectGt[i]>=0) ){
/* Case 3: We have an inequality comparison against the ROWID field.
*/
int testOp = OP_Noop;
int start;
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
if( iDirectGt[i]>=0 ){
k = iDirectGt[i];
assert( kpRight);
}else{
sqliteExprCode(pParse, aExpr[k].p->pLeft);
}
sqliteVdbeAddOp(v, OP_ForceInt,
aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
disableTerm(pLevel, &aExpr[k].p);
}else{
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
}
if( iDirectLt[i]>=0 ){
k = iDirectLt[i];
assert( kpRight);
}else{
sqliteExprCode(pParse, aExpr[k].p->pLeft);
}
/* sqliteVdbeAddOp(v, OP_MustBeInt, 0, sqliteVdbeCurrentAddr(v)+1); */
pLevel->iMem = pParse->nMem++;
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
testOp = OP_Ge;
}else{
testOp = OP_Gt;
}
disableTerm(pLevel, &aExpr[k].p);
}
start = sqliteVdbeCurrentAddr(v);
pLevel->op = OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
if( testOp!=OP_Noop ){
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqliteVdbeAddOp(v, testOp, 0, brk);
}
haveKey = 0;
}else if( pIdx==0 ){
/* Case 4: There is no usable index. We must do a complete
** scan of the entire database table.
*/
int start;
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
cont = pLevel->cont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
start = sqliteVdbeCurrentAddr(v);
pLevel->op = OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
haveKey = 0;
}else{
/* Case 5: The WHERE clause term that refers to the right-most
** column of the index is an inequality. For example, if
** the index is on (x,y,z) and the WHERE clause is of the
** form "x=5 AND y<10" then this case is used. Only the
** right-most column can be an inequality - the rest must
** use the "==" operator.
**
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
*/
int score = pLevel->score;
int nEqColumn = score/8;
int start;
int leFlag, geFlag;
int testOp;
/* Evaluate the equality constraints
*/
for(j=0; jop==TK_EQ
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pRight);
disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
&& aExpr[k].p->op==TK_EQ
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, aExpr[k].p->pLeft);
disableTerm(pLevel, &aExpr[k].p);
break;
}
}
}
/* Duplicate the equality term values because they will all be
** used twice: once to make the termination key and once to make the
** start key.
*/
for(j=0; jcont = sqliteVdbeMakeLabel(v);
brk = pLevel->brk = sqliteVdbeMakeLabel(v);
/* Generate the termination key. This is the key value that
** will end the search. There is no termination key if there
** are no equality terms and no "X<..." term.
**
** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
** key computed here really ends up being the start key.
*/
if( (score & 1)!=0 ){
for(k=0; kop==TK_LT || pExpr->op==TK_LE)
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
&& pExpr->pLeft->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, pExpr->pRight);
leFlag = pExpr->op==TK_LE;
disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
&& (pExpr->op==TK_GT || pExpr->op==TK_GE)
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
&& pExpr->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, pExpr->pLeft);
leFlag = pExpr->op==TK_GE;
disableTerm(pLevel, &aExpr[k].p);
break;
}
}
testOp = OP_IdxGE;
}else{
testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
leFlag = 1;
}
if( testOp!=OP_Noop ){
int nCol = nEqColumn + (score & 1);
pLevel->iMem = pParse->nMem++;
sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, brk);
sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
sqliteAddIdxKeyType(v, pIdx);
if( leFlag ){
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
}
if( pLevel->bRev ){
sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
}else{
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
}
}else if( pLevel->bRev ){
sqliteVdbeAddOp(v, OP_Last, pLevel->iCur, brk);
}
/* Generate the start key. This is the key that defines the lower
** bound on the search. There is no start key if there are no
** equality terms and if there is no "X>..." term. In
** that case, generate a "Rewind" instruction in place of the
** start key search.
**
** 2002-Dec-04: In the case of a reverse-order search, the so-called
** "start" key really ends up being used as the termination key.
*/
if( (score & 2)!=0 ){
for(k=0; kop==TK_GT || pExpr->op==TK_GE)
&& (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
&& pExpr->pLeft->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, pExpr->pRight);
geFlag = pExpr->op==TK_GE;
disableTerm(pLevel, &aExpr[k].p);
break;
}
if( aExpr[k].idxRight==iCur
&& (pExpr->op==TK_LT || pExpr->op==TK_LE)
&& (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
&& pExpr->pRight->iColumn==pIdx->aiColumn[j]
){
sqliteExprCode(pParse, pExpr->pLeft);
geFlag = pExpr->op==TK_LE;
disableTerm(pLevel, &aExpr[k].p);
break;
}
}
}else{
geFlag = 1;
}
if( nEqColumn>0 || (score&2)!=0 ){
int nCol = nEqColumn + ((score&2)!=0);
sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, brk);
sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
sqliteAddIdxKeyType(v, pIdx);
if( !geFlag ){
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
}
if( pLevel->bRev ){
pLevel->iMem = pParse->nMem++;
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
testOp = OP_IdxLT;
}else{
sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
}
}else if( pLevel->bRev ){
testOp = OP_Noop;
}else{
sqliteVdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
}
/* Generate the the top of the loop. If there is a termination
** key we have to test for that key and abort at the top of the
** loop.
*/
start = sqliteVdbeCurrentAddr(v);
if( testOp!=OP_Noop ){
sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
}
sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
sqliteVdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
if( i==pTabList->nSrc-1 && pushKey ){
haveKey = 1;
}else{
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
haveKey = 0;
}
/* Record the instruction used to terminate the loop.
*/
pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
pLevel->p1 = pLevel->iCur;
pLevel->p2 = start;
}
loopMask |= getMask(&maskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
*/
for(j=0; jiLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ){
continue;
}
if( haveKey ){
haveKey = 0;
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
}
sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
aExpr[j].p = 0;
}
brk = cont;
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->top = sqliteVdbeCurrentAddr(v);
sqliteVdbeAddOp(v, OP_Integer, 1, 0);
sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
for(j=0; jiContinue = cont;
if( pushKey && !haveKey ){
sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
}
freeMaskSet(&maskSet);
return pWInfo;
}
| where.c | 303 |
VOID | sqliteWhereEnd(WhereInfo *pWInfo)
void sqliteWhereEnd(WhereInfo *pWInfo){
Vdbe *v = pWInfo->pParse->pVdbe;
int i;
WhereLevel *pLevel;
SrcList *pTabList = pWInfo->pTabList;
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqliteVdbeResolveLabel(v, pLevel->cont);
if( pLevel->op!=OP_Noop ){
sqliteVdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);
}
sqliteVdbeResolveLabel(v, pLevel->brk);
if( pLevel->inOp!=OP_Noop ){
sqliteVdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);
}
if( pLevel->iLeftJoin ){
int addr;
addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));
sqliteVdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
if( pLevel->iCur>=0 ){
sqliteVdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);
}
sqliteVdbeAddOp(v, OP_Goto, 0, pLevel->top);
}
}
sqliteVdbeResolveLabel(v, pWInfo->iBreak);
for(i=0; inSrc; i++){
Table *pTab = pTabList->a[i].pTab;
assert( pTab!=0 );
if( pTab->isTransient || pTab->pSelect ) continue;
pLevel = &pWInfo->a[i];
sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
if( pLevel->pIdx!=0 ){
sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);
}
}
#if 0 /* Never reuse a cursor */
if( pWInfo->pParse->nTab==pWInfo->peakNTab ){
pWInfo->pParse->nTab = pWInfo->savedNTab;
}
#endif
sqliteFree(pWInfo);
return;
}
| where.c | 1186 |
|