Beispiel #1
0
/*
** This routine is called once for each row in the result table.  Its job
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.
*/
static public int sqlite3_get_table_cb( object pArg, i64 nCol, object Oargv, object Ocolv )
{
string[] argv = (string[])Oargv;
string[]colv = (string[])Ocolv;
TabResult p = (TabResult)pArg;
int need;
int i;
string 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!=null ){
need = (int)nCol*2;
}else{
need = (int)nCol;
}
if( p.nData + need >= p.nAlloc ){
string[] azNew;
p.nAlloc = p.nAlloc*2 + need + 1;
azNew = new string[p.nAlloc];//sqlite3_realloc( p.azResult, sizeof(char*)*p.nAlloc );
if( azNew==null ) goto malloc_failed;
p.azResult = azNew;
}

/* If this is the first row, then generate an extra row containing
** the names of all columns.
*/
if( p.nRow==0 ){
p.nColumn = (int)nCol;
for(i=0; i<nCol; i++){
z = sqlite3_mprintf("%s", colv[i]);
if( z==null ) goto malloc_failed;
p.azResult[p.nData++ -1] = z;
}
}else if( p.nColumn!=nCol ){
//sqlite3_free(ref p.zErrMsg);
p.zErrMsg = sqlite3_mprintf(
"sqlite3_get_table() called with two or more incompatible queries"
);
p.rc = SQLITE_ERROR;
return 1;
}

/* Copy over the row data
*/
if( argv!=null ){
for(i=0; i<nCol; i++){
if( argv[i]==null ){
z = null;
}else{
int n = sqlite3Strlen30(argv[i])+1;
//z = sqlite3_malloc( n );
//if( z==0 ) goto malloc_failed;
z= argv[i];//memcpy(z, argv[i], n);
}
p.azResult[p.nData++ -1] = z;
}
p.nRow++;
}
return 0;

malloc_failed:
p.rc = SQLITE_NOMEM;
return 1;
}
Beispiel #2
0
        /*
        ** pCur points at an index entry created using the OP_MakeRecord opcode.
        ** Read the rowid (the last field in the record) and store it in *rowid.
        ** Return SQLITE_OK if everything works, or an error code otherwise.
        **
        ** pCur might be pointing to text obtained from a corrupt database file.
        ** So the content cannot be trusted.  Do appropriate checks on the content.
        */
        static int sqlite3VdbeIdxRowid( sqlite3 db, BtCursor pCur, ref i64 rowid )
        {
            i64 nCellKey = 0;
              int rc;
              u32 szHdr = 0;        /* Size of the header */
              u32 typeRowid = 0;    /* Serial type of the rowid */
              u32 lenRowid;       /* Size of the rowid */
              Mem m = null;
              Mem v = null;
              v = sqlite3Malloc( v );
              UNUSED_PARAMETER( db );

              /* Get the size of the index entry.  Only indices entries of less
              ** than 2GiB are support - anything large must be database corruption.
              ** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
              ** this code can safely assume that nCellKey is 32-bits
              */
              Debug.Assert( sqlite3BtreeCursorIsValid( pCur ) );
              rc = sqlite3BtreeKeySize( pCur, ref nCellKey );
              Debug.Assert( rc == SQLITE_OK );     /* pCur is always valid so KeySize cannot fail */
              Debug.Assert( ( (u32)nCellKey & SQLITE_MAX_U32 ) == (u64)nCellKey );

              /* Read in the complete content of the index entry */
              m = sqlite3Malloc( m );
              // memset(&m, 0, sizeof(m));
              rc = sqlite3VdbeMemFromBtree( pCur, 0, (int)nCellKey, true, m );
              if ( rc != 0 )
              {
            return rc;
              }

              /* The index entry must begin with a header size */
              getVarint32( m.zBLOB, 0, ref szHdr );
              testcase( szHdr == 3 );
              testcase( szHdr == m.n );
              if ( unlikely( szHdr < 3 || (int)szHdr > m.n ) )
              {
            goto idx_rowid_corruption;
              }

              /* The last field of the index should be an integer - the ROWID.
              ** Verify that the last entry really is an integer. */
              getVarint32( m.zBLOB, szHdr - 1, ref typeRowid );
              testcase( typeRowid == 1 );
              testcase( typeRowid == 2 );
              testcase( typeRowid == 3 );
              testcase( typeRowid == 4 );
              testcase( typeRowid == 5 );
              testcase( typeRowid == 6 );
              testcase( typeRowid == 8 );
              testcase( typeRowid == 9 );
              if ( unlikely( typeRowid < 1 || typeRowid > 9 || typeRowid == 7 ) )
              {
            goto idx_rowid_corruption;
              }
              lenRowid = (u32)sqlite3VdbeSerialTypeLen( typeRowid );
              testcase( (u32)m.n == szHdr + lenRowid );
              if ( unlikely( (u32)m.n < szHdr + lenRowid ) )
              {
            goto idx_rowid_corruption;
              }

              /* Fetch the integer off the end of the index record */
              sqlite3VdbeSerialGet( m.zBLOB, (int)( m.n - lenRowid ), typeRowid, v );
              rowid = v.u.i;
              sqlite3VdbeMemRelease( m );
              return SQLITE_OK;

            /* Jump here if database corruption is detected after m has been
            ** allocated.  Free the m object and return SQLITE_CORRUPT. */
            idx_rowid_corruption:
              //testcase( m.zMalloc != 0 );
              sqlite3VdbeMemRelease( m );
              return SQLITE_CORRUPT_BKPT();
        }
Beispiel #3
0
 //P4_INT64
 static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, i64 pP4, int p4type )
 {
     union_p4 _p4 = new union_p4();
       _p4.pI64 = pP4;
       int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
       sqlite3VdbeChangeP4( p, addr, _p4, p4type );
       return addr;
 }
Beispiel #4
0
        static i64 refNULL = 0;   //Dummy for C# ref NULL

        static int checkTreePage(
            IntegrityCk pCheck,    /* Context for the sanity check */
            int iPage,             /* Page number of the page to check */
            string zParentContext, /* Parent context */
            ref i64 pnParentMinKey,
            ref i64 pnParentMaxKey,
            object _pnParentMinKey, /* C# Needed to determine if content passed*/
            object _pnParentMaxKey  /* C# Needed to determine if content passed*/
            )
        {
            MemPage pPage = new MemPage();
            int     i, rc, depth, d2, pgno, cnt;
            int     hdr, cellStart;
            int     nCell;

            u8[]          data;
            BtShared      pBt;
            int           usableSize;
            StringBuilder zContext = new StringBuilder(100);

            byte[] hit     = null;
            i64    nMinKey = 0;
            i64    nMaxKey = 0;


            sqlite3_snprintf(200, zContext, "Page %d: ", iPage);

            /* Check that the page exists
             */
            pBt        = pCheck.pBt;
            usableSize = (int)pBt.usableSize;
            if (iPage == 0)
            {
                return(0);
            }
            if (checkRef(pCheck, (u32)iPage, zParentContext) != 0)
            {
                return(0);
            }
            if ((rc = btreeGetPage(pBt, (Pgno)iPage, ref pPage, 0)) != 0)
            {
                checkAppendMsg(pCheck, zContext.ToString(),
                               "unable to get the page. error code=%d", rc);
                return(0);
            }

            /* Clear MemPage.isInit to make sure the corruption detection code in
            ** btreeInitPage() is executed.  */
            pPage.isInit = 0;
            if ((rc = btreeInitPage(pPage)) != 0)
            {
                Debug.Assert(rc == SQLITE_CORRUPT);  /* The only possible error from InitPage */
                checkAppendMsg(pCheck, zContext.ToString(),
                               "btreeInitPage() returns error code %d", rc);
                releasePage(pPage);
                return(0);
            }

            /* Check out all the cells.
             */
            depth = 0;
            for (i = 0; i < pPage.nCell && pCheck.mxErr != 0; i++)
            {
                u8[]     pCell;
                u32      sz;
                CellInfo info = new CellInfo();

                /* Check payload overflow pages
                 */
                sqlite3_snprintf(200, zContext,
                                 "On tree page %d cell %d: ", iPage, i);
                int iCell = findCell(pPage, i);            //pCell = findCell( pPage, i );
                pCell = pPage.aData;
                btreeParseCellPtr(pPage, iCell, ref info); //btreeParseCellPtr( pPage, pCell, info );
                sz = info.nData;
                if (0 == pPage.intKey)
                {
                    sz += (u32)info.nKey;
                }

                /* For intKey pages, check that the keys are in order.
                 */
                else if (i == 0)
                {
                    nMinKey = nMaxKey = info.nKey;
                }
                else
                {
                    if (info.nKey <= nMaxKey)
                    {
                        checkAppendMsg(pCheck, zContext.ToString(),
                                       "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
                    }
                    nMaxKey = info.nKey;
                }
                Debug.Assert(sz == info.nPayload);
                if ((sz > info.nLocal)
                    //&& (pCell[info.iOverflow]<=&pPage.aData[pBt.usableSize])
                    )
                {
                    int  nPage    = (int)(sz - info.nLocal + usableSize - 5) / (usableSize - 4);
                    Pgno pgnoOvfl = sqlite3Get4byte(pCell, iCell, info.iOverflow);
#if !SQLITE_OMIT_AUTOVACUUM
                    if (pBt.autoVacuum)
                    {
                        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, (u32)iPage, zContext.ToString());
                    }
#endif
                    checkList(pCheck, 0, (int)pgnoOvfl, nPage, zContext.ToString());
                }

                /* Check sanity of left child page.
                 */
                if (0 == pPage.leaf)
                {
                    pgno = (int)sqlite3Get4byte(pCell, iCell); //sqlite3Get4byte( pCell );
#if !SQLITE_OMIT_AUTOVACUUM
                    if (pBt.autoVacuum)
                    {
                        checkPtrmap(pCheck, (u32)pgno, PTRMAP_BTREE, (u32)iPage, zContext.ToString());
                    }
#endif
                    if (i == 0)
                    {
                        d2 = checkTreePage(pCheck, pgno, zContext.ToString(), ref nMinKey, ref refNULL, pCheck, null);
                    }
                    else
                    {
                        d2 = checkTreePage(pCheck, pgno, zContext.ToString(), ref nMinKey, ref nMaxKey, pCheck, pCheck);
                    }

                    if (i > 0 && d2 != depth)
                    {
                        checkAppendMsg(pCheck, zContext, "Child page depth differs");
                    }
                    depth = d2;
                }
            }
            if (0 == pPage.leaf)
            {
                pgno = (int)sqlite3Get4byte(pPage.aData, pPage.hdrOffset + 8);
                sqlite3_snprintf(200, zContext,
                                 "On page %d at right child: ", iPage);
#if !SQLITE_OMIT_AUTOVACUUM
                if (pBt.autoVacuum)
                {
                    checkPtrmap(pCheck, (u32)pgno, PTRMAP_BTREE, (u32)iPage, zContext.ToString());
                }
#endif
                //    checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
                if (0 == pPage.nCell)
                {
                    checkTreePage(pCheck, pgno, zContext.ToString(), ref refNULL, ref refNULL, null, null);
                }
                else
                {
                    checkTreePage(pCheck, pgno, zContext.ToString(), ref refNULL, ref nMaxKey, null, pCheck);
                }
            }

            /* For intKey leaf pages, check that the min/max keys are in order
            ** with any left/parent/right pages.
            */
            if (pPage.leaf != 0 && pPage.intKey != 0)
            {
                /* if we are a left child page */
                if (_pnParentMinKey != null)
                {
                    /* if we are the left most child page */
                    if (_pnParentMaxKey == null)
                    {
                        if (nMaxKey > pnParentMinKey)
                        {
                            checkAppendMsg(pCheck, zContext,
                                           "Rowid %lld out of order (max larger than parent min of %lld)",
                                           nMaxKey, pnParentMinKey);
                        }
                    }
                    else
                    {
                        if (nMinKey <= pnParentMinKey)
                        {
                            checkAppendMsg(pCheck, zContext,
                                           "Rowid %lld out of order (min less than parent min of %lld)",
                                           nMinKey, pnParentMinKey);
                        }
                        if (nMaxKey > pnParentMaxKey)
                        {
                            checkAppendMsg(pCheck, zContext,
                                           "Rowid %lld out of order (max larger than parent max of %lld)",
                                           nMaxKey, pnParentMaxKey);
                        }
                        pnParentMinKey = nMaxKey;
                    }
                    /* else if we're a right child page */
                }
                else if (_pnParentMaxKey != null)
                {
                    if (nMinKey <= pnParentMaxKey)
                    {
                        checkAppendMsg(pCheck, zContext,
                                       "Rowid %lld out of order (min less than parent max of %lld)",
                                       nMinKey, pnParentMaxKey);
                    }
                }
            }

            /* Check for complete coverage of the page
             */
            data = pPage.aData;
            hdr  = pPage.hdrOffset;
            hit  = sqlite3Malloc(pBt.pageSize);
            //if( hit==null ){
            //  pCheck.mallocFailed = 1;
            //}else
            {
                int contentOffset = get2byteNotZero(data, hdr + 5);
                Debug.Assert(contentOffset <= usableSize);                   /* Enforced by btreeInitPage() */
                Array.Clear(hit, contentOffset, usableSize - contentOffset); //memset(hit+contentOffset, 0, usableSize-contentOffset);
                for (int iLoop = contentOffset - 1; iLoop >= 0; iLoop--)
                {
                    hit[iLoop] = 1;//memset(hit, 1, contentOffset);
                }
                nCell     = get2byte(data, hdr + 3);
                cellStart = hdr + 12 - 4 * pPage.leaf;
                for (i = 0; i < nCell; i++)
                {
                    int pc   = get2byte(data, cellStart + i * 2);
                    u32 size = 65536;
                    int j;
                    if (pc <= usableSize - 4)
                    {
                        size = cellSizePtr(pPage, data, pc);
                    }
                    if ((int)(pc + size - 1) >= usableSize)
                    {
                        checkAppendMsg(pCheck, "",
                                       "Corruption detected in cell %d on page %d", i, iPage);
                    }
                    else
                    {
                        for (j = (int)(pc + size - 1); j >= pc; j--)
                        {
                            hit[j]++;
                        }
                    }
                }
                i = get2byte(data, hdr + 1);
                while (i > 0)
                {
                    int size, j;
                    Debug.Assert(i <= usableSize - 4);     /* Enforced by btreeInitPage() */
                    size = get2byte(data, i + 2);
                    Debug.Assert(i + size <= usableSize);  /* Enforced by btreeInitPage() */
                    for (j = i + size - 1; j >= i; j--)
                    {
                        hit[j]++;
                    }
                    j = get2byte(data, i);
                    Debug.Assert(j == 0 || j > i + size); /* Enforced by btreeInitPage() */
                    Debug.Assert(j <= usableSize - 4);    /* Enforced by btreeInitPage() */
                    i = j;
                }
                for (i = cnt = 0; i < usableSize; i++)
                {
                    if (hit[i] == 0)
                    {
                        cnt++;
                    }
                    else if (hit[i] > 1)
                    {
                        checkAppendMsg(pCheck, "",
                                       "Multiple uses for byte %d of page %d", i, iPage);
                        break;
                    }
                }
                if (cnt != data[hdr + 7])
                {
                    checkAppendMsg(pCheck, "",
                                   "Fragmentation of %d bytes reported as %d on page %d",
                                   cnt, data[hdr + 7], iPage);
                }
            }
            sqlite3PageFree(ref hit);
            releasePage(pPage);
            return(depth + 1);
        }