Merge trunk into wasi-patches branch and add missing yes/no result to the configure script's output for the --with-wasi-sdk=PATH test.
FossilOrigin-Name: adc0ede0a43241b85563408d0de8e640a75ec4f7bdfe5e48acc5cdd6b182b88c
This commit is contained in:
@@ -10430,6 +10430,8 @@ fi
|
||||
|
||||
if test "${use_wasi_sdk}" = "no" ; then
|
||||
HAVE_WASI_SDK=""
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
else
|
||||
HAVE_WASI_SDK=1
|
||||
# Changing --host and --target have no effect here except to possibly
|
||||
@@ -10451,6 +10453,8 @@ else
|
||||
# libtool is apparently hard-coded to use gcc for linking DLLs, so
|
||||
# we disable the DLL build...
|
||||
enable_shared=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ AC_CACHE_VAL(ac_cv_c_wasi_sdk,[
|
||||
])
|
||||
if test "${use_wasi_sdk}" = "no" ; then
|
||||
HAVE_WASI_SDK=""
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
HAVE_WASI_SDK=1
|
||||
# Changing --host and --target have no effect here except to possibly
|
||||
@@ -202,6 +203,7 @@ else
|
||||
# libtool is apparently hard-coded to use gcc for linking DLLs, so
|
||||
# we disable the DLL build...
|
||||
enable_shared=no
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
AC_SUBST(HAVE_WASI_SDK)
|
||||
|
||||
|
||||
@@ -1625,7 +1625,7 @@ static int fts5UpdateMethod(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
/* A transaction must be open when this is called. */
|
||||
assert( pTab->ts.eState==1 );
|
||||
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
|
||||
|
||||
assert( pVtab->zErrMsg==0 );
|
||||
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
|
||||
|
||||
@@ -402,5 +402,46 @@ do_test 15.4 {
|
||||
list [catch { db2 eval COMMIT } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db
|
||||
do_execsql_test 16.0 {
|
||||
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t2(x,y);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a);
|
||||
BEGIN;
|
||||
INSERT INTO x1 VALUES('abc');
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 16.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
BEGIN;
|
||||
SELECT * FROM t2
|
||||
} {1 2}
|
||||
|
||||
do_catchsql_test 16.2 {
|
||||
COMMIT;
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_execsql_test 16.3 {
|
||||
INSERT INTO x1 VALUES('def');
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 16.4 {
|
||||
END
|
||||
}
|
||||
|
||||
do_execsql_test 16.5 {
|
||||
COMMIT
|
||||
}
|
||||
|
||||
do_execsql_test -db db2 16.6 {
|
||||
SELECT * FROM x1
|
||||
} {abc def}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+3
-1
@@ -405,7 +405,7 @@ struct Segment {
|
||||
LsmPgno iFirst; /* First page of this run */
|
||||
LsmPgno iLastPg; /* Last page of this run */
|
||||
LsmPgno iRoot; /* Root page number (if any) */
|
||||
int nSize; /* Size of this run in pages */
|
||||
LsmPgno nSize; /* Size of this run in pages */
|
||||
|
||||
Redirect *pRedirect; /* Block redirects (or NULL) */
|
||||
};
|
||||
@@ -853,6 +853,8 @@ int lsmVarintGet32(u8 *, int *);
|
||||
int lsmVarintPut64(u8 *aData, i64 iVal);
|
||||
int lsmVarintGet64(const u8 *aData, i64 *piVal);
|
||||
|
||||
int lsmVarintLen64(i64);
|
||||
|
||||
int lsmVarintLen32(int);
|
||||
int lsmVarintSize(u8 c);
|
||||
|
||||
|
||||
+1
-1
@@ -511,7 +511,7 @@ static void ckptNewSegment(
|
||||
pSegment->iFirst = ckptGobble64(aIn, piIn);
|
||||
pSegment->iLastPg = ckptGobble64(aIn, piIn);
|
||||
pSegment->iRoot = ckptGobble64(aIn, piIn);
|
||||
pSegment->nSize = (int)ckptGobble64(aIn, piIn);
|
||||
pSegment->nSize = ckptGobble64(aIn, piIn);
|
||||
assert( pSegment->iFirst );
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -215,8 +215,8 @@ struct FileSystem {
|
||||
char *zLog; /* Database file name */
|
||||
int nMetasize; /* Size of meta pages in bytes */
|
||||
int nMetaRwSize; /* Read/written size of meta pages in bytes */
|
||||
int nPagesize; /* Database page-size in bytes */
|
||||
int nBlocksize; /* Database block-size in bytes */
|
||||
i64 nPagesize; /* Database page-size in bytes */
|
||||
i64 nBlocksize; /* Database block-size in bytes */
|
||||
|
||||
/* r/w file descriptors for both files. */
|
||||
LsmFile *pLsmFile; /* Used after lsm_close() to link into list */
|
||||
@@ -889,7 +889,7 @@ static LsmPgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){
|
||||
iPg = pFS->nBlocksize * (LsmPgno)(iBlock-1) + 4;
|
||||
}
|
||||
}else{
|
||||
const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
|
||||
const i64 nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
|
||||
if( iBlock==1 ){
|
||||
iPg = 1 + ((pFS->nMetasize*2 + pFS->nPagesize - 1) / pFS->nPagesize);
|
||||
}else{
|
||||
@@ -1131,7 +1131,6 @@ static void fsGrowMapping(
|
||||
i64 iSz, /* Minimum size to extend mapping to */
|
||||
int *pRc /* IN/OUT: Error code */
|
||||
){
|
||||
assert( pFS->pCompress==0 );
|
||||
assert( PAGE_HASPREV==4 );
|
||||
|
||||
if( *pRc==LSM_OK && iSz>pFS->nMap ){
|
||||
@@ -1872,7 +1871,7 @@ void lsmFsGobble(
|
||||
assert( nPgno>0 && 0==fsPageRedirects(pFS, pRun, aPgno[0]) );
|
||||
|
||||
iBlk = fsPageToBlock(pFS, pRun->iFirst);
|
||||
pRun->nSize += (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
|
||||
pRun->nSize += (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
|
||||
|
||||
while( rc==LSM_OK ){
|
||||
int iNext = 0;
|
||||
@@ -1883,13 +1882,13 @@ void lsmFsGobble(
|
||||
}
|
||||
rc = fsBlockNext(pFS, pRun, iBlk, &iNext);
|
||||
if( rc==LSM_OK ) rc = fsFreeBlock(pFS, pSnapshot, pRun, iBlk);
|
||||
pRun->nSize -= (int)(
|
||||
pRun->nSize -= (
|
||||
1 + fsLastPageOnBlock(pFS, iBlk) - fsFirstPageOnBlock(pFS, iBlk)
|
||||
);
|
||||
iBlk = iNext;
|
||||
}
|
||||
|
||||
pRun->nSize -= (int)(pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
|
||||
pRun->nSize -= (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
|
||||
assert( pRun->nSize>0 );
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -432,7 +432,7 @@ int lsm_config(lsm_db *pDb, int eParam, ...){
|
||||
}
|
||||
|
||||
void lsmAppendSegmentList(LsmString *pStr, char *zPre, Segment *pSeg){
|
||||
lsmStringAppendf(pStr, "%s{%d %d %d %d}", zPre,
|
||||
lsmStringAppendf(pStr, "%s{%lld %lld %lld %lld}", zPre,
|
||||
pSeg->iFirst, pSeg->iLastPg, pSeg->iRoot, pSeg->nSize
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1306,6 +1306,24 @@ int lsmBeginRoTrans(lsm_db *db){
|
||||
}
|
||||
}
|
||||
|
||||
/* In 'lsm_open()' we don't update the page and block sizes in the
|
||||
** Filesystem for 'readonly' connection. Because member 'db->pShmhdr' is a
|
||||
** nullpointer, this prevents loading a checkpoint. Now that the system is
|
||||
** live this member should be set. So we can update both values in
|
||||
** the Filesystem.
|
||||
**
|
||||
** Configure the file-system connection with the page-size and block-size
|
||||
** of this database. Even if the database file is zero bytes in size
|
||||
** on disk, these values have been set in shared-memory by now, and so
|
||||
** are guaranteed not to change during the lifetime of this connection. */
|
||||
if( LSM_OK==rc
|
||||
&& 0==lsmCheckpointClientCacheOk(db)
|
||||
&& LSM_OK==(rc=lsmCheckpointLoad(db, 0))
|
||||
){
|
||||
lsmFsSetPageSize(db->pFS, lsmCheckpointPgsz(db->aSnapshot));
|
||||
lsmFsSetBlockSize(db->pFS, lsmCheckpointBlksz(db->aSnapshot));
|
||||
}
|
||||
|
||||
if( rc==LSM_OK ){
|
||||
rc = lsmBeginReadTrans(db);
|
||||
}
|
||||
|
||||
+54
-53
@@ -657,14 +657,14 @@ static int btreeCursorLoadKey(BtreeCursor *pCsr){
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int btreeCursorPtr(u8 *aData, int nData, int iCell){
|
||||
static LsmPgno btreeCursorPtr(u8 *aData, int nData, int iCell){
|
||||
int nCell;
|
||||
|
||||
nCell = pageGetNRec(aData, nData);
|
||||
if( iCell>=nCell ){
|
||||
return (int)pageGetPtr(aData, nData);
|
||||
return pageGetPtr(aData, nData);
|
||||
}
|
||||
return (int)pageGetRecordPtr(aData, nData, iCell);
|
||||
return pageGetRecordPtr(aData, nData, iCell);
|
||||
}
|
||||
|
||||
static int btreeCursorNext(BtreeCursor *pCsr){
|
||||
@@ -751,7 +751,7 @@ static int btreeCursorFirst(BtreeCursor *pCsr){
|
||||
|
||||
Page *pPg = 0;
|
||||
FileSystem *pFS = pCsr->pFS;
|
||||
int iPg = (int)pCsr->pSeg->iRoot;
|
||||
LsmPgno iPg = pCsr->pSeg->iRoot;
|
||||
|
||||
do {
|
||||
rc = lsmFsDbPageGet(pFS, pCsr->pSeg, iPg, &pPg);
|
||||
@@ -779,7 +779,7 @@ static int btreeCursorFirst(BtreeCursor *pCsr){
|
||||
assert( pCsr->aPg[pCsr->nDepth].iCell==0 );
|
||||
pCsr->aPg[pCsr->nDepth].pPage = pPg;
|
||||
pCsr->nDepth++;
|
||||
iPg = (int)pageGetRecordPtr(aData, nData, 0);
|
||||
iPg = pageGetRecordPtr(aData, nData, 0);
|
||||
}
|
||||
}
|
||||
}while( rc==LSM_OK );
|
||||
@@ -871,7 +871,7 @@ static int btreeCursorRestore(
|
||||
int nSeek;
|
||||
int iTopicSeek;
|
||||
int iPg = 0;
|
||||
int iLoad = (int)pSeg->iRoot;
|
||||
LsmPgno iLoad = pSeg->iRoot;
|
||||
Page *pPg = pCsr->aPg[nDepth-1].pPage;
|
||||
|
||||
if( pageObjGetNRec(pPg)==0 ){
|
||||
@@ -903,7 +903,7 @@ static int btreeCursorRestore(
|
||||
aData = fsPageData(pPg2, &nData);
|
||||
assert( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );
|
||||
|
||||
iLoad = (int)pageGetPtr(aData, nData);
|
||||
iLoad = pageGetPtr(aData, nData);
|
||||
iCell2 = pageGetNRec(aData, nData);
|
||||
iMax = iCell2-1;
|
||||
iMin = 0;
|
||||
@@ -926,7 +926,7 @@ static int btreeCursorRestore(
|
||||
assert( res!=0 );
|
||||
|
||||
if( res<0 ){
|
||||
iLoad = (int)iPtr;
|
||||
iLoad = iPtr;
|
||||
iCell2 = iTry;
|
||||
iMax = iTry-1;
|
||||
}else{
|
||||
@@ -1013,7 +1013,7 @@ static void segmentPtrSetPage(SegmentPtr *pPtr, Page *pNext){
|
||||
static int segmentPtrLoadPage(
|
||||
FileSystem *pFS,
|
||||
SegmentPtr *pPtr, /* Load page into this SegmentPtr object */
|
||||
int iNew /* Page number of new page */
|
||||
LsmPgno iNew /* Page number of new page */
|
||||
){
|
||||
Page *pPg = 0; /* The new page */
|
||||
int rc; /* Return Code */
|
||||
@@ -1633,7 +1633,7 @@ static int segmentPtrSeek(
|
||||
int iTopic, /* Key topic to seek to */
|
||||
void *pKey, int nKey, /* Key to seek to */
|
||||
int eSeek, /* Search bias - see above */
|
||||
int *piPtr, /* OUT: FC pointer */
|
||||
LsmPgno *piPtr, /* OUT: FC pointer */
|
||||
int *pbStop
|
||||
){
|
||||
int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
|
||||
@@ -1759,7 +1759,7 @@ static int segmentPtrSeek(
|
||||
}
|
||||
|
||||
assert( rc!=LSM_OK || assertSeekResult(pCsr,pPtr,iTopic,pKey,nKey,eSeek) );
|
||||
*piPtr = (int)iPtrOut;
|
||||
*piPtr = iPtrOut;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1773,11 +1773,11 @@ static int seekInBtree(
|
||||
){
|
||||
int i = 0;
|
||||
int rc;
|
||||
int iPg;
|
||||
LsmPgno iPg;
|
||||
Page *pPg = 0;
|
||||
LsmBlob blob = {0, 0, 0};
|
||||
|
||||
iPg = (int)pSeg->iRoot;
|
||||
iPg = pSeg->iRoot;
|
||||
do {
|
||||
LsmPgno *piFirst = 0;
|
||||
if( aPg ){
|
||||
@@ -1799,7 +1799,7 @@ static int seekInBtree(
|
||||
flags = pageGetFlags(aData, nData);
|
||||
if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;
|
||||
|
||||
iPg = (int)pageGetPtr(aData, nData);
|
||||
iPg = pageGetPtr(aData, nData);
|
||||
nRec = pageGetNRec(aData, nData);
|
||||
|
||||
iMin = 0;
|
||||
@@ -1825,7 +1825,7 @@ static int seekInBtree(
|
||||
pCsr->pDb->xCmp, iTopic, pKey, nKey, iTopicT, pKeyT, nKeyT
|
||||
);
|
||||
if( res<0 ){
|
||||
iPg = (int)iPtr;
|
||||
iPg = iPtr;
|
||||
iMax = iTry-1;
|
||||
}else{
|
||||
iMin = iTry+1;
|
||||
@@ -1851,12 +1851,12 @@ static int seekInSegment(
|
||||
SegmentPtr *pPtr,
|
||||
int iTopic,
|
||||
void *pKey, int nKey,
|
||||
int iPg, /* Page to search */
|
||||
LsmPgno iPg, /* Page to search */
|
||||
int eSeek, /* Search bias - see above */
|
||||
int *piPtr, /* OUT: FC pointer */
|
||||
LsmPgno *piPtr, /* OUT: FC pointer */
|
||||
int *pbStop /* OUT: Stop search flag */
|
||||
){
|
||||
int iPtr = iPg;
|
||||
LsmPgno iPtr = iPg;
|
||||
int rc = LSM_OK;
|
||||
|
||||
if( pPtr->pSeg->iRoot ){
|
||||
@@ -1866,7 +1866,7 @@ static int seekInSegment(
|
||||
if( rc==LSM_OK ) segmentPtrSetPage(pPtr, pPg);
|
||||
}else{
|
||||
if( iPtr==0 ){
|
||||
iPtr = (int)pPtr->pSeg->iFirst;
|
||||
iPtr = pPtr->pSeg->iFirst;
|
||||
}
|
||||
if( rc==LSM_OK ){
|
||||
rc = segmentPtrLoadPage(pCsr->pDb->pFS, pPtr, iPtr);
|
||||
@@ -1904,7 +1904,7 @@ static int seekInLevel(
|
||||
){
|
||||
Level *pLvl = aPtr[0].pLevel; /* Level to seek within */
|
||||
int rc = LSM_OK; /* Return code */
|
||||
int iOut = 0; /* Pointer to return to caller */
|
||||
LsmPgno iOut = 0; /* Pointer to return to caller */
|
||||
int res = -1; /* Result of xCmp(pKey, split) */
|
||||
int nRhs = pLvl->nRight; /* Number of right-hand-side segments */
|
||||
int bStop = 0;
|
||||
@@ -1923,8 +1923,8 @@ static int seekInLevel(
|
||||
** left-hand-side of the level in this case. */
|
||||
if( res<0 ){
|
||||
int i;
|
||||
int iPtr = 0;
|
||||
if( nRhs==0 ) iPtr = (int)*piPgno;
|
||||
LsmPgno iPtr = 0;
|
||||
if( nRhs==0 ) iPtr = *piPgno;
|
||||
|
||||
rc = seekInSegment(
|
||||
pCsr, &aPtr[0], iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
|
||||
@@ -1939,7 +1939,7 @@ static int seekInLevel(
|
||||
|
||||
if( res>=0 ){
|
||||
int bHit = 0; /* True if at least one rhs is not EOF */
|
||||
int iPtr = (int)*piPgno;
|
||||
LsmPgno iPtr = *piPgno;
|
||||
int i;
|
||||
segmentPtrReset(&aPtr[0], LSM_SEGMENTPTR_FREE_THRESHOLD);
|
||||
for(i=1; rc==LSM_OK && i<=nRhs && bStop==0; i++){
|
||||
@@ -3480,7 +3480,7 @@ static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
|
||||
lsm_env *pEnv = pMW->pDb->pEnv;
|
||||
Page **apHier = 0;
|
||||
int nHier = 0;
|
||||
int iPg = (int)pSeg->iRoot;
|
||||
LsmPgno iPg = pSeg->iRoot;
|
||||
|
||||
do {
|
||||
Page *pPg = 0;
|
||||
@@ -3506,7 +3506,7 @@ static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
|
||||
nHier++;
|
||||
|
||||
apHier[0] = pPg;
|
||||
iPg = (int)pageGetPtr(aData, nData);
|
||||
iPg = pageGetPtr(aData, nData);
|
||||
}else{
|
||||
lsmFsPageRelease(pPg);
|
||||
break;
|
||||
@@ -3625,10 +3625,11 @@ static int mergeWorkerBtreeWrite(
|
||||
assert( lsmFsPageWritable(pOld) );
|
||||
aData = fsPageData(pOld, &nData);
|
||||
if( eType==0 ){
|
||||
nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32((int)iKeyPg);
|
||||
nByte = 2 + 1 + lsmVarintLen64(iPtr) + lsmVarintLen64(iKeyPg);
|
||||
}else{
|
||||
nByte = 2 + 1 + lsmVarintLen32((int)iPtr) + lsmVarintLen32(nKey) + nKey;
|
||||
nByte = 2 + 1 + lsmVarintLen64(iPtr) + lsmVarintLen32(nKey) + nKey;
|
||||
}
|
||||
|
||||
nRec = pageGetNRec(aData, nData);
|
||||
nFree = SEGMENT_EOF(nData, nRec) - mergeWorkerPageOffset(aData, nData);
|
||||
if( nByte<=nFree ) break;
|
||||
@@ -3672,11 +3673,11 @@ static int mergeWorkerBtreeWrite(
|
||||
lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], (u16)(nRec+1));
|
||||
if( eType==0 ){
|
||||
aData[iOff++] = 0x00;
|
||||
iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
|
||||
iOff += lsmVarintPut32(&aData[iOff], (int)iKeyPg);
|
||||
iOff += lsmVarintPut64(&aData[iOff], iPtr);
|
||||
iOff += lsmVarintPut64(&aData[iOff], iKeyPg);
|
||||
}else{
|
||||
aData[iOff++] = eType;
|
||||
iOff += lsmVarintPut32(&aData[iOff], (int)iPtr);
|
||||
iOff += lsmVarintPut64(&aData[iOff], iPtr);
|
||||
iOff += lsmVarintPut32(&aData[iOff], nKey);
|
||||
memcpy(&aData[iOff], pKey, nKey);
|
||||
}
|
||||
@@ -3872,7 +3873,7 @@ static int mergeWorkerNextPage(
|
||||
static int mergeWorkerData(
|
||||
MergeWorker *pMW, /* Merge worker object */
|
||||
int bSep, /* True to write to separators run */
|
||||
int iFPtr, /* Footer ptr for new pages */
|
||||
LsmPgno iFPtr, /* Footer ptr for new pages */
|
||||
u8 *aWrite, /* Write data from this buffer */
|
||||
int nWrite /* Size of aWrite[] in bytes */
|
||||
){
|
||||
@@ -3916,14 +3917,14 @@ static int mergeWorkerData(
|
||||
static int mergeWorkerFirstPage(MergeWorker *pMW){
|
||||
int rc = LSM_OK; /* Return code */
|
||||
Page *pPg = 0; /* First page of run pSeg */
|
||||
int iFPtr = 0; /* Pointer value read from footer of pPg */
|
||||
LsmPgno iFPtr = 0; /* Pointer value read from footer of pPg */
|
||||
MultiCursor *pCsr = pMW->pCsr;
|
||||
|
||||
assert( pMW->pPage==0 );
|
||||
|
||||
if( pCsr->pBtCsr ){
|
||||
rc = LSM_OK;
|
||||
iFPtr = (int)pMW->pLevel->pNext->lhs.iFirst;
|
||||
iFPtr = pMW->pLevel->pNext->lhs.iFirst;
|
||||
}else if( pCsr->nPtr>0 ){
|
||||
Segment *pSeg;
|
||||
pSeg = pCsr->aPtr[pCsr->nPtr-1].pSeg;
|
||||
@@ -3932,7 +3933,7 @@ static int mergeWorkerFirstPage(MergeWorker *pMW){
|
||||
u8 *aData; /* Buffer for page pPg */
|
||||
int nData; /* Size of aData[] in bytes */
|
||||
aData = fsPageData(pPg, &nData);
|
||||
iFPtr = (int)pageGetPtr(aData, nData);
|
||||
iFPtr = pageGetPtr(aData, nData);
|
||||
lsmFsPageRelease(pPg);
|
||||
}
|
||||
}
|
||||
@@ -3951,7 +3952,7 @@ static int mergeWorkerWrite(
|
||||
int eType, /* One of SORTED_SEPARATOR, WRITE or DELETE */
|
||||
void *pKey, int nKey, /* Key value */
|
||||
void *pVal, int nVal, /* Value value */
|
||||
int iPtr /* Absolute value of page pointer, or 0 */
|
||||
LsmPgno iPtr /* Absolute value of page pointer, or 0 */
|
||||
){
|
||||
int rc = LSM_OK; /* Return code */
|
||||
Merge *pMerge; /* Persistent part of level merge state */
|
||||
@@ -3960,8 +3961,8 @@ static int mergeWorkerWrite(
|
||||
u8 *aData; /* Data buffer for page pWriter->pPage */
|
||||
int nData = 0; /* Size of buffer aData[] in bytes */
|
||||
int nRec = 0; /* Number of records on page pPg */
|
||||
int iFPtr = 0; /* Value of pointer in footer of pPg */
|
||||
int iRPtr = 0; /* Value of pointer written into record */
|
||||
LsmPgno iFPtr = 0; /* Value of pointer in footer of pPg */
|
||||
LsmPgno iRPtr = 0; /* Value of pointer written into record */
|
||||
int iOff = 0; /* Current write offset within page pPg */
|
||||
Segment *pSeg; /* Segment being written */
|
||||
int flags = 0; /* If != 0, flags value for page footer */
|
||||
@@ -3978,7 +3979,7 @@ static int mergeWorkerWrite(
|
||||
if( pPg ){
|
||||
aData = fsPageData(pPg, &nData);
|
||||
nRec = pageGetNRec(aData, nData);
|
||||
iFPtr = (int)pageGetPtr(aData, nData);
|
||||
iFPtr = pageGetPtr(aData, nData);
|
||||
iRPtr = iPtr - iFPtr;
|
||||
}
|
||||
|
||||
@@ -4009,7 +4010,7 @@ static int mergeWorkerWrite(
|
||||
assert( aData );
|
||||
memset(&aData[iOff], 0, SEGMENT_EOF(nData, nRec)-iOff);
|
||||
}
|
||||
iFPtr = (int)*pMW->pCsr->pPrevMergePtr;
|
||||
iFPtr = *pMW->pCsr->pPrevMergePtr;
|
||||
iRPtr = iPtr - iFPtr;
|
||||
iOff = 0;
|
||||
nRec = 0;
|
||||
@@ -4283,7 +4284,7 @@ static int mergeWorkerStep(MergeWorker *pMW){
|
||||
pVal = pCsr->val.pData;
|
||||
}
|
||||
if( rc==LSM_OK ){
|
||||
rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, (int)iPtr);
|
||||
rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, iPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4604,7 +4605,7 @@ static int mergeWorkerInit(
|
||||
SegmentPtr *pPtr;
|
||||
assert( pCsr->aPtr[i].pPg==0 );
|
||||
pPtr = &pCsr->aPtr[i];
|
||||
rc = segmentPtrLoadPage(pDb->pFS, pPtr, (int)pInput->iPg);
|
||||
rc = segmentPtrLoadPage(pDb->pFS, pPtr, pInput->iPg);
|
||||
if( rc==LSM_OK && pPtr->nCell>0 ){
|
||||
rc = segmentPtrLoadCell(pPtr, pInput->iCell);
|
||||
}
|
||||
@@ -5469,7 +5470,7 @@ int lsmFlushTreeToDisk(lsm_db *pDb){
|
||||
** be freed by the caller using lsmFree().
|
||||
*/
|
||||
static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
|
||||
int nSize = pSeg->nSize;
|
||||
LsmPgno nSize = pSeg->nSize;
|
||||
LsmPgno iRoot = pSeg->iRoot;
|
||||
LsmPgno iFirst = pSeg->iFirst;
|
||||
LsmPgno iLast = pSeg->iLastPg;
|
||||
@@ -5481,9 +5482,9 @@ static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
|
||||
|
||||
z1 = lsmMallocPrintf(pEnv, "%d.%d", iFirst, iLast);
|
||||
if( iRoot ){
|
||||
z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
|
||||
z2 = lsmMallocPrintf(pEnv, "root=%lld", iRoot);
|
||||
}else{
|
||||
z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
|
||||
z2 = lsmMallocPrintf(pEnv, "size=%lld", nSize);
|
||||
}
|
||||
|
||||
nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
|
||||
@@ -5536,7 +5537,7 @@ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
|
||||
int i;
|
||||
|
||||
int nRec;
|
||||
int iPtr;
|
||||
LsmPgno iPtr;
|
||||
int flags;
|
||||
u8 *aData;
|
||||
int nData;
|
||||
@@ -5544,11 +5545,11 @@ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
|
||||
aData = fsPageData(pPg, &nData);
|
||||
|
||||
nRec = pageGetNRec(aData, nData);
|
||||
iPtr = (int)pageGetPtr(aData, nData);
|
||||
iPtr = pageGetPtr(aData, nData);
|
||||
flags = pageGetFlags(aData, nData);
|
||||
|
||||
lsmStringInit(&s, pDb->pEnv);
|
||||
lsmStringAppendf(&s,"nCell=%d iPtr=%d flags=%d {", nRec, iPtr, flags);
|
||||
lsmStringAppendf(&s,"nCell=%d iPtr=%lld flags=%d {", nRec, iPtr, flags);
|
||||
if( flags&SEGMENT_BTREE_FLAG ) iPtr = 0;
|
||||
|
||||
for(i=0; i<nRec; i++){
|
||||
@@ -5558,13 +5559,13 @@ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
|
||||
u8 *aVal = 0; int nVal = 0; /* Value */
|
||||
int iTopic;
|
||||
u8 *aCell;
|
||||
int iPgPtr;
|
||||
i64 iPgPtr;
|
||||
int eType;
|
||||
|
||||
aCell = pageGetCell(aData, nData, i);
|
||||
eType = *aCell++;
|
||||
assert( (flags & SEGMENT_BTREE_FLAG) || eType!=0 );
|
||||
aCell += lsmVarintGet32(aCell, &iPgPtr);
|
||||
aCell += lsmVarintGet64(aCell, &iPgPtr);
|
||||
|
||||
if( eType==0 ){
|
||||
LsmPgno iRef; /* Page number of referenced page */
|
||||
@@ -5590,7 +5591,7 @@ void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
|
||||
}
|
||||
}
|
||||
|
||||
lsmStringAppendf(&s, " %d", iPgPtr+iPtr);
|
||||
lsmStringAppendf(&s, " %lld", iPgPtr+iPtr);
|
||||
lsmFsPageRelease(pRef);
|
||||
}
|
||||
lsmStringAppend(&s, "}", 1);
|
||||
@@ -5720,20 +5721,20 @@ static int infoPageDump(
|
||||
int nKeyWidth = 0;
|
||||
LsmString str;
|
||||
int nRec;
|
||||
int iPtr;
|
||||
LsmPgno iPtr;
|
||||
int flags2;
|
||||
int iCell;
|
||||
u8 *aData; int nData; /* Page data and size thereof */
|
||||
|
||||
aData = fsPageData(pPg, &nData);
|
||||
nRec = pageGetNRec(aData, nData);
|
||||
iPtr = (int)pageGetPtr(aData, nData);
|
||||
iPtr = pageGetPtr(aData, nData);
|
||||
flags2 = pageGetFlags(aData, nData);
|
||||
|
||||
lsmStringInit(&str, pDb->pEnv);
|
||||
lsmStringAppendf(&str, "Page : %lld (%d bytes)\n", iPg, nData);
|
||||
lsmStringAppendf(&str, "nRec : %d\n", nRec);
|
||||
lsmStringAppendf(&str, "iPtr : %d\n", iPtr);
|
||||
lsmStringAppendf(&str, "iPtr : %lld\n", iPtr);
|
||||
lsmStringAppendf(&str, "flags: %04x\n", flags2);
|
||||
lsmStringAppendf(&str, "\n");
|
||||
|
||||
|
||||
@@ -185,6 +185,11 @@ int lsmVarintLen32(int n){
|
||||
return lsmVarintPut32(aData, n);
|
||||
}
|
||||
|
||||
int lsmVarintLen64(i64 n){
|
||||
u8 aData[9];
|
||||
return lsmVarintPut64(aData, n);
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is the first byte of a varint. This function returns the
|
||||
** total number of bytes in the entire varint (including the first byte).
|
||||
|
||||
+12
-3
@@ -55,6 +55,15 @@
|
||||
|
||||
#include "sqlite3ext.h"
|
||||
|
||||
#ifndef deliberate_fall_through
|
||||
/* Quiet some compilers about some of our intentional code. */
|
||||
# if GCC_VERSION>=7000000
|
||||
# define deliberate_fall_through __attribute__((fallthrough));
|
||||
# else
|
||||
# define deliberate_fall_through
|
||||
# endif
|
||||
#endif
|
||||
|
||||
SQLITE_EXTENSION_INIT1;
|
||||
|
||||
#define PC 0x80 /* pad character */
|
||||
@@ -165,15 +174,15 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
||||
case ND:
|
||||
/* Treat dark non-digits as pad, but they terminate decode too. */
|
||||
ncIn = 0;
|
||||
/* fall thru */
|
||||
deliberate_fall_through;
|
||||
case WS:
|
||||
/* Treat whitespace as pad and terminate this group.*/
|
||||
nti = nac;
|
||||
/* fall thru */
|
||||
deliberate_fall_through;
|
||||
case PC:
|
||||
bdp = 0;
|
||||
--nbo;
|
||||
/* fall thru */
|
||||
deliberate_fall_through;
|
||||
default: /* bdp is the digit value. */
|
||||
qv = qv<<6 | bdp;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -1285,7 +1285,7 @@ static int zipfileFilter(
|
||||
}
|
||||
|
||||
if( 0==pTab->pWriteFd && 0==bInMemory ){
|
||||
pCsr->pFile = fopen(zFile, "rb");
|
||||
pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
|
||||
if( pCsr->pFile==0 ){
|
||||
zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
|
||||
rc = SQLITE_ERROR;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
_malloc
|
||||
_free
|
||||
_realloc
|
||||
_sqlite3_aggregate_context
|
||||
_sqlite3_auto_extension
|
||||
_sqlite3_bind_blob
|
||||
_sqlite3_bind_double
|
||||
_sqlite3_bind_int
|
||||
@@ -10,6 +14,7 @@ _sqlite3_bind_pointer
|
||||
_sqlite3_bind_text
|
||||
_sqlite3_busy_handler
|
||||
_sqlite3_busy_timeout
|
||||
_sqlite3_cancel_auto_extension
|
||||
_sqlite3_changes
|
||||
_sqlite3_changes64
|
||||
_sqlite3_clear_bindings
|
||||
@@ -26,9 +31,11 @@ _sqlite3_column_name
|
||||
_sqlite3_column_text
|
||||
_sqlite3_column_type
|
||||
_sqlite3_column_value
|
||||
_sqlite3_commit_hook
|
||||
_sqlite3_compileoption_get
|
||||
_sqlite3_compileoption_used
|
||||
_sqlite3_complete
|
||||
_sqlite3_context_db_handle
|
||||
_sqlite3_create_collation
|
||||
_sqlite3_create_collation_v2
|
||||
_sqlite3_create_function
|
||||
@@ -72,11 +79,18 @@ _sqlite3_open_v2
|
||||
_sqlite3_overload_function
|
||||
_sqlite3_prepare_v2
|
||||
_sqlite3_prepare_v3
|
||||
_sqlite3_preupdate_blobwrite
|
||||
_sqlite3_preupdate_count
|
||||
_sqlite3_preupdate_depth
|
||||
_sqlite3_preupdate_hook
|
||||
_sqlite3_preupdate_new
|
||||
_sqlite3_preupdate_old
|
||||
_sqlite3_progress_handler
|
||||
_sqlite3_randomness
|
||||
_sqlite3_realloc
|
||||
_sqlite3_realloc64
|
||||
_sqlite3_reset
|
||||
_sqlite3_reset_auto_extension
|
||||
_sqlite3_result_blob
|
||||
_sqlite3_result_double
|
||||
_sqlite3_result_error
|
||||
@@ -91,6 +105,7 @@ _sqlite3_result_subtype
|
||||
_sqlite3_result_text
|
||||
_sqlite3_result_zeroblob
|
||||
_sqlite3_result_zeroblob64
|
||||
_sqlite3_rollback_hook
|
||||
_sqlite3_serialize
|
||||
_sqlite3_set_authorizer
|
||||
_sqlite3_set_auxdata
|
||||
@@ -113,6 +128,7 @@ _sqlite3_total_changes
|
||||
_sqlite3_total_changes64
|
||||
_sqlite3_trace_v2
|
||||
_sqlite3_txn_state
|
||||
_sqlite3_update_hook
|
||||
_sqlite3_uri_boolean
|
||||
_sqlite3_uri_int64
|
||||
_sqlite3_uri_key
|
||||
@@ -143,6 +159,45 @@ _sqlite3_vtab_in_next
|
||||
_sqlite3_vtab_nochange
|
||||
_sqlite3_vtab_on_conflict
|
||||
_sqlite3_vtab_rhs_value
|
||||
_malloc
|
||||
_free
|
||||
_realloc
|
||||
_sqlite3changegroup_add
|
||||
_sqlite3changegroup_add_strm
|
||||
_sqlite3changegroup_delete
|
||||
_sqlite3changegroup_new
|
||||
_sqlite3changegroup_output
|
||||
_sqlite3changegroup_output_strm
|
||||
_sqlite3changeset_apply
|
||||
_sqlite3changeset_apply_strm
|
||||
_sqlite3changeset_apply_v2
|
||||
_sqlite3changeset_apply_v2_strm
|
||||
_sqlite3changeset_concat
|
||||
_sqlite3changeset_concat_strm
|
||||
_sqlite3changeset_conflict
|
||||
_sqlite3changeset_finalize
|
||||
_sqlite3changeset_fk_conflicts
|
||||
_sqlite3changeset_invert
|
||||
_sqlite3changeset_invert_strm
|
||||
_sqlite3changeset_new
|
||||
_sqlite3changeset_next
|
||||
_sqlite3changeset_old
|
||||
_sqlite3changeset_op
|
||||
_sqlite3changeset_pk
|
||||
_sqlite3changeset_start
|
||||
_sqlite3changeset_start_strm
|
||||
_sqlite3changeset_start_v2
|
||||
_sqlite3changeset_start_v2_strm
|
||||
_sqlite3session_attach
|
||||
_sqlite3session_changeset
|
||||
_sqlite3session_changeset_size
|
||||
_sqlite3session_changeset_strm
|
||||
_sqlite3session_config
|
||||
_sqlite3session_create
|
||||
_sqlite3session_delete
|
||||
_sqlite3session_diff
|
||||
_sqlite3session_enable
|
||||
_sqlite3session_indirect
|
||||
_sqlite3session_isempty
|
||||
_sqlite3session_memory_used
|
||||
_sqlite3session_object_config
|
||||
_sqlite3session_patchset
|
||||
_sqlite3session_patchset_strm
|
||||
_sqlite3session_table_filter
|
||||
|
||||
+772
-330
File diff suppressed because it is too large
Load Diff
@@ -72,7 +72,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
wasm.installFunction('i(ippp)', function(t,c,p,x){
|
||||
if(capi.SQLITE_TRACE_STMT===t){
|
||||
// x == SQL, p == sqlite3_stmt*
|
||||
console.log("SQL TRACE #"+(++this.counter),
|
||||
console.log("SQL TRACE #"+(++this.counter)+' via sqlite3@'+c+':',
|
||||
wasm.cstrToJs(x));
|
||||
}
|
||||
}.bind({counter: 0}));
|
||||
@@ -161,7 +161,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
capi.sqlite3_extended_result_codes(pDb, 1);
|
||||
if(flagsStr.indexOf('t')>=0){
|
||||
capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT,
|
||||
__dbTraceToConsole, 0);
|
||||
__dbTraceToConsole, pDb);
|
||||
}
|
||||
}catch( e ){
|
||||
if( pDb ) capi.sqlite3_close_v2(pDb);
|
||||
@@ -463,23 +463,21 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
};
|
||||
|
||||
/**
|
||||
Internal impl of the DB.selectArray() and
|
||||
Internal impl of the DB.selectValue(), selectArray(), and
|
||||
selectObject() methods.
|
||||
*/
|
||||
const __selectFirstRow = (db, sql, bind, getArg)=>{
|
||||
let stmt, rc;
|
||||
const __selectFirstRow = (db, sql, bind, ...getArgs)=>{
|
||||
const stmt = db.prepare(sql);
|
||||
try {
|
||||
stmt = db.prepare(sql).bind(bind);
|
||||
if(stmt.step()) rc = stmt.get(getArg);
|
||||
return stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined;
|
||||
}finally{
|
||||
if(stmt) stmt.finalize();
|
||||
stmt.finalize();
|
||||
}
|
||||
return rc;
|
||||
};
|
||||
|
||||
/**
|
||||
Internal impl of the DB.selectArrays() and
|
||||
selectObjects() methods.
|
||||
Internal impl of the DB.selectArrays() and selectObjects()
|
||||
methods.
|
||||
*/
|
||||
const __selectAll =
|
||||
(db, sql, bind, rowMode)=>db.exec({
|
||||
@@ -1083,15 +1081,31 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Throws on error (e.g. malformed SQL).
|
||||
*/
|
||||
selectValue: function(sql,bind,asType){
|
||||
let stmt, rc;
|
||||
return __selectFirstRow(this, sql, bind, 0, asType);
|
||||
},
|
||||
|
||||
/**
|
||||
Runs the given query and returns an array of the values from
|
||||
the first result column of each row of the result set. The 2nd
|
||||
argument is an optional value for use in a single-argument call
|
||||
to Stmt.bind(). The 3rd argument may be any value suitable for
|
||||
use as the 2nd argument to Stmt.get(). If a 3rd argument is
|
||||
desired but no bind data are needed, pass `undefined` for the 2nd
|
||||
argument.
|
||||
|
||||
If there are no result rows, an empty array is returned.
|
||||
*/
|
||||
selectValues: function(sql,bind,asType){
|
||||
const stmt = this.prepare(sql), rc = [];
|
||||
try {
|
||||
stmt = this.prepare(sql).bind(bind);
|
||||
if(stmt.step()) rc = stmt.get(0,asType);
|
||||
stmt.bind(bind);
|
||||
while(stmt.step()) rc.push(stmt.get(0,asType));
|
||||
}finally{
|
||||
if(stmt) stmt.finalize();
|
||||
stmt.finalize();
|
||||
}
|
||||
return rc;
|
||||
},
|
||||
|
||||
/**
|
||||
Prepares the given SQL, step()s it one time, and returns an
|
||||
array containing the values of the first result row. If it has
|
||||
@@ -1147,7 +1161,10 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
/**
|
||||
Returns the number of currently-opened Stmt handles for this db
|
||||
handle, or 0 if this DB instance is closed.
|
||||
handle, or 0 if this DB instance is closed. Note that only
|
||||
handles prepared via this.prepare() are counted, and not
|
||||
handles prepared using capi.sqlite3_prepare_v3() (or
|
||||
equivalent).
|
||||
*/
|
||||
openStatementCount: function(){
|
||||
return this.pointer ? Object.keys(__stmtMap.get(this)).length : 0;
|
||||
@@ -1163,9 +1180,25 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Note that transactions may not be nested, so this will throw if
|
||||
it is called recursively. For nested transactions, use the
|
||||
savepoint() method or manually manage SAVEPOINTs using exec().
|
||||
|
||||
If called with 2 arguments, the first must be a keyword which
|
||||
is legal immediately after a BEGIN statement, e.g. one of
|
||||
"DEFERRED", "IMMEDIATE", or "EXCLUSIVE". Though the exact list
|
||||
of supported keywords is not hard-coded here, in order to be
|
||||
future-compatible, if the argument does not look like a single
|
||||
keyword then an exception is triggered with a description of
|
||||
the problem.
|
||||
*/
|
||||
transaction: function(callback){
|
||||
affirmDbOpen(this).exec("BEGIN");
|
||||
transaction: function(/* [beginQualifier,] */callback){
|
||||
let opener = 'BEGIN';
|
||||
if(arguments.length>1){
|
||||
if(/[^a-zA-Z]/.test(arguments[0])){
|
||||
toss3(capi.SQLITE_MISUSE, "Invalid argument for BEGIN qualifier.");
|
||||
}
|
||||
opener += ' '+arguments[0];
|
||||
callback = arguments[1];
|
||||
}
|
||||
affirmDbOpen(this).exec(opener);
|
||||
try {
|
||||
const rc = callback(this);
|
||||
this.exec("COMMIT");
|
||||
@@ -1229,9 +1262,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
if(wasm.bigIntEnabled) return t;
|
||||
/* else fall through */
|
||||
default:
|
||||
//console.log("isSupportedBindType",t,v);
|
||||
return (util.isBindableTypedArray(v) || (v instanceof ArrayBuffer))
|
||||
? BindTypes.blob : undefined;
|
||||
return util.isBindableTypedArray(v) ? BindTypes.blob : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1449,7 +1480,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
blob binding).
|
||||
|
||||
- Uint8Array, Int8Array, and ArrayBuffer instances are bound as
|
||||
blobs. (TODO? binding the other TypedArray types.)
|
||||
blobs.
|
||||
|
||||
If passed an array, each element of the array is bound at
|
||||
the parameter index equal to the array index plus 1
|
||||
|
||||
@@ -321,7 +321,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
};
|
||||
|
||||
/**
|
||||
Returns v if v appears to be one of our bind()-able TypedArray
|
||||
Returns true if v appears to be one of our bind()-able TypedArray
|
||||
types: Uint8Array or Int8Array or ArrayBuffer. Support for
|
||||
TypedArrays with element sizes >1 is a potential TODO just
|
||||
waiting on a use case to justify them. Until then, their `buffer`
|
||||
@@ -377,7 +377,11 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
returned. Else v is returned as-is.
|
||||
*/
|
||||
const flexibleString = function(v){
|
||||
if(isSQLableTypedArray(v)) return typedArrayToString(v);
|
||||
if(isSQLableTypedArray(v)){
|
||||
return typedArrayToString(
|
||||
(v instanceof ArrayBuffer) ? new Uint8Array(v) : v
|
||||
);
|
||||
}
|
||||
else if(Array.isArray(v)) return v.join("");
|
||||
else if(wasm.isPtr(v)) v = wasm.cstrToJs(v);
|
||||
return v;
|
||||
@@ -405,6 +409,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
}else{
|
||||
super("Allocation failed.");
|
||||
}
|
||||
this.resultCode = capi.SQLITE_NOMEM;
|
||||
this.name = 'WasmAllocError';
|
||||
}
|
||||
};
|
||||
@@ -657,8 +662,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
terminated with a 0 byte.
|
||||
|
||||
In usage (1), the 2nd argument must be of type string,
|
||||
Uint8Array, or Int8Array (either of which is assumed to
|
||||
hold SQL). If it is, this function assumes case (1) and
|
||||
Uint8Array, Int8Array, or ArrayBuffer (all of which are assumed
|
||||
to hold SQL). If it is, this function assumes case (1) and
|
||||
calls the underyling C function with the equivalent of:
|
||||
|
||||
(pDb, sqlAsString, -1, prepFlags, ppStmt, null)
|
||||
@@ -1019,12 +1024,20 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
to the memory. On error, returns throws a WasmAllocError. The
|
||||
memory must eventually be released using restore().
|
||||
|
||||
If n is a string, it must be a WASM "IR" value in the set
|
||||
accepted by wasm.sizeofIR(), which is mapped to the size of
|
||||
that data type. If passed a string not in that set, it throws a
|
||||
WasmAllocError.
|
||||
|
||||
This method always adjusts the given value to be a multiple
|
||||
of 8 bytes because failing to do so can lead to incorrect
|
||||
results when reading and writing 64-bit values from/to the WASM
|
||||
heap. Similarly, the returned address is always 8-byte aligned.
|
||||
*/
|
||||
alloc: (n)=>{
|
||||
alloc: function(n){
|
||||
if('string'===typeof n && !(n = wasm.sizeofIR(n))){
|
||||
WasmAllocError.toss("Invalid value for pstack.alloc(",arguments[0],")");
|
||||
}
|
||||
return wasm.exports.sqlite3_wasm_pstack_alloc(n)
|
||||
|| WasmAllocError.toss("Could not allocate",n,
|
||||
"bytes from the pstack.");
|
||||
@@ -1034,6 +1047,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
returns the addresses as an array of n element, each holding
|
||||
the address of one chunk.
|
||||
|
||||
sz may optionally be an IR string accepted by wasm.sizeofIR().
|
||||
|
||||
Throws a WasmAllocError if allocation fails.
|
||||
|
||||
Example:
|
||||
@@ -1042,7 +1057,10 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
const [p1, p2, p3] = wasm.pstack.allocChunks(3,4);
|
||||
```
|
||||
*/
|
||||
allocChunks: (n,sz)=>{
|
||||
allocChunks: function(n,sz){
|
||||
if('string'===typeof sz && !(sz = wasm.sizeofIR(sz))){
|
||||
WasmAllocError.toss("Invalid size value for allocChunks(",arguments[1],")");
|
||||
}
|
||||
const mem = wasm.pstack.alloc(n * sz);
|
||||
const rc = [];
|
||||
let i = 0, offset = 0;
|
||||
@@ -1749,8 +1767,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
argument of sqlite3_value_to_js(). If the sqlite3_column_value()
|
||||
returns NULL (e.g. because the column index is out of range),
|
||||
this function returns `undefined`, regardless of the 3rd
|
||||
argument. 3rd argument is falsy and conversion fails, `undefined`
|
||||
will be returned.
|
||||
argument. If the 3rd argument is falsy and conversion fails,
|
||||
`undefined` will be returned.
|
||||
|
||||
Note that sqlite3_column_value() returns an "unprotected" value
|
||||
object, but in a single-threaded environment (like this one)
|
||||
@@ -1761,6 +1779,56 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
return (0===v) ? undefined : capi.sqlite3_value_to_js(v, throwIfCannotConvert);
|
||||
};
|
||||
|
||||
/**
|
||||
Internal impl of sqlite3_preupdate_new/old_js() and
|
||||
sqlite3changeset_new/old_js().
|
||||
*/
|
||||
const __newOldValue = function(pObj, iCol, impl){
|
||||
impl = capi[impl];
|
||||
if(!this.ptr) this.ptr = wasm.allocPtr();
|
||||
else wasm.pokePtr(this.ptr, 0);
|
||||
const rc = impl(pObj, iCol, this.ptr);
|
||||
if(rc) return SQLite3Error.toss(rc,arguments[2]+"() failed with code "+rc);
|
||||
const pv = wasm.peekPtr(this.ptr);
|
||||
return pv ? capi.sqlite3_value_to_js( pv, true ) : undefined;
|
||||
}.bind(Object.create(null));
|
||||
|
||||
/**
|
||||
A wrapper around sqlite3_preupdate_new() which fetches the
|
||||
sqlite3_value at the given index and returns the result of
|
||||
passing it to sqlite3_value_to_js(). Throws on error.
|
||||
*/
|
||||
capi.sqlite3_preupdate_new_js =
|
||||
(pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_new');
|
||||
|
||||
/**
|
||||
The sqlite3_preupdate_old() counterpart of
|
||||
sqlite3_preupdate_new_js(), with an identical interface.
|
||||
*/
|
||||
capi.sqlite3_preupdate_old_js =
|
||||
(pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_old');
|
||||
|
||||
/**
|
||||
A wrapper around sqlite3changeset_new() which fetches the
|
||||
sqlite3_value at the given index and returns the result of
|
||||
passing it to sqlite3_value_to_js(). Throws on error.
|
||||
|
||||
If sqlite3changeset_new() succeeds but has no value to report,
|
||||
this function returns the undefined value, noting that undefined
|
||||
is a valid conversion from an `sqlite3_value`, so is unambiguous.
|
||||
*/
|
||||
capi.sqlite3changeset_new_js =
|
||||
(pChangesetIter, iCol) => __newOldValue(pChangesetIter, iCol,
|
||||
'sqlite3changeset_new');
|
||||
|
||||
/**
|
||||
The sqlite3changeset_old() counterpart of
|
||||
sqlite3changeset_new_js(), with an identical interface.
|
||||
*/
|
||||
capi.sqlite3changeset_old_js =
|
||||
(pChangesetIter, iCol)=>__newOldValue(pChangesetIter, iCol,
|
||||
'sqlite3changeset_old');
|
||||
|
||||
/* The remainder of the API will be set up in later steps. */
|
||||
const sqlite3 = {
|
||||
WasmAllocError: WasmAllocError,
|
||||
|
||||
@@ -158,15 +158,6 @@
|
||||
|
||||
bigIntEnabled: bool. True if BigInt support is enabled.
|
||||
|
||||
wasmfsOpfsDir: path prefix, if any, _intended_ for use with
|
||||
WASMFS OPFS persistent storage.
|
||||
|
||||
wasmfsOpfsEnabled: true if persistent storage is enabled in the
|
||||
current environment. Only files stored under wasmfsOpfsDir
|
||||
will persist using that mechanism, however. It is legal to use
|
||||
the non-WASMFS OPFS VFS to open a database via a URI-style
|
||||
db filename.
|
||||
|
||||
vfsList: result of sqlite3.capi.sqlite3_js_vfs_list()
|
||||
}
|
||||
}
|
||||
@@ -449,7 +440,6 @@ sqlite3.initWorker1API = function(){
|
||||
toss("Throwing because of simulateError flag.");
|
||||
}
|
||||
const rc = Object.create(null);
|
||||
const pDir = sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||
let byteArray, pVfs;
|
||||
oargs.vfs = args.vfs;
|
||||
if(isSpecialDbFilename(args.filename)){
|
||||
@@ -482,8 +472,7 @@ sqlite3.initWorker1API = function(){
|
||||
}
|
||||
const db = wState.open(oargs);
|
||||
rc.filename = db.filename;
|
||||
rc.persistent = (!!pDir && db.filename.startsWith(pDir+'/'))
|
||||
|| !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
|
||||
rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs");
|
||||
rc.dbId = getDbId(db);
|
||||
rc.vfs = db.dbVfsName();
|
||||
return rc;
|
||||
@@ -558,11 +547,10 @@ sqlite3.initWorker1API = function(){
|
||||
'config-get': function(){
|
||||
const rc = Object.create(null), src = sqlite3.config;
|
||||
[
|
||||
'wasmfsOpfsDir', 'bigIntEnabled'
|
||||
'bigIntEnabled'
|
||||
].forEach(function(k){
|
||||
if(Object.getOwnPropertyDescriptor(src, k)) rc[k] = src[k];
|
||||
});
|
||||
rc.wasmfsOpfsEnabled = !!sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||
rc.version = sqlite3.version;
|
||||
rc.vfsList = sqlite3.capi.sqlite3_js_vfs_list();
|
||||
rc.opfsEnabled = !!sqlite3.opfs;
|
||||
|
||||
@@ -99,15 +99,21 @@
|
||||
#ifndef SQLITE_ENABLE_FTS4
|
||||
# define SQLITE_ENABLE_FTS4 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_MATH_FUNCTIONS
|
||||
# define SQLITE_ENABLE_MATH_FUNCTIONS 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
# define SQLITE_ENABLE_OFFSET_SQL_FUNC 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
# define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_RTREE
|
||||
# define SQLITE_ENABLE_RTREE 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_SESSION
|
||||
# define SQLITE_ENABLE_SESSION 1
|
||||
#endif
|
||||
#ifndef SQLITE_ENABLE_STMTVTAB
|
||||
# define SQLITE_ENABLE_STMTVTAB 1
|
||||
#endif
|
||||
@@ -323,11 +329,13 @@ SQLITE_WASM_KEEP int sqlite3_wasm_pstack_quota(void){
|
||||
*/
|
||||
SQLITE_WASM_KEEP
|
||||
int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){
|
||||
if( 0!=zMsg ){
|
||||
const int nMsg = sqlite3Strlen30(zMsg);
|
||||
sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
|
||||
}else{
|
||||
sqlite3ErrorWithMsg(db, err_code, NULL);
|
||||
if( db!=0 ){
|
||||
if( 0!=zMsg ){
|
||||
const int nMsg = sqlite3Strlen30(zMsg);
|
||||
sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg);
|
||||
}else{
|
||||
sqlite3ErrorWithMsg(db, err_code, NULL);
|
||||
}
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
@@ -456,6 +464,24 @@ const char * sqlite3_wasm_enum_json(void){
|
||||
/* SQLITE_STATIC/TRANSIENT need to be handled explicitly as
|
||||
** integers to avoid casting-related warnings. */
|
||||
out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1");
|
||||
outf(",\"SQLITE_WASM_DEALLOC\": %lld",
|
||||
(sqlite3_int64)(sqlite3_free));
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(changeset){
|
||||
DefInt(SQLITE_CHANGESETSTART_INVERT);
|
||||
DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
|
||||
DefInt(SQLITE_CHANGESETAPPLY_INVERT);
|
||||
|
||||
DefInt(SQLITE_CHANGESET_DATA);
|
||||
DefInt(SQLITE_CHANGESET_NOTFOUND);
|
||||
DefInt(SQLITE_CHANGESET_CONFLICT);
|
||||
DefInt(SQLITE_CHANGESET_CONSTRAINT);
|
||||
DefInt(SQLITE_CHANGESET_FOREIGN_KEY);
|
||||
|
||||
DefInt(SQLITE_CHANGESET_OMIT);
|
||||
DefInt(SQLITE_CHANGESET_REPLACE);
|
||||
DefInt(SQLITE_CHANGESET_ABORT);
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(config){
|
||||
@@ -794,6 +820,11 @@ const char * sqlite3_wasm_enum_json(void){
|
||||
DefInt(SQLITE_DESERIALIZE_RESIZEABLE);
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(session){
|
||||
DefInt(SQLITE_SESSION_CONFIG_STRMSIZE);
|
||||
DefInt(SQLITE_SESSION_OBJCONFIG_SIZE);
|
||||
} _DefGroup;
|
||||
|
||||
DefGroup(sqlite3Status){
|
||||
DefInt(SQLITE_STATUS_MEMORY_USED);
|
||||
DefInt(SQLITE_STATUS_PAGECACHE_USED);
|
||||
@@ -1562,6 +1593,36 @@ int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){
|
||||
return sqlite3_config(op, arg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Pending removal after verification of a workaround discussed in the
|
||||
// forum post linked to below.
|
||||
/*
|
||||
** This function is NOT part of the sqlite3 public API. It is strictly
|
||||
** for use by the sqlite project's own JS/WASM bindings.
|
||||
**
|
||||
** Returns a pointer to sqlite3_free(). In compliant browsers the
|
||||
** return value, when passed to sqlite3.wasm.exports.functionEntry(),
|
||||
** must resolve to the same function as
|
||||
** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where
|
||||
** sqlite3 is exported globally, the following must be true:
|
||||
**
|
||||
** ```
|
||||
** sqlite3.wasm.functionEntry(
|
||||
** sqlite3.wasm.exports.sqlite3_wasm_ptr_to_sqlite3_free()
|
||||
** ) === sqlite3.wasm.exports.sqlite3_free
|
||||
** ```
|
||||
**
|
||||
** Using a function to return this pointer, as opposed to exporting it
|
||||
** via sqlite3_wasm_enum_json(), is an attempt to work around a
|
||||
** Safari-specific quirk covered at
|
||||
** https://sqlite.org/forum/info/e5b20e1feb37a19a.
|
||||
**/
|
||||
SQLITE_WASM_KEEP
|
||||
void * sqlite3_wasm_ptr_to_sqlite3_free(void){
|
||||
return (void*)sqlite3_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS)
|
||||
#include <emscripten/wasmfs.h>
|
||||
|
||||
|
||||
@@ -41,9 +41,6 @@
|
||||
//console.warn("worker1 theJs =",theJs);
|
||||
importScripts(theJs);
|
||||
sqlite3InitModule().then((sqlite3)=>{
|
||||
if(sqlite3.capi.sqlite3_wasmfs_opfs_dir){
|
||||
sqlite3.capi.sqlite3_wasmfs_opfs_dir();
|
||||
}
|
||||
sqlite3.initWorker1API();
|
||||
});
|
||||
})();
|
||||
|
||||
+131
-43
@@ -246,6 +246,25 @@ self.WhWasmUtilInstaller = function(target){
|
||||
cache.utf8Decoder = new TextDecoder();
|
||||
cache.utf8Encoder = new TextEncoder('utf-8');
|
||||
|
||||
/**
|
||||
For the given IR-like string in the set ('i8', 'i16', 'i32',
|
||||
'f32', 'float', 'i64', 'f64', 'double', '*'), or any string value
|
||||
ending in '*', returns the sizeof for that value
|
||||
(target.ptrSizeof in the latter case). For any other value, it
|
||||
returns the undefined value.
|
||||
*/
|
||||
target.sizeofIR = (n)=>{
|
||||
switch(n){
|
||||
case 'i8': return 1;
|
||||
case 'i16': return 2;
|
||||
case 'i32': case 'f32': case 'float': return 4;
|
||||
case 'i64': case 'f64': case 'double': return 8;
|
||||
case '*': return ptrSizeof;
|
||||
default:
|
||||
return (''+n).endsWith('*') ? ptrSizeof : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
If (cache.heapSize !== cache.memory.buffer.byteLength), i.e. if
|
||||
the heap has grown since the last call, updates cache.HEAPxyz.
|
||||
@@ -1480,7 +1499,7 @@ self.WhWasmUtilInstaller = function(target){
|
||||
*/
|
||||
const AbstractArgAdapter = class {
|
||||
constructor(opt){
|
||||
this.name = opt.name;
|
||||
this.name = opt.name || 'unnamed adapter';
|
||||
}
|
||||
/**
|
||||
Gets called via xWrap() to "convert" v to whatever type
|
||||
@@ -1496,7 +1515,7 @@ self.WhWasmUtilInstaller = function(target){
|
||||
types are indeterminate, whereas the LHS values will be
|
||||
WASM-compatible values by the time this is called.
|
||||
*/
|
||||
convertArg(v,argIndex,argv){
|
||||
convertArg(v,argv,argIndex){
|
||||
toss("AbstractArgAdapter must be subclassed.");
|
||||
}
|
||||
};
|
||||
@@ -1541,24 +1560,42 @@ self.WhWasmUtilInstaller = function(target){
|
||||
context. This mode is the default if bindScope is _not_ set
|
||||
but a property named contextKey (described below) is.
|
||||
|
||||
- 'permanent': the function is installed and left there
|
||||
forever. There is no way to recover its pointer address
|
||||
later on.
|
||||
|
||||
- callProxy (function): if set, this must be a function which
|
||||
will act as a proxy for any "converted" JS function. It is
|
||||
passed the being-converted function value and must return
|
||||
either that function or a function which acts on its
|
||||
behalf. The returned function will be the one which gets
|
||||
installed into the WASM function table. The proxy must perform
|
||||
any required argument conversion (noting that it will be called
|
||||
from C code, so will receive C-format arguments) before passing
|
||||
them on to the being-converted function. Whether or not the
|
||||
proxy itself must return a value depends on the context. If it
|
||||
does, it must be a WASM-friendly value, as it will be returning
|
||||
from a call made from native code.
|
||||
|
||||
- contextKey (function): is only used if bindScope is 'context'
|
||||
or if bindScope is not set and this function is, in which case
|
||||
'context' is assumed. This function gets passed
|
||||
(argIndex,argv), where argIndex is the index of _this_ function
|
||||
pointer in its _wrapping_ function's arguments and argv is the
|
||||
_current_ still-being-xWrap()-processed args array. All
|
||||
arguments to the left of argIndex will have been processed by
|
||||
xWrap() by the time this is called. argv[argIndex] will be the
|
||||
value the user passed in to the xWrap()'d function for the
|
||||
argument this FuncPtrAdapter is mapped to. Arguments to the
|
||||
right of argv[argIndex] will not yet have been converted before
|
||||
this is called. The function must return a key which uniquely
|
||||
'context' is assumed. This function gets bound to this object,
|
||||
so its "this" is this object. It gets passed (argv,argIndex),
|
||||
where argIndex is the index of _this_ function pointer in its
|
||||
_wrapping_ function's arguments and argv is the _current_
|
||||
still-being-xWrap()-processed args array. All arguments to the
|
||||
left of argIndex will have been processed by xWrap() by the
|
||||
time this is called. argv[argIndex] will be the value the user
|
||||
passed in to the xWrap()'d function for the argument this
|
||||
FuncPtrAdapter is mapped to. Arguments to the right of
|
||||
argv[argIndex] will not yet have been converted before this is
|
||||
called. The function must return a key which uniquely
|
||||
identifies this function mapping context for _this_
|
||||
FuncPtrAdapter instance (other instances are not considered),
|
||||
taking into account that C functions often take some sort of
|
||||
state object as one or more of their arguments. As an example,
|
||||
if the xWrap()'d function takes `(int,T*,functionPtr,X*)` and
|
||||
this FuncPtrAdapter is the argv[2]nd arg, contextKey(2,argv)
|
||||
this FuncPtrAdapter is the argv[2]nd arg, contextKey(argv,2)
|
||||
might return 'T@'+argv[1], or even just argv[1]. Note,
|
||||
however, that the (X*) argument will not yet have been
|
||||
processed by the time this is called and should not be used as
|
||||
@@ -1570,42 +1607,77 @@ self.WhWasmUtilInstaller = function(target){
|
||||
use their pointers in the key because most C-strings in this
|
||||
constellation are transient.
|
||||
|
||||
Yes, that ^^^ is a bit awkward, but it's what we have.
|
||||
Yes, that ^^^ is quite awkward, but it's what we have.
|
||||
|
||||
The constructor only saves the above state for later, and does
|
||||
not actually bind any functions. Its convertArg() method is
|
||||
called via xWrap() to perform any bindings.
|
||||
|
||||
Shortcomings: function pointers which include C-string arguments
|
||||
may still need a level of hand-written wrappers around them,
|
||||
depending on how they're used, in order to provide the client
|
||||
with JS strings.
|
||||
Shortcomings:
|
||||
|
||||
- These "reverse" bindings, i.e. calling into a JS-defined
|
||||
function from a WASM-defined function (the generated proxy
|
||||
wrapper), lack all type conversion support. That means, for
|
||||
example, that...
|
||||
|
||||
- Function pointers which include C-string arguments may still
|
||||
need a level of hand-written wrappers around them, depending on
|
||||
how they're used, in order to provide the client with JS
|
||||
strings. Alternately, clients will need to perform such conversions
|
||||
on their own, e.g. using cstrtojs(). Or maybe we can find a way
|
||||
to perform such conversions here, via addition of an xWrap()-style
|
||||
function signature to the options argument.
|
||||
*/
|
||||
xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter {
|
||||
constructor(opt) {
|
||||
super(opt);
|
||||
if(xArg.FuncPtrAdapter.warnOnUse){
|
||||
console.warn('xArg.FuncPtrAdapter is an internal-only API',
|
||||
'and is not intended to be invoked from',
|
||||
'client-level code. Invoked with:',opt);
|
||||
}
|
||||
this.signature = opt.signature;
|
||||
if(!opt.bindScope && (opt.contextKey instanceof Function)){
|
||||
opt.bindScope = 'context';
|
||||
}else if(FuncPtrAdapter.bindScopes.indexOf(opt.bindScope)<0){
|
||||
if(opt.contextKey instanceof Function){
|
||||
this.contextKey = opt.contextKey;
|
||||
if(!opt.bindScope) opt.bindScope = 'context';
|
||||
}
|
||||
this.bindScope = opt.bindScope
|
||||
|| toss("FuncPtrAdapter options requires a bindScope (explicit or implied).");
|
||||
if(FuncPtrAdapter.bindScopes.indexOf(opt.bindScope)<0){
|
||||
toss("Invalid options.bindScope ("+opt.bindMod+") for FuncPtrAdapter. "+
|
||||
"Expecting one of: ("+FuncPtrAdapter.bindScopes.join(', ')+')');
|
||||
}
|
||||
this.bindScope = opt.bindScope;
|
||||
if(opt.contextKey) this.contextKey = opt.contextKey /*else inherit one*/;
|
||||
this.isTransient = 'transient'===this.bindScope;
|
||||
this.isContext = 'context'===this.bindScope;
|
||||
if( ('singleton'===this.bindScope) ) this.singleton = [];
|
||||
else this.singleton = undefined;
|
||||
this.isPermanent = 'permanent'===this.bindScope;
|
||||
this.singleton = ('singleton'===this.bindScope) ? [] : undefined;
|
||||
//console.warn("FuncPtrAdapter()",opt,this);
|
||||
this.callProxy = (opt.callProxy instanceof Function)
|
||||
? opt.callProxy : undefined;
|
||||
}
|
||||
|
||||
/** If true, the constructor emits a warning. The intent is that
|
||||
this be set to true after bootstrapping of the higher-level
|
||||
client library is complete, to warn downstream clients that
|
||||
they shouldn't be relying on this implemenation detail which
|
||||
does not have a stable interface. */
|
||||
static warnOnUse = false;
|
||||
|
||||
/** If true, convertArg() will FuncPtrAdapter.debugOut() when it
|
||||
(un)installs a function binding to/from WASM. Note that
|
||||
deinstallation of bindScope=transient bindings happens
|
||||
via scopedAllocPop() so will not be output. */
|
||||
static debugFuncInstall = false;
|
||||
|
||||
/** Function used for debug output. */
|
||||
static debugOut = console.debug.bind(console);
|
||||
|
||||
static bindScopes = [
|
||||
'transient', 'context', 'singleton'
|
||||
'transient', 'context', 'singleton', 'permanent'
|
||||
];
|
||||
|
||||
/* Dummy impl. Overwritten per-instance as needed. */
|
||||
contextKey(argIndex,argv){
|
||||
contextKey(argv,argIndex){
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1638,18 +1710,28 @@ self.WhWasmUtilInstaller = function(target){
|
||||
See the parent class's convertArg() docs for details on what
|
||||
exactly the 2nd and 3rd arguments are.
|
||||
*/
|
||||
convertArg(v,argIndex,argv){
|
||||
//console.warn("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
|
||||
convertArg(v,argv,argIndex){
|
||||
//FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.signature,this.transient,v);
|
||||
let pair = this.singleton;
|
||||
if(!pair && this.isContext){
|
||||
pair = this.contextMap(this.contextKey(argIndex, argv));
|
||||
pair = this.contextMap(this.contextKey(argv,argIndex));
|
||||
}
|
||||
if(pair && pair[0]===v) return pair[1];
|
||||
if(v instanceof Function){
|
||||
/* Install a WASM binding and return its pointer. */
|
||||
if(this.callProxy) v = this.callProxy(v);
|
||||
const fp = __installFunction(v, this.signature, this.isTransient);
|
||||
if(FuncPtrAdapter.debugFuncInstall){
|
||||
FuncPtrAdapter.debugOut("FuncPtrAdapter installed", this,
|
||||
this.contextKey(argv,argIndex), '@'+fp, v);
|
||||
}
|
||||
if(pair){
|
||||
/* Replace existing stashed mapping */
|
||||
if(pair[1]){
|
||||
if(FuncPtrAdapter.debugFuncInstall){
|
||||
FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
|
||||
this.contextKey(argv,argIndex), '@'+pair[1], v);
|
||||
}
|
||||
try{target.uninstallFunction(pair[1])}
|
||||
catch(e){/*ignored*/}
|
||||
}
|
||||
@@ -1660,10 +1742,13 @@ self.WhWasmUtilInstaller = function(target){
|
||||
}else if(target.isPtr(v) || null===v || undefined===v){
|
||||
if(pair && pair[1] && pair[1]!==v){
|
||||
/* uninstall stashed mapping and replace stashed mapping with v. */
|
||||
//console.warn("FuncPtrAdapter is uninstalling function", this.contextKey(argIndex,argv),v);
|
||||
if(FuncPtrAdapter.debugFuncInstall){
|
||||
FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this,
|
||||
this.contextKey(argv,argIndex), '@'+pair[1], v);
|
||||
}
|
||||
try{target.uninstallFunction(pair[1])}
|
||||
catch(e){/*ignored*/}
|
||||
pair[0] = pair[1] = (v || 0);
|
||||
pair[0] = pair[1] = (v | 0);
|
||||
}
|
||||
return v || 0;
|
||||
}else{
|
||||
@@ -1893,21 +1978,24 @@ self.WhWasmUtilInstaller = function(target){
|
||||
const scope = target.scopedAllocPush();
|
||||
try{
|
||||
/*
|
||||
Maintenance reminder re. arguments passed to convertArgs():
|
||||
Maintenance reminder re. arguments passed to convertArg():
|
||||
The public interface of argument adapters is that they take
|
||||
ONE argument and return a (possibly) converted result for
|
||||
it. The passing-on of arguments after the first is an
|
||||
internal impl. detail for the sake of AbstractArgAdapter, and
|
||||
not to be relied on or documented for other cases. The fact
|
||||
that this is how AbstractArgAdapter.convertArgs() gets its 2nd+
|
||||
arguments, and how FuncPtrAdapter.contextKey() gets its
|
||||
args, is also an implementation detail and subject to
|
||||
change. i.e. the public interface of 1 argument is stable.
|
||||
The fact that any arguments may be passed in after that one,
|
||||
and what those arguments are, is _not_ part of the public
|
||||
interface and is _not_ stable.
|
||||
internal implementation detail for the sake of
|
||||
AbstractArgAdapter, and not to be relied on or documented
|
||||
for other cases. The fact that this is how
|
||||
AbstractArgAdapter.convertArgs() gets its 2nd+ arguments,
|
||||
and how FuncPtrAdapter.contextKey() gets its args, is also
|
||||
an implementation detail and subject to change. i.e. the
|
||||
public interface of 1 argument is stable. The fact that any
|
||||
arguments may be passed in after that one, and what those
|
||||
arguments are, is _not_ part of the public interface and is
|
||||
_not_ stable.
|
||||
*/
|
||||
for(const i in args) args[i] = cxw.convertArgNoCheck(argTypes[i], args[i], i, args);
|
||||
for(const i in args) args[i] = cxw.convertArgNoCheck(
|
||||
argTypes[i], args[i], args, i
|
||||
);
|
||||
return cxw.convertResultNoCheck(resultType, xf.apply(null,args));
|
||||
}finally{
|
||||
target.scopedAllocPop(scope);
|
||||
|
||||
@@ -76,9 +76,7 @@
|
||||
await wtest('config-get', (ev)=>{
|
||||
const r = ev.result;
|
||||
log('sqlite3.config subset:', r);
|
||||
T.assert('boolean' === typeof r.bigIntEnabled)
|
||||
.assert('string'===typeof r.wasmfsOpfsDir)
|
||||
.assert('boolean' === typeof r.wasmfsOpfsEnabled);
|
||||
T.assert('boolean' === typeof r.bigIntEnabled);
|
||||
sqConfig = r;
|
||||
});
|
||||
logHtml('',
|
||||
@@ -213,7 +211,7 @@
|
||||
sql: "select 'foo' foo, a bar, 'baz' baz from t limit 2",
|
||||
callback: resultRowTest3,
|
||||
columnNames: [],
|
||||
rowMode: ':bar'
|
||||
rowMode: '$bar'
|
||||
}, function(ev){
|
||||
log("exec() result row:",ev);
|
||||
T.assert(2===resultRowTest3.counter);
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
<script>(async function(){
|
||||
const apiLinks = Object.assign(Object.create(null),{
|
||||
sqlite3_aggregate_context: 'www:/c3ref/aggregate_context.html',
|
||||
sqlite3_auto_extension: 'wasm:/api-c-style.md#auto-extension',
|
||||
sqlite3_bind_blob: 'www:/c3ref/bind_blob.html',
|
||||
sqlite3_bind_double: 'www:/c3ref/bind_blob.html',
|
||||
sqlite3_bind_int: 'www:/c3ref/bind_blob.html',
|
||||
@@ -205,6 +206,7 @@
|
||||
sqlite3_bind_text: 'www:/c3ref/bind_blob.html',
|
||||
sqlite3_busy_handler: 'www:/c3ref/busy_handler.html',
|
||||
sqlite3_busy_timeout: 'www:/c3ref/busy_timeout.html',
|
||||
sqlite3_cancel_auto_extension: 'wasm:/api-c-style.md#auto-extension',
|
||||
sqlite3_changes: 'www:/c3ref/changes.html',
|
||||
sqlite3_changes64: 'www:/c3ref/changes.html',
|
||||
sqlite3_clear_bindings: 'www:/c3ref/clear_bindings.html',
|
||||
@@ -220,9 +222,12 @@
|
||||
sqlite3_column_text: 'www:/c3ref/column_blob.html',
|
||||
sqlite3_column_type: 'www:/c3ref/column_blob.html',
|
||||
sqlite3_column_value: 'www:/c3ref/column_blob.html',
|
||||
sqlite3_commit_hook: 'wasm:/api-c-style.md#hook-api',
|
||||
sqlite3_compileoption_get: 'www:/c3ref/compileoption_get.html',
|
||||
sqlite3_compileoption_used: 'www:/c3ref/compileoption_get.html',
|
||||
sqlite3_complete: 'www:/c3ref/complete.html',
|
||||
sqlite3_config: 'www:/c3ref/config.html',
|
||||
sqlite3_context_db_handle: 'www:/c3ref/context_db_handle.html',
|
||||
sqlite3_create_collation: 'www:/c3ref/create_collation.html',
|
||||
sqlite3_create_collation_v2: 'www:/c3ref/create_collation.html',
|
||||
sqlite3_create_function: 'wasm:/api-c-style.md#sqlite3_create_function',
|
||||
@@ -272,6 +277,7 @@
|
||||
sqlite3_realloc: 'www:/c3ref/free.html',
|
||||
sqlite3_realloc64: 'www:/c3ref/free.html',
|
||||
sqlite3_reset: 'www:/c3ref/reset.html',
|
||||
sqlite3_reset_auto_extension: 'wasm:/api-c-style.md#auto-extension',
|
||||
sqlite3_result_blob: 'www:/c3ref/result_blob.html',
|
||||
sqlite3_result_double: 'www:/c3ref/result_blob.html',
|
||||
sqlite3_result_error: 'www:/c3ref/result_blob.html',
|
||||
@@ -286,9 +292,10 @@
|
||||
sqlite3_result_text: 'www:/c3ref/result_blob.html',
|
||||
sqlite3_result_zeroblob: 'www:/c3ref/result_blob.html',
|
||||
sqlite3_result_zeroblob64: 'www:/c3ref/result_blob.html',
|
||||
sqlite3_rollback_hook: 'wasm:/api-c-style.md#hook-api',
|
||||
sqlite3_serialize: 'www:/c3ref/serialize.html',
|
||||
sqlite3_set_authorizer: 'wasm:/api-c-style.md#sqlite3_set_authorizer',
|
||||
sqlite3_set_auxdata: 'www:/c3ref/set_auxdata.html',
|
||||
sqlite3_set_auxdata: 'www:/c3ref/get_auxdata.html',
|
||||
sqlite3_set_last_insert_rowid: 'www:/c3ref/set_last_insert_rowid',
|
||||
sqlite3_shutdown: 'www:/c3ref/initialize.html',
|
||||
sqlite3_sourceid: 'www:/c3ref/libversion.html',
|
||||
@@ -308,6 +315,7 @@
|
||||
sqlite3_total_changes64: 'www:/c3ref/total_changes.html',
|
||||
sqlite3_trace_v2: 'www:/c3ref/trace_v2.html',
|
||||
sqlite3_txn_state: 'www:/c3ref/txn_state.html',
|
||||
sqlite3_update_hook: 'wasm:/api-c-style.md#hook-api',
|
||||
sqlite3_uri_boolean: 'www:/c3ref/uri_boolean.html',
|
||||
sqlite3_uri_int64: 'www:/c3ref/uri_boolean.html',
|
||||
sqlite3_uri_key: 'www:/c3ref/uri_boolean.html',
|
||||
|
||||
+380
-16
@@ -1010,7 +1010,12 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
T.assert(P.quota >= 4096)
|
||||
.assert(remaining === P.quota)
|
||||
.mustThrowMatching(()=>P.alloc(0), isAllocErr)
|
||||
.mustThrowMatching(()=>P.alloc(-1), isAllocErr);
|
||||
.mustThrowMatching(()=>P.alloc(-1), isAllocErr)
|
||||
.mustThrowMatching(
|
||||
()=>P.alloc('i33'),
|
||||
(e)=>e instanceof sqlite3.WasmAllocError
|
||||
);
|
||||
;
|
||||
let p1 = P.alloc(12);
|
||||
T.assert(p1 === stack - 16/*8-byte aligned*/)
|
||||
.assert(P.pointer === p1);
|
||||
@@ -1029,7 +1034,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
|
||||
T.assert(P.pointer === stack);
|
||||
try {
|
||||
const [p1, p2, p3] = P.allocChunks(3,4);
|
||||
const [p1, p2, p3] = P.allocChunks(3,'i32');
|
||||
T.assert(P.pointer === stack-16/*always rounded to multiple of 8*/)
|
||||
.assert(p2 === p1 + 4)
|
||||
.assert(p3 === p2 + 4);
|
||||
@@ -1183,7 +1188,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
T.assert(0 === rc);
|
||||
const stack = wasm.pstack.pointer;
|
||||
try {
|
||||
const [pCur, pHi] = wasm.pstack.allocChunks(2,8);
|
||||
const [pCur, pHi] = wasm.pstack.allocChunks(2,'i64');
|
||||
rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED,
|
||||
pCur, pHi, 0);
|
||||
T.assert(0===rc);
|
||||
@@ -1353,6 +1358,16 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
if(wasm.bigIntEnabled){
|
||||
T.assert(4n===db.changes(false,true));
|
||||
}
|
||||
|
||||
let vals = db.selectValues('select a from t order by a limit 2');
|
||||
T.assert( 2 === vals.length )
|
||||
.assert( 1===vals[0] && 3===vals[1] );
|
||||
vals = db.selectValues('select a from t order by a limit $L',
|
||||
{$L:2}, capi.SQLITE_TEXT);
|
||||
T.assert( 2 === vals.length )
|
||||
.assert( '1'===vals[0] && '3'===vals[1] );
|
||||
vals = undefined;
|
||||
|
||||
let blob = db.selectValue("select b from t where a='blob'");
|
||||
T.assert(blob instanceof Uint8Array).
|
||||
assert(0x68===blob[0] && 0x69===blob[1]);
|
||||
@@ -1614,7 +1629,6 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
.t({
|
||||
name:'Scalar UDFs',
|
||||
//predicate: ()=>false,
|
||||
test: function(sqlite3){
|
||||
const db = this.db;
|
||||
db.createFunction("foo",(pCx,a,b)=>a+b);
|
||||
@@ -1625,6 +1639,7 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
db.createFunction("bar", {
|
||||
arity: -1,
|
||||
xFunc: (pCx,...args)=>{
|
||||
T.assert(db.pointer === capi.sqlite3_context_db_handle(pCx));
|
||||
let rc = 0;
|
||||
for(const v of args) rc += v;
|
||||
return rc;
|
||||
@@ -1680,6 +1695,45 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
sqlite3.capi.SQLITE_MISUSE === rc,
|
||||
"For invalid arg count."
|
||||
);
|
||||
|
||||
/* Confirm that we can map and unmap the same function with
|
||||
multiple arities... */
|
||||
const fCounts = [0,0];
|
||||
const fArityCheck = function(pCx){
|
||||
return ++fCounts[arguments.length-1];
|
||||
};
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
|
||||
rc = capi.sqlite3_create_function_v2(
|
||||
db, "nary", 0, capi.SQLITE_UTF8, 0, fArityCheck, 0, 0, 0
|
||||
);
|
||||
T.assert( 0===rc );
|
||||
rc = capi.sqlite3_create_function_v2(
|
||||
db, "nary", 1, capi.SQLITE_UTF8, 0, fArityCheck, 0, 0, 0
|
||||
);
|
||||
T.assert( 0===rc );
|
||||
const sqlFArity0 = "select nary()";
|
||||
const sqlFArity1 = "select nary(1)";
|
||||
T.assert( 1 === db.selectValue(sqlFArity0) )
|
||||
.assert( 1 === fCounts[0] ).assert( 0 === fCounts[1] );
|
||||
T.assert( 1 === db.selectValue(sqlFArity1) )
|
||||
.assert( 1 === fCounts[0] ).assert( 1 === fCounts[1] );
|
||||
capi.sqlite3_create_function_v2(
|
||||
db, "nary", 0, capi.SQLITE_UTF8, 0, 0, 0, 0, 0
|
||||
);
|
||||
T.mustThrowMatching((()=>db.selectValue(sqlFArity0)),
|
||||
(e)=>((e instanceof sqlite3.SQLite3Error)
|
||||
&& e.message.indexOf("wrong number of arguments")>0),
|
||||
"0-arity variant was uninstalled.");
|
||||
T.assert( 2 === db.selectValue(sqlFArity1) )
|
||||
.assert( 1 === fCounts[0] ).assert( 2 === fCounts[1] );
|
||||
capi.sqlite3_create_function_v2(
|
||||
db, "nary", 1, capi.SQLITE_UTF8, 0, 0, 0, 0, 0
|
||||
);
|
||||
T.mustThrowMatching((()=>db.selectValue(sqlFArity1)),
|
||||
(e)=>((e instanceof sqlite3.SQLite3Error)
|
||||
&& e.message.indexOf("no such function")>0),
|
||||
"1-arity variant was uninstalled.");
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1855,7 +1909,6 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
.assert('select 2;' === rc[1])
|
||||
.assert('-- empty\n; select 3' === rc[2]
|
||||
/* Strange but true. */);
|
||||
|
||||
T.mustThrowMatching(()=>{
|
||||
db.exec({sql:'', returnValue: 'nope'});
|
||||
}, /^Invalid returnValue/);
|
||||
@@ -1882,18 +1935,18 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
T.assert(3===resultRows.length)
|
||||
.assert(2===resultRows[1]);
|
||||
T.assert(2===db.selectValue('select a from foo.bar where a>1 order by a'));
|
||||
|
||||
/** Demonstrate the JS-simplified form of the sqlite3_exec() callback... */
|
||||
let colCount = 0, rowCount = 0;
|
||||
const execCallback = function(pVoid, nCols, aVals, aNames){
|
||||
//console.warn("execCallback(",arguments,")");
|
||||
colCount = nCols;
|
||||
++rowCount;
|
||||
T.assert(2===aVals.length)
|
||||
.assert(2===aNames.length)
|
||||
.assert(+(aVals[1]) === 2 * +(aVals[0]));
|
||||
};
|
||||
let rc = capi.sqlite3_exec(
|
||||
db.pointer, "select a, a*2 from foo.bar", execCallback,
|
||||
0, 0
|
||||
db, "select a, a*2 from foo.bar", function(aVals, aNames){
|
||||
//console.warn("execCallback(",arguments,")");
|
||||
colCount = aVals.length;
|
||||
++rowCount;
|
||||
T.assert(2===aVals.length)
|
||||
.assert(2===aNames.length)
|
||||
.assert(+(aVals[1]) === 2 * +(aVals[0]));
|
||||
}, 0, 0
|
||||
);
|
||||
T.assert(0===rc).assert(3===rowCount).assert(2===colCount);
|
||||
rc = capi.sqlite3_exec(
|
||||
@@ -1902,8 +1955,48 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
}, 0, 0
|
||||
);
|
||||
T.assert(capi.SQLITE_ABORT === rc);
|
||||
|
||||
/* Demonstrate how to get access to the "full" callback
|
||||
signature, as opposed to the simplified JS-specific one... */
|
||||
rowCount = colCount = 0;
|
||||
const pCb = wasm.installFunction('i(pipp)', function(pVoid,nCols,aVals,aCols){
|
||||
/* Tip: wasm.cArgvToJs() can be used to convert aVals and
|
||||
aCols to arrays: const vals = wasm.cArgvToJs(nCols,
|
||||
aVals); */
|
||||
++rowCount;
|
||||
colCount = nCols;
|
||||
T.assert(2 === nCols)
|
||||
.assert(wasm.isPtr(pVoid))
|
||||
.assert(wasm.isPtr(aVals))
|
||||
.assert(wasm.isPtr(aCols))
|
||||
.assert(+wasm.cstrToJs(wasm.peekPtr(aVals + wasm.ptrSizeof))
|
||||
=== 2 * +wasm.cstrToJs(wasm.peekPtr(aVals)));
|
||||
return 0;
|
||||
});
|
||||
try {
|
||||
T.assert(wasm.isPtr(pCb));
|
||||
rc = capi.sqlite3_exec(
|
||||
db, new TextEncoder('utf-8').encode("select a, a*2 from foo.bar"),
|
||||
pCb, 0, 0
|
||||
);
|
||||
T.assert(0===rc)
|
||||
.assert(3===rowCount)
|
||||
.assert(2===colCount);
|
||||
}finally{
|
||||
wasm.uninstallFunction(pCb);
|
||||
}
|
||||
|
||||
// Demonstrate that an OOM result does not propagate through sqlite3_exec()...
|
||||
rc = capi.sqlite3_exec(
|
||||
db, ["select a,"," a*2 from foo.bar"], (aVals, aNames)=>{
|
||||
sqlite3.WasmAllocError.toss("just testing");
|
||||
}, 0, 0
|
||||
);
|
||||
T.assert(capi.SQLITE_ABORT === rc);
|
||||
|
||||
db.exec("detach foo");
|
||||
T.mustThrow(()=>db.exec("select * from foo.bar"));
|
||||
T.mustThrow(()=>db.exec("select * from foo.bar"),
|
||||
"Because foo is no longer attached.");
|
||||
})
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -2594,6 +2687,277 @@ self.sqlite3InitModule = sqlite3InitModule;
|
||||
}/*OPFS util sanity checks*/)
|
||||
;/* end OPFS tests */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('Hook APIs')
|
||||
.t({
|
||||
name: "sqlite3_commit/rollback/update_hook()",
|
||||
predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64",
|
||||
test: function(sqlite3){
|
||||
let countCommit = 0, countRollback = 0;;
|
||||
const db = new sqlite3.oo1.DB(':memory:',1 ? 'c' : 'ct');
|
||||
let rc = capi.sqlite3_commit_hook(db, (p)=>{
|
||||
++countCommit;
|
||||
return (1 === p) ? 0 : capi.SQLITE_ERROR;
|
||||
}, 1);
|
||||
T.assert( 0 === rc /*void pointer*/ );
|
||||
|
||||
// Commit hook...
|
||||
db.exec("BEGIN; SELECT 1; COMMIT");
|
||||
T.assert(0 === countCommit,
|
||||
"No-op transactions (mostly) do not trigger commit hook.");
|
||||
db.exec("BEGIN EXCLUSIVE; SELECT 1; COMMIT");
|
||||
T.assert(1 === countCommit,
|
||||
"But EXCLUSIVE transactions do.");
|
||||
db.transaction((d)=>{d.exec("create table t(a)");});
|
||||
T.assert(2 === countCommit);
|
||||
|
||||
// Rollback hook:
|
||||
rc = capi.sqlite3_rollback_hook(db, (p)=>{
|
||||
++countRollback;
|
||||
T.assert( 2 === p );
|
||||
}, 2);
|
||||
T.assert( 0 === rc /*void pointer*/ );
|
||||
T.mustThrowMatching(()=>{
|
||||
db.transaction('drop table t',()=>{})
|
||||
}, (e)=>{
|
||||
return (capi.SQLITE_MISUSE === e.resultCode)
|
||||
&& ( e.message.indexOf('Invalid argument') > 0 );
|
||||
});
|
||||
T.assert(0 === countRollback, "Transaction was not started.");
|
||||
T.mustThrowMatching(()=>{
|
||||
db.transaction('immediate', ()=>{
|
||||
sqlite3.SQLite3Error.toss(capi.SQLITE_FULL,'testing rollback hook');
|
||||
});
|
||||
}, (e)=>{
|
||||
return capi.SQLITE_FULL === e.resultCode
|
||||
});
|
||||
T.assert(1 === countRollback);
|
||||
|
||||
// Update hook...
|
||||
const countUpdate = Object.create(null);
|
||||
capi.sqlite3_update_hook(db, (p,op,dbName,tbl,rowid)=>{
|
||||
T.assert('main' === dbName.toLowerCase())
|
||||
.assert('t' === tbl.toLowerCase())
|
||||
.assert(3===p)
|
||||
.assert('bigint' === typeof rowid);
|
||||
switch(op){
|
||||
case capi.SQLITE_INSERT:
|
||||
case capi.SQLITE_UPDATE:
|
||||
case capi.SQLITE_DELETE:
|
||||
countUpdate[op] = (countUpdate[op]||0) + 1;
|
||||
break;
|
||||
default: toss("Unexpected hook operator:",op);
|
||||
}
|
||||
}, 3);
|
||||
db.transaction((d)=>{
|
||||
d.exec([
|
||||
"insert into t(a) values(1);",
|
||||
"update t set a=2;",
|
||||
"update t set a=3;",
|
||||
"delete from t where a=3"
|
||||
// update hook is not called for an unqualified DELETE
|
||||
]);
|
||||
});
|
||||
T.assert(1 === countRollback)
|
||||
.assert(3 === countCommit)
|
||||
.assert(1 === countUpdate[capi.SQLITE_INSERT])
|
||||
.assert(2 === countUpdate[capi.SQLITE_UPDATE])
|
||||
.assert(1 === countUpdate[capi.SQLITE_DELETE]);
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
|
||||
T.assert(1 === capi.sqlite3_commit_hook(db, 0, 0));
|
||||
T.assert(2 === capi.sqlite3_rollback_hook(db, 0, 0));
|
||||
T.assert(3 === capi.sqlite3_update_hook(db, 0, 0));
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
|
||||
db.close();
|
||||
}
|
||||
})/* commit/rollback/update hooks */
|
||||
.t({
|
||||
name: "sqlite3_preupdate_hook()",
|
||||
predicate: ()=>wasm.bigIntEnabled || "Pre-update hook requires int64",
|
||||
test: function(sqlite3){
|
||||
const db = new sqlite3.oo1.DB(':memory:', 1 ? 'c' : 'ct');
|
||||
const countHook = Object.create(null);
|
||||
let rc = capi.sqlite3_preupdate_hook(
|
||||
db, function(p, pDb, op, zDb, zTbl, iKey1, iKey2){
|
||||
T.assert(9 === p)
|
||||
.assert(db.pointer === pDb)
|
||||
.assert(1 === capi.sqlite3_preupdate_count(pDb))
|
||||
.assert( 0 > capi.sqlite3_preupdate_blobwrite(pDb) );
|
||||
countHook[op] = (countHook[op]||0) + 1;
|
||||
switch(op){
|
||||
case capi.SQLITE_INSERT:
|
||||
case capi.SQLITE_UPDATE:
|
||||
T.assert('number' === typeof capi.sqlite3_preupdate_new_js(pDb, 0));
|
||||
break;
|
||||
case capi.SQLITE_DELETE:
|
||||
T.assert('number' === typeof capi.sqlite3_preupdate_old_js(pDb, 0));
|
||||
break;
|
||||
default: toss("Unexpected hook operator:",op);
|
||||
}
|
||||
},
|
||||
9
|
||||
);
|
||||
db.transaction((d)=>{
|
||||
d.exec([
|
||||
"create table t(a);",
|
||||
"insert into t(a) values(1);",
|
||||
"update t set a=2;",
|
||||
"update t set a=3;",
|
||||
"delete from t where a=3"
|
||||
]);
|
||||
});
|
||||
T.assert(1 === countHook[capi.SQLITE_INSERT])
|
||||
.assert(2 === countHook[capi.SQLITE_UPDATE])
|
||||
.assert(1 === countHook[capi.SQLITE_DELETE]);
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = true;
|
||||
db.close();
|
||||
//wasm.xWrap.FuncPtrAdapter.debugFuncInstall = false;
|
||||
}
|
||||
})/*pre-update hooks*/
|
||||
;/*end hook API tests*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('Auto-extension API')
|
||||
.t({
|
||||
name: "Auto-extension sanity checks.",
|
||||
test: function(sqlite3){
|
||||
let counter = 0;
|
||||
const fp = wasm.installFunction('i(ppp)', function(pDb,pzErr,pApi){
|
||||
++counter;
|
||||
return 0;
|
||||
});
|
||||
(new sqlite3.oo1.DB()).close();
|
||||
T.assert( 0===counter );
|
||||
capi.sqlite3_auto_extension(fp);
|
||||
(new sqlite3.oo1.DB()).close();
|
||||
T.assert( 1===counter );
|
||||
(new sqlite3.oo1.DB()).close();
|
||||
T.assert( 2===counter );
|
||||
capi.sqlite3_cancel_auto_extension(fp);
|
||||
wasm.uninstallFunction(fp);
|
||||
(new sqlite3.oo1.DB()).close();
|
||||
T.assert( 2===counter );
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
T.g('Session API')
|
||||
.t({
|
||||
name: 'Session API sanity checks',
|
||||
predicate: ()=>!!capi.sqlite3changegroup_add,
|
||||
test: function(sqlite3){
|
||||
warn("The session API tests could use some expansion.");
|
||||
const db1 = new sqlite3.oo1.DB(), db2 = new sqlite3.oo1.DB();
|
||||
const sqlInit = [
|
||||
"create table t(rowid INTEGER PRIMARY KEY,a,b); ",
|
||||
"insert into t(rowid,a,b) values",
|
||||
"(1,'a1','b1'),",
|
||||
"(2,'a2','b2'),",
|
||||
"(3,'a3','b3');"
|
||||
].join('');
|
||||
db1.exec(sqlInit);
|
||||
db2.exec(sqlInit);
|
||||
T.assert(3 === db1.selectValue("select count(*) from t"))
|
||||
.assert('b3' === db1.selectValue('select b from t where rowid=3'));
|
||||
const stackPtr = wasm.pstack.pointer;
|
||||
try{
|
||||
let ppOut = wasm.pstack.allocPtr();
|
||||
let rc = capi.sqlite3session_create(db1, "main", ppOut);
|
||||
T.assert(0===rc);
|
||||
let pSession = wasm.peekPtr(ppOut);
|
||||
T.assert(pSession && wasm.isPtr(pSession));
|
||||
capi.sqlite3session_table_filter(pSession, (pCtx, tbl)=>{
|
||||
T.assert('t' === tbl).assert( 99 === pCtx );
|
||||
return 1;
|
||||
}, 99);
|
||||
db1.exec([
|
||||
"update t set b='bTwo' where rowid=2;",
|
||||
"update t set a='aThree' where rowid=3;",
|
||||
"delete from t where rowid=1;",
|
||||
"insert into t(rowid,a,b) values(4,'a4','b4')"
|
||||
]);
|
||||
T.assert('bTwo' === db1.selectValue("select b from t where rowid=2"))
|
||||
.assert(undefined === db1.selectValue('select a from t where rowid=1'))
|
||||
.assert('b4' === db1.selectValue('select b from t where rowid=4'))
|
||||
.assert(3 === db1.selectValue('select count(*) from t'));
|
||||
|
||||
const testSessionEnable = false;
|
||||
if(testSessionEnable){
|
||||
rc = capi.sqlite3session_enable(pSession, 0);
|
||||
T.assert( 0 === rc )
|
||||
.assert( 0 === capi.sqlite3session_enable(pSession, -1) );
|
||||
db1.exec("delete from t where rowid=2;");
|
||||
rc = capi.sqlite3session_enable(pSession, 1);
|
||||
T.assert( rc > 0 )
|
||||
.assert( capi.sqlite3session_enable(pSession, -1) > 0 )
|
||||
.assert(undefined === db1.selectValue('select a from t where rowid=2'));
|
||||
}else{
|
||||
warn("sqlite3session_enable() tests disabled due to unexpected results.",
|
||||
"(Possibly a tester misunderstanding, as opposed to a bug.)");
|
||||
}
|
||||
let db1Count = db1.selectValue("select count(*) from t");
|
||||
T.assert( db1Count === (testSessionEnable ? 2 : 3) );
|
||||
|
||||
/* Capture changeset and destroy session. */
|
||||
let pnChanges = wasm.pstack.alloc('i32'),
|
||||
ppChanges = wasm.pstack.allocPtr();
|
||||
rc = capi.sqlite3session_changeset(pSession, pnChanges, ppChanges);
|
||||
T.assert( 0 === rc );
|
||||
capi.sqlite3session_delete(pSession);
|
||||
pSession = 0;
|
||||
const pChanges = wasm.peekPtr(ppChanges),
|
||||
nChanges = wasm.peek32(pnChanges);
|
||||
T.assert( pChanges && wasm.isPtr( pChanges ) )
|
||||
.assert( nChanges > 0 );
|
||||
|
||||
/* Revert db1 via an inverted changeset, but keep pChanges
|
||||
and nChanges for application to db2. */
|
||||
rc = capi.sqlite3changeset_invert( nChanges, pChanges, pnChanges, ppChanges );
|
||||
T.assert( 0 === rc );
|
||||
rc = capi.sqlite3changeset_apply(
|
||||
db1, wasm.peek32(pnChanges), wasm.peekPtr(ppChanges), 0, (pCtx, eConflict, pIter)=>{
|
||||
return 1;
|
||||
}, 0
|
||||
);
|
||||
T.assert( 0 === rc );
|
||||
wasm.dealloc( wasm.peekPtr(ppChanges) );
|
||||
pnChanges = ppChanges = 0;
|
||||
T.assert('b2' === db1.selectValue("select b from t where rowid=2"))
|
||||
.assert('a1' === db1.selectValue('select a from t where rowid=1'))
|
||||
.assert(undefined === db1.selectValue('select b from t where rowid=4'));
|
||||
db1Count = db1.selectValue("select count(*) from t");
|
||||
T.assert(3 === db1Count);
|
||||
|
||||
/* Apply pre-reverted changeset (pChanges, nChanges) to
|
||||
db2... */
|
||||
rc = capi.sqlite3changeset_apply(
|
||||
db2, nChanges, pChanges, 0, (pCtx, eConflict, pIter)=>{
|
||||
return pCtx ? 1 : 0
|
||||
}, 1
|
||||
);
|
||||
wasm.dealloc( pChanges );
|
||||
T.assert( 0 === rc )
|
||||
.assert( 'b4' === db2.selectValue('select b from t where rowid=4') )
|
||||
.assert( 'aThree' === db2.selectValue('select a from t where rowid=3') )
|
||||
.assert( undefined === db2.selectValue('select b from t where rowid=1') );
|
||||
if(testSessionEnable){
|
||||
T.assert( (undefined === db2.selectValue('select b from t where rowid=2')),
|
||||
"But... the session was disabled when rowid=2 was deleted?" );
|
||||
log("rowids from db2.t:",db2.selectValues('select rowid from t order by rowid'));
|
||||
T.assert( 3 === db2.selectValue('select count(*) from t') );
|
||||
}else{
|
||||
T.assert( 'bTwo' === db2.selectValue('select b from t where rowid=2') )
|
||||
.assert( 3 === db2.selectValue('select count(*) from t') );
|
||||
}
|
||||
}finally{
|
||||
wasm.pstack.restore(stackPtr);
|
||||
db1.close();
|
||||
db2.close();
|
||||
}
|
||||
}
|
||||
})/*session API sanity tests*/
|
||||
;/*end of session API group*/;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
log("Loading and initializing sqlite3 WASM module...");
|
||||
if(!self.sqlite3InitModule && !isUIThread()){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Incorporate\swasi-sdk\sRANLIB\sconfigure\sscript\spatch\sfrom\sthe\sVMware\sOCTO\steam.
|
||||
D 2022-12-24T15:34:16.082
|
||||
C Merge\strunk\sinto\swasi-patches\sbranch\sand\sadd\smissing\syes/no\sresult\sto\sthe\sconfigure\sscript's\soutput\sfor\sthe\s--with-wasi-sdk=PATH\stest.
|
||||
D 2023-01-11T22:45:20.283
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -33,8 +33,8 @@ F autoconf/tea/win/nmakehlp.c b01f822eabbe1ed2b64e70882d97d48402b42d2689a1ea0034
|
||||
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
|
||||
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
|
||||
F configure 7932e767cf730e8161b65bca56dee4d3bba56acd90808ac262e8c6345d1ca006 x
|
||||
F configure.ac b5f9355c46b73222ea1a9a16be868e016adda9b9b6349bfc3f72ae267f38331c
|
||||
F configure 6ba84abf7878bb072d460766d29e492028468775d4c09464940343092eb6493c x
|
||||
F configure.ac 4654d32ac0a0d0b48f1e1e79bdc3d777b723cf2f63c33eb1d7c4ed8b435938e8
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
@@ -119,7 +119,7 @@ F ext/fts5/fts5_config.c 501e7d3566bc92766b0e11c0109a7c5a6146bc41144195459af5422
|
||||
F ext/fts5/fts5_expr.c 40174a64829d30cc86e8266306ad24980f6911edd5ca0b8c1ce7821ea1341b88
|
||||
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
|
||||
F ext/fts5/fts5_index.c e879315306f368b5681d32cffc90770b124649814214615b88d79ddd957f6747
|
||||
F ext/fts5/fts5_main.c 3fd46be6a7aaac1d4210d4df0c7f9b1e78d1f0af566bfa2ab58d945ffa328ff7
|
||||
F ext/fts5/fts5_main.c 2bf44b9efdecc7fd936f320064666235b91bba8a6c4f3dc6e2d7eae6662570ed
|
||||
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
|
||||
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
@@ -194,7 +194,7 @@ F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc27826807405
|
||||
F ext/fts5/test/fts5matchinfo.test 10c9a6f7fe61fb132299c4183c012770b10c4d5c2f2edb6df0b6607f683d737a
|
||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||
F ext/fts5/test/fts5misc.test f0c5d5f6bc64f7cec522042f0ceb79c9195a4cde9fceb2af3718b3f10c8b7168
|
||||
F ext/fts5/test/fts5misc.test d6d4fdd7ec164e69e50af539137c0565362a4124547bf841ba474f092298637b
|
||||
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
|
||||
@@ -267,19 +267,19 @@ F ext/lsm1/lsm-test/lsmtest_tdb4.c cbe230727b9413d244062943371af1421ace472ccb023
|
||||
F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
|
||||
F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
|
||||
F ext/lsm1/lsm.h 0f6f64ff071471cb87bf98beb8386566f30ea001
|
||||
F ext/lsm1/lsmInt.h 5983690e05e83653cc01ba9d8fbf8455e534ddf8349ed9adedbf46a7549760b0
|
||||
F ext/lsm1/lsm_ckpt.c 0eabfaf812ddb4ea43add38f05e430694cd054eb622c3e35af4c43118a2d5321
|
||||
F ext/lsm1/lsm_file.c 3c51841d5b3e7da162693cbac9a9f47eeedf6bcbbe2969a4d25e30c428c9fe36
|
||||
F ext/lsm1/lsmInt.h 22ed041ac98a94b654432c33e0857d0a128e35d1935f2ce49f64614f03607929
|
||||
F ext/lsm1/lsm_ckpt.c ad9a8028d401be9e76f20c4d86d49f33f4fc27785577b452ca955094314a72b4
|
||||
F ext/lsm1/lsm_file.c 5486f4a63b19e4d7d972ee2482f29ebdf06c29544f31845f713cccb5199f9ad1
|
||||
F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c
|
||||
F ext/lsm1/lsm_main.c b5703f8042e71d3a2d65e671f6832e077e79e89e9975818f67f969922618db63
|
||||
F ext/lsm1/lsm_main.c 87770a9c7e73859fce7620cb79623776ba4b30369086229ad82c3e6eeaf45457
|
||||
F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
|
||||
F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
|
||||
F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525
|
||||
F ext/lsm1/lsm_sorted.c 6f7d8cf7a7d3d3f1ab5d9ba6347e8f39f3d73c00ec48afcd0c4bcbefd806f9b8
|
||||
F ext/lsm1/lsm_shared.c c67282a4f2c91e2a3362bdd40a81f9041cd587973ffc4bca8b8fbdab5470dee1
|
||||
F ext/lsm1/lsm_sorted.c 8bf11fa5ee03e49858375316aee89bb8fa7c353e1a4138a82312ae5aad4f274b
|
||||
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
|
||||
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
|
||||
F ext/lsm1/lsm_unix.c 11e0a5c19d754a4e1d93dfad06de8cc201f10f886b8e61a4c599ed34e334fc24
|
||||
F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62
|
||||
F ext/lsm1/lsm_varint.c fe134ad7b2db1ecd99b6a155d2f3625cfd497730e227ae18892452e457b73327
|
||||
F ext/lsm1/lsm_vtab.c e57aa3eb456bf2b98064014027e097c9402d6dec7b59564ddbfa1c0ead8f96c5
|
||||
F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
|
||||
F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
|
||||
@@ -289,7 +289,7 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23
|
||||
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
|
||||
F ext/misc/base64.c d9bcb499d4edf42d1d981cc49af0a084532af288f982facb83e23c2e46f7c009 x
|
||||
F ext/misc/base64.c d43d2b209c8ab70ca3f860104bb353b0f52a1c5462a2466140025c954e4f3ea7 x
|
||||
F ext/misc/base85.c 4b53d66c50e120e8697dd2a8ea6ddbc8750a4a1f6bcc6e0b7202a3998b0852bc
|
||||
F ext/misc/basexx.c 5e859e1820620aa8080fb9145eb47089de426ae808f6abb01a8e12921c3a8e67
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
@@ -341,7 +341,7 @@ F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e
|
||||
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
|
||||
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c a838d1bea913c514ff316c69695efbb49ea3b8cb37d22afc57f73b6b010b4546
|
||||
F ext/misc/zipfile.c bc4f8c552c8eed68fddc44600da9eed5d4de9c0e765b1256cf8750288097307f
|
||||
F ext/misc/zipfile.c f98239261488397618ce4754c500626d1de20cd2d44bf2f2d571d7ddaab668a7
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8
|
||||
F ext/rbu/rbu1.test c62904bd9526dcdc3496a21199aaf14ae191bbadbf67f076bf16be6b3f2115c2
|
||||
@@ -494,7 +494,7 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
|
||||
F ext/wasm/GNUmakefile ffe0e9818a3b6b36c85a1d10dab76b220a8f5cd83439c62e50223a7970b3d68a
|
||||
F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
|
||||
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 4c7788042196cecab32f87d8e4965c183fea59037603888059f244b1752babcc
|
||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||
F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
|
||||
F ext/wasm/api/extern-post-js.c-pp.js 8923f76c3d2213159e12d641dc750523ead5c848185dc4996fae5cc12397f88d
|
||||
@@ -503,32 +503,32 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
|
||||
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
|
||||
F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
|
||||
F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
|
||||
F ext/wasm/api/sqlite3-api-glue.js ba532798e577497da9221bf9ac7d286619eec4d16736c927f1d10f3c8d21ada3
|
||||
F ext/wasm/api/sqlite3-api-oo1.js 5393fb0b325d2fdafada7fdbfb9219af9a865631acb351d5c5196a982b632c8b
|
||||
F ext/wasm/api/sqlite3-api-prologue.js b0302c61abf21966c8cf9788453fea29c790633f7a14a92e05e6db994b590d11
|
||||
F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
|
||||
F ext/wasm/api/sqlite3-api-glue.js 0a93e58aabf52b32ddccbb107a1fd4552f2505e103ab63396c4d0a0743704785
|
||||
F ext/wasm/api/sqlite3-api-oo1.js e9fba119e9b1716b3f731838ed1ab18741401bcf4c51d2a4a6e9d1d23cf9d771
|
||||
F ext/wasm/api/sqlite3-api-prologue.js 0b9b463db92881990ab6995c863c5968969da3d2a5029112037cbf425c9cb6b1
|
||||
F ext/wasm/api/sqlite3-api-worker1.js c9ef8865f072e61251260b218aa4ed614a21a25e9e3cc6f22acf81794d32fc0b
|
||||
F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
|
||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 7795b84b66a7a8dedc791340709b310bb497c3c72a80bef364fa2a58e2ddae3f
|
||||
F ext/wasm/api/sqlite3-v-helper.js 6f6c3e390a72e08b0a5b16a0d567d7af3c04d172831853a29d72a6f1dd40ff24
|
||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 66daf6fb6843bea615fe193109e1542efbeca24f560ee9da63375a910bb48115
|
||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||
F ext/wasm/api/sqlite3-wasm.c 313489816e1733a10ece74a92cbea65d3ee241eb07d98088e96258cc211c9719
|
||||
F ext/wasm/api/sqlite3-wasm.c 76625a70937a8522d014ef686c32db5b53a3ee61850323f5c601d2ac39fe52fe
|
||||
F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
|
||||
F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
|
||||
F ext/wasm/api/sqlite3-worker1.js 9d3d3dfc70bff8998c1d8ff6d881cf1c3d52468d635417f02796151fe6b31cd7
|
||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||
F ext/wasm/batch-runner.js 0dad6a02ad796f1003d3b7048947d275c4d6277f63767b8e685c27df8fdac93e
|
||||
F ext/wasm/c-pp.c 92285f7bce67ed7b7020b40fde8ed0982c442b63dc33df9dfd4b658d4a6c0779
|
||||
F ext/wasm/common/SqliteTestUtil.js d8bf97ecb0705a2299765c8fc9e11b1a5ac7f10988bbf375a6558b7ca287067b
|
||||
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
|
||||
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
|
||||
F ext/wasm/common/whwasmutil.js 700fb1b702986522d2177fe8247bfbab3040e82cb4f6c35e929c4c85fbd7ffc5
|
||||
F ext/wasm/common/whwasmutil.js cad510071533dbe47787bce53f2e0dcab5b05d2dde1dbe477d8fb04e00d4e8c4
|
||||
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
|
||||
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
|
||||
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
|
||||
F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
|
||||
F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
|
||||
F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98ab22f5786620b3354ed15f
|
||||
F ext/wasm/demo-worker1-promiser.js b85a2bb1b918db4f09dfa24419241cb3edad7791389425c2505092e9b715017d
|
||||
F ext/wasm/demo-worker1-promiser.js b99c550763fa792c204e9a7cceadd976004036d9fc3e22fab7051712e30d207d
|
||||
F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
|
||||
F ext/wasm/demo-worker1.js a619adffc98b75b66c633b00f747b856449a134a9a0357909287d80a182d70fa
|
||||
F ext/wasm/dist.make 5523b02e824db5ab8176e3eedc2e709fe1204d8f4d6e52e8321cdf6830114b72
|
||||
@@ -541,7 +541,7 @@ F ext/wasm/index-dist.html c806b6005145b71d64240606e9c6e0bf56878ee8829c66fe7486c
|
||||
F ext/wasm/index.html cc8b174ff01be282b399e64b58bdf3c921d7020da5d4e22e88bbbb4a6787a209
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.js 06f2ef1ad640c26c593def3d960336e9bb789819b920516480895c38ed5f58fa
|
||||
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
|
||||
F ext/wasm/module-symbols.html 573317801087e67c946a157783715d5716e027fcf484918a0c3aae4e627cc93d
|
||||
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
|
||||
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
|
||||
F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
|
||||
F ext/wasm/speedtest1-wasmfs.html 7a301f4f5b6ad4f5d37fd6e7ca03a2f5d5547fd289da60a39075a93d7646d354
|
||||
@@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
||||
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
||||
F ext/wasm/tester1-worker.html d43f3c131d88f10d00aff3e328fed13c858d674ea2ff1ff90225506137f85aa9
|
||||
F ext/wasm/tester1.c-pp.html d34bef3d48e5cbc1c7c06882ad240fec49bf88f5f65696cc2c72c416933aa406
|
||||
F ext/wasm/tester1.c-pp.js dec750b65ec33ff267b35370ab746899859beb0a7c695cb9b087663d5b144512
|
||||
F ext/wasm/tester1.c-pp.js 7786fa3bdf074be8935e3a77b1ca135fd36ef6f87823c0695deaca585b133d06
|
||||
F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
|
||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||
@@ -584,10 +584,10 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
|
||||
F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7
|
||||
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
|
||||
F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
|
||||
F src/btree.c 2f794c217e52fdf4322bf37ee7778331b4d93aed2c00b5d67f914c0239a9edcc
|
||||
F src/btree.h 49da925329574798be3cbb745a49d069a9e67c99900d8a0d04b1e934d60394ea
|
||||
F src/btreeInt.h 88ad499c92b489afedbfefc3f067c4d15023ec021afe622db240dc9d2277cfa5
|
||||
F src/build.c e7b131773a3647701660d1b929b9947bccc9b3397788459168dd04a9e29a1f1f
|
||||
F src/btree.c 8b776a47d1e791ca78b539b8356cf32e449a613201cf64b87e7f01c62f79bd1b
|
||||
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
|
||||
F src/btreeInt.h 06bb2c1a07172d5a1cd27a2a5d617b93b1e976c5873709c31964786f86365a6e
|
||||
F src/build.c c55ab6d1b089ceef57160e840f05f692955ac90944c3d04fcf01d97fd7bfd08d
|
||||
F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
|
||||
@@ -600,21 +600,21 @@ F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
|
||||
F src/func.c 68f610a44962814a4ba593fc95137a6682cb7e65086f22167e167b75ee3432e7
|
||||
F src/global.c e06ff8e0acd85aec13563c9ecb44fbbf38232ccf73594998fd880b92d619594b
|
||||
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.c c6af5f96a7a76d000f07c5402c48c318c2566beecdee9e78b9d9f60ce7119565
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h b638809e083b601b618df877b2e89cb87c2a47a01f4def10be4c4ebb54664ac7
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 1b11a2e33ee52db93c02fddac67e39d00161d61b69fac2675b82f2aa68c1b61c
|
||||
F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 25663175950c5c4404b9377840b7b4c6fe5c53b415caf43634c62f442c02a9a7
|
||||
F src/main.c 5fba7c69ac63d728090d164930855d8f1dea37cce02858d77a9500ad20261a4b
|
||||
F src/loadext.c b04eb648cedc45efe4298e1ef439ac4f0096ae27b5f01accb0a1f49d57789128
|
||||
F src/main.c f5ed7b748d7e54b96ac577a9d87af9461f13f092bbe684d473448010333402dc
|
||||
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c 5a3dbd8ac8a6501152a4fc1fcae9b0900c2d7eb0589c4ec7456fdde15725a26c
|
||||
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
|
||||
F src/memdb.c 559c42e61eb70cd6d4bc692b042497133c6d96c09a3d514d92f3dac72268e223
|
||||
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
|
||||
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
|
||||
@@ -627,9 +627,9 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
|
||||
F src/os.c 81c9c1c52eab711e27e33fd51fe5788488d3a02bc1a71439857abbee5d0d2c97
|
||||
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 73f89ab97ecdb3216857d2acc8395103f89164eaadac87cce4e9e16445c89541
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 1086fcd1e024f009576d64bb7e1fc7f2cbcb5076c26246c5be127143330a9658
|
||||
F src/os_unix.c ca8e0cd2fb8ec774cfe6bb1f101e480f2a8f913716976d95c5556fee780c099e
|
||||
F src/os_win.c 295fe45f18bd86f2477f4cd79f3377c6f883ceb941b1f46808665c73747f2345
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c d3122cf67f327f1e2df12d06236a3473a8099542071e257067552f42917f172d
|
||||
@@ -638,24 +638,24 @@ F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
|
||||
F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
|
||||
F src/pragma.c 894c2621d35edd4beea9b331cfdb1b42032394420074d2294c8febe548eea8a1
|
||||
F src/pragma.c 23e74aaa441a03e6d97098db5883f53ee50cc50d294ecefb916437b8484012b3
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 9ebd3a1b12bbd1951f0d6db850f32cf5d4547a6ab8bb9e958d75dfbe4e60d0a3
|
||||
F src/printf.c ff4b05e38bf928ff1b80d3dda4f977b10fe39ecbfe69c018224c7e5594fb2455
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 83de67e4857be2866d048c98e93f65461d8a0408ca4ce88fec68ebfe030997ae
|
||||
F src/shell.c.in 8e411527c1b470c16e83be447ad6f8e957af7cf35a92ccce96e73fa286377b6f
|
||||
F src/sqlite.h.in 0d6a58aaf31e88f309d4ca0e06611182785adaa969ae0ab44db2febcc6045b77
|
||||
F src/select.c 146222acbf9ea4e7f99c45a9e3cb4a0ba7e02c4f0df5186094ea1f9ea9907a02
|
||||
F src/shell.c.in 007d30baf6aa51e5b7148facab9c5a92ada9e684a2436b70062c7cbca320d1b0
|
||||
F src/sqlite.h.in 7be540a872826ab3374534b4dae855faf03b28db78e995e6fe98cb833c3607c4
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c4b9fa7a7e2bcdf850cfeb4b8a91d5ec47b7a00033bc996fd2ee96cbf2741f5f
|
||||
F src/sqliteInt.h 98bc12d3191ff4c70e8491b639784c83d577b7177377d4fb344826ac56bae8a8
|
||||
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
|
||||
F src/sqliteInt.h 079ccd9c161f4b74967188fd6321810159fdc4c32371b68559719828fac20f43
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 4e64ba300a5a26e0f1170e09032429faeb65e45e8f3d1a7833e8edb69fc2979e
|
||||
F src/test1.c 98f4a4525e10b0df164ba7f33950824348bb29fd582101e0f93b1af72f493154
|
||||
F src/test1.c 39c13c25f5c4e75a07cb6bd34cfc1b8aa97ecc6f80f08953fa164db7e92ce71e
|
||||
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
|
||||
@@ -667,7 +667,7 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
|
||||
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
|
||||
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
|
||||
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 8294d8223b7f18a3ddb7f9a0e30815dcca4e61681f78b538c870f7d934f88b81
|
||||
F src/test_bestindex.c 1627f782e866a3f4b5ecd01cb46813686bf36612afc9755f26058717fe90b24e
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 8264637b06a3c1f0727c88d1ea32dcf7986b9e7e358a970cae87cdac8a5b2708
|
||||
@@ -715,15 +715,15 @@ F src/trigger.c 5e68b790f022b8dafbfb0eb244786512a95c9575fc198719d2557d73e5795858
|
||||
F src/update.c f118e51768d2c1309e3c81e9f91141b22b8a1339cbc5969b1b2d810feaa25b22
|
||||
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050
|
||||
F src/util.c 0e5cf9062a796f0f1b6b3228b121b2344932c05425f7c8b5a7cb245812473bbd
|
||||
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
|
||||
F src/vdbe.c b2f2cbaae707685b9860bd54cdd6657076c28e82c725d795ae389c10850a97a6
|
||||
F src/vdbe.c 238635c1c40d42d9ded72994b81d4127f99d6d09e9279bdd37f6f34f4025adee
|
||||
F src/vdbe.h 73b904a6b3bb27f308c6cc287a5751ebc7f1f89456be0ed068a12b92844c6e8c
|
||||
F src/vdbeInt.h fc15815b7bdafbb27e7f027faba2b0112e87d382c0d72241672528806ebc0db5
|
||||
F src/vdbeapi.c 4ee67890913c1d2469c68e3ad2e7ddeab57ac5924a64bbfd0906a8ea0d542c7f
|
||||
F src/vdbeaux.c 9eb7394126b88e55f81321d5e87636e0cd5e5856818d644d8abd6bfbb9c0be9d
|
||||
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
|
||||
F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
|
||||
F src/vdbemem.c 316d518115f3720b4097f0231e2a3d6eefd06c787eccf44972f8d8f462153421
|
||||
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
|
||||
@@ -735,8 +735,8 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c d0d8e3cb2c11e77ba0f8f9ed8eada9d84dbd377167cdcf387b8eeb824c35a3ad
|
||||
F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
|
||||
F src/wherecode.c 76bca3379219880d2527493b71a3be49e696f75396d3481e4de5d4ceec7886b2
|
||||
F src/whereexpr.c 05295b44b54eea76d1ba766f0908928d0e20e990c249344c9521454d3d09c7ae
|
||||
F src/window.c 14836767adb26573b50f528eb37f8b1336f2c430ab38de7cead1e5c546bb4d8c
|
||||
F src/whereexpr.c 7c5671a04b00c876bec5e99fd4e6f688065feb4773160fbf76fd7900d2901777
|
||||
F src/window.c 9ea4dc243420e029586c8e1ed5929fad2eae438279341ae9defc66e8f905aabc
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||
@@ -793,7 +793,7 @@ F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 00e754484859998d124d144de6d114d920f2ed6ca2f961e6a7f4183c714f885e
|
||||
F test/attachmalloc.test 67309af95c6b765c13e7d2279d7fccbef78e6eb0565d75d51cefd5dc88784549
|
||||
F test/auth.test 0f246deec5cb2f6f893f8fbb76628f182c08fe40f178b254dd72467ca012f657
|
||||
F test/auth.test 4fbeaa283637dd06e1bec5bf92dc9c39e27ef83fd20844bdcf1a85c0e6fc160d
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
@@ -828,6 +828,7 @@ F test/bestindex6.test 16942535b551273f3ad9df8d7cc4b7f22b1fcd8882714358859eb049a
|
||||
F test/bestindex7.test f094c669a6400777f4d2ddc3ed28e39169f1adb5be3d59b55f22ccf8c414b71e
|
||||
F test/bestindex8.test 333ad8c6a554b885a49b68c019166eda92b05f493a92b36b0acdf7f766d04dad
|
||||
F test/bestindex9.test bf2eb8556e8d5c00ef3ee18c521751cd03c1b55454b6e7683b4c6742e3131b23
|
||||
F test/bestindexA.test dd7b7439a46169b45d0305c4cbbb14fc20c7044acc2055c767d2f838b3479c3f
|
||||
F test/between.test b9a65fb065391980119e8a781a7409d3fcf059d89968279c750e190a9a1d5263
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
@@ -1182,7 +1183,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/having.test a89236dd8d55aa50c4805f82ac9daf64d477a44d712d8209c118978d0ca21ec9
|
||||
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test bb9e03b93fa4bc3bf0f164e455ddaee3603dee0501cb61119baed557c8f936be
|
||||
F test/hook.test 18cae9140fa7f9a6f346e892a3fe3e31b2ca0be1494cd01b918adb74281016a6
|
||||
F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
|
||||
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
|
||||
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
|
||||
@@ -1227,10 +1228,10 @@ F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c77
|
||||
F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4
|
||||
F test/instrfault.test 95e28efade652e6d51ae11b377088fe523a581a07ec428009e152a4dd0e0f44c
|
||||
F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440
|
||||
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
|
||||
F test/interrupt.test ac1ef50ec9ab8e4f0e17c47629f82539d4b22558904e321ed5abea2e6187da7a
|
||||
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
|
||||
F test/intpkey.test aee694afed1a65c86c4e69ad030224b3fc268113d00685234d40079fca16bad3
|
||||
F test/intreal.test 2a87e85a5949bd55e41ef04c58f5800587c5380bdbc559ff1c79b614b0e6a533
|
||||
F test/intreal.test 68829a8bb073ee1610ca3f8f9e0f99b0371fb36e0fa64862dd5ced4ef03c2343
|
||||
F test/io.test f138f3fe696d1ed8c51dfea5b325910d319a1b29e1d25ea57231a02092f02cca
|
||||
F test/ioerr.test 530d05801ff1b6327018b2e140da34a74effa2773a844ddb8dc79c32e9567318
|
||||
F test/ioerr2.test 2593563599e2cc6b6b4fcf5878b177bdd5d8df26
|
||||
@@ -1398,7 +1399,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 3e0d6eea70e5087f3240b1a2fe621b0c73445f38a262029f0a1d2d89564026f7
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 620622fb0815f1cbea8e26e1d8abad38e0cbcbed8927fd84048fe9fd6239e323
|
||||
F test/pragma.test a74a9c9642e5d7e32f5a2aa77a2ed64ec5b69fecff39d52c4daf5945a2a4de65
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
|
||||
F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
|
||||
@@ -1568,7 +1569,7 @@ F test/swarmvtab.test 250231404fcac88f61a6c147bb0e3a118ed879278cd3ccb0ae2d3a729e
|
||||
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
|
||||
F test/swarmvtab3.test 41a3ab47cb7a834d4e5336425103b617410a67bb95d335ef536f887587ece073
|
||||
F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95
|
||||
F test/symlink.test 72b22238d4405ba34df8e60b335d290a3b1129fd5c260835c944c1e4e77288a9
|
||||
F test/symlink.test 4368af0e213dd6e726a6240a16f2bb96a5a58f83f2d5d60652f27547b28cbf06
|
||||
F test/symlink2.test 9531f475a53d8781c4f81373f87faf2e2aff4f5fb2102ec6386e0c827916a670
|
||||
F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
@@ -1772,7 +1773,7 @@ F test/triggerE.test 612969cb57a4ef792059ad6d01af0117e1ae862c283753ffcc9a6428642
|
||||
F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
|
||||
F test/triggerG.test 2b816093c91ba73c733cfa8aedcc210ad819d72a98b1da30768a3c56505233e9
|
||||
F test/triggerupfrom.test d1f9e56090408115c522bee626cc33a2f3370f627a5e341d832589d72e3aa271
|
||||
F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f49edef1494
|
||||
F test/trustschema1.test d2996bb284859c99956ac706160eab9f086919da738d19bfef3ac431cce8fd47
|
||||
F test/tt3_checkpoint.c ac7ca661d739280c89d9c253897df64a59a49369bd1247207ac0f655b622579d
|
||||
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
|
||||
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
|
||||
@@ -1819,7 +1820,7 @@ F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce0
|
||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test a7c463254fd7ce86e861b60ddf489d5c14f22e8052f5ab2f5ff57d3eb17ccdea
|
||||
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
||||
F test/view2.test db32c8138b5b556f610b35dfddd38c5a58a292f07fda5281eedb0851b2672679
|
||||
F test/view3.test ad8a8290ee2b55ff6ce66c9ef1ce3f1e47926273a3814e1c425293e128a95456
|
||||
F test/vt02.c 33ecddc0832d4cd24e9e9fa83d868981b1e049462f4ec9080710353f6479a534
|
||||
@@ -1959,7 +1960,7 @@ F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501d
|
||||
F test/zeroblob.test 7b74cefc7b281dfa2b07cd237987fbe94b4a2037a7771e9e83f2d5f608b1d99e
|
||||
F test/zeroblobfault.test 861d8191a0d944dfebb3cb4d2c5b4e46a5a119eaec5a63dd996c2389f8063441
|
||||
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
|
||||
F test/zipfile.test 0d8758d8c0d63f16644f959689f78969d223789d998964276554039f067b4548
|
||||
F test/zipfile.test 4178a2de98739e9adac41cb8f0be5553df060e470c846f51fdbed247117728a7
|
||||
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
|
||||
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
|
||||
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
|
||||
@@ -2044,7 +2045,7 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 1dcb7632e57cf57105248029e6e162fddaf6c0fccb3bb9e6215603752c5a2d4a
|
||||
F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh d58dc38367cc776550f90327e205d7946802d4004fb9f291fd8b81256bc1eedd
|
||||
F tool/warnings.sh ab651bb82586c43ff8b560beceac959735bf917b44c5e0f67ba3426e474f29f8
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
|
||||
F vsixtest/App.xaml.cpp 41158ee43269820136fa3bba00c0bd91b26cc38b650ee392aec2a8d823e54318
|
||||
@@ -2067,8 +2068,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 52f40ab12e437c59af2b91c7ac105ab7784db57fc8d9ab7a1356f17092681f43
|
||||
R 93cdd50555e4edfd8abc358599b58d5a
|
||||
P 478fe96ee7f3ffd5732231b75e6f04e898a59368b3c91f79e6af9496dfcef6d3 7526c46632578a2b602622b9debc406b52af4a42cc880970c4307d13853d59d3
|
||||
R 5ee0a5dc148df08bb72fa9f7b42ab4d1
|
||||
U stephan
|
||||
Z 748c24f9d507d828fe21c349ea9e2c67
|
||||
Z 38bf5f86327b02eef8312b8f75a4ee2f
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
478fe96ee7f3ffd5732231b75e6f04e898a59368b3c91f79e6af9496dfcef6d3
|
||||
adc0ede0a43241b85563408d0de8e640a75ec4f7bdfe5e48acc5cdd6b182b88c
|
||||
+84
-28
@@ -8914,9 +8914,13 @@ static int btreeOverwriteContent(
|
||||
|
||||
/*
|
||||
** Overwrite the cell that cursor pCur is pointing to with fresh content
|
||||
** contained in pX.
|
||||
** contained in pX. In this variant, pCur is pointing to an overflow
|
||||
** cell.
|
||||
*/
|
||||
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
static SQLITE_NOINLINE int btreeOverwriteOverflowCell(
|
||||
BtCursor *pCur, /* Cursor pointing to cell to ovewrite */
|
||||
const BtreePayload *pX /* Content to write into the cell */
|
||||
){
|
||||
int iOffset; /* Next byte of pX->pData to write */
|
||||
int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
|
||||
int rc; /* Return code */
|
||||
@@ -8925,16 +8929,12 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
Pgno ovflPgno; /* Next overflow page to write */
|
||||
u32 ovflPageSize; /* Size to write on overflow page */
|
||||
|
||||
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|
||||
|| pCur->info.pPayload < pPage->aData + pPage->cellOffset
|
||||
){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
assert( pCur->info.nLocal<nTotal ); /* pCur is an overflow cell */
|
||||
|
||||
/* Overwrite the local portion first */
|
||||
rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
|
||||
0, pCur->info.nLocal);
|
||||
if( rc ) return rc;
|
||||
if( pCur->info.nLocal==nTotal ) return SQLITE_OK;
|
||||
|
||||
/* Now overwrite the overflow pages */
|
||||
iOffset = pCur->info.nLocal;
|
||||
@@ -8964,6 +8964,29 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Overwrite the cell that cursor pCur is pointing to with fresh content
|
||||
** contained in pX.
|
||||
*/
|
||||
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
|
||||
MemPage *pPage = pCur->pPage; /* Page being written */
|
||||
|
||||
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|
||||
|| pCur->info.pPayload < pPage->aData + pPage->cellOffset
|
||||
){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( pCur->info.nLocal==nTotal ){
|
||||
/* The entire cell is local */
|
||||
return btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
|
||||
0, pCur->info.nLocal);
|
||||
}else{
|
||||
/* The cell contains overflow content */
|
||||
return btreeOverwriteOverflowCell(pCur, pX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Insert a new record into the BTree. The content of the new record
|
||||
@@ -10158,6 +10181,41 @@ Pager *sqlite3BtreePager(Btree *p){
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/*
|
||||
** Record an OOM error during integrity_check
|
||||
*/
|
||||
static void checkOom(IntegrityCk *pCheck){
|
||||
pCheck->rc = SQLITE_NOMEM;
|
||||
pCheck->mxErr = 0; /* Causes integrity_check processing to stop */
|
||||
if( pCheck->nErr==0 ) pCheck->nErr++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Invoke the progress handler, if appropriate. Also check for an
|
||||
** interrupt.
|
||||
*/
|
||||
static void checkProgress(IntegrityCk *pCheck){
|
||||
sqlite3 *db = pCheck->db;
|
||||
if( AtomicLoad(&db->u1.isInterrupted) ){
|
||||
pCheck->rc = SQLITE_INTERRUPT;
|
||||
pCheck->nErr++;
|
||||
pCheck->mxErr = 0;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
if( db->xProgress ){
|
||||
assert( db->nProgressOps>0 );
|
||||
pCheck->nStep++;
|
||||
if( (pCheck->nStep % db->nProgressOps)==0
|
||||
&& db->xProgress(db->pProgressArg)
|
||||
){
|
||||
pCheck->rc = SQLITE_INTERRUPT;
|
||||
pCheck->nErr++;
|
||||
pCheck->mxErr = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Append a message to the error message string.
|
||||
*/
|
||||
@@ -10167,6 +10225,7 @@ static void checkAppendMsg(
|
||||
...
|
||||
){
|
||||
va_list ap;
|
||||
checkProgress(pCheck);
|
||||
if( !pCheck->mxErr ) return;
|
||||
pCheck->mxErr--;
|
||||
pCheck->nErr++;
|
||||
@@ -10180,7 +10239,7 @@ static void checkAppendMsg(
|
||||
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
|
||||
va_end(ap);
|
||||
if( pCheck->errMsg.accError==SQLITE_NOMEM ){
|
||||
pCheck->bOomFault = 1;
|
||||
checkOom(pCheck);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
@@ -10222,7 +10281,6 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
|
||||
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
|
||||
return 1;
|
||||
}
|
||||
if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1;
|
||||
setPageReferenced(pCheck, iPage);
|
||||
return 0;
|
||||
}
|
||||
@@ -10245,7 +10303,7 @@ static void checkPtrmap(
|
||||
|
||||
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->bOomFault = 1;
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck);
|
||||
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
|
||||
return;
|
||||
}
|
||||
@@ -10429,6 +10487,8 @@ static int checkTreePage(
|
||||
|
||||
/* Check that the page exists
|
||||
*/
|
||||
checkProgress(pCheck);
|
||||
if( pCheck->mxErr==0 ) goto end_of_check;
|
||||
pBt = pCheck->pBt;
|
||||
usableSize = pBt->usableSize;
|
||||
if( iPage==0 ) return 0;
|
||||
@@ -10674,13 +10734,14 @@ end_of_check:
|
||||
** the unverified btrees. Except, if aRoot[1] is 1, then the freelist
|
||||
** checks are still performed.
|
||||
*/
|
||||
char *sqlite3BtreeIntegrityCheck(
|
||||
int sqlite3BtreeIntegrityCheck(
|
||||
sqlite3 *db, /* Database connection that is running the check */
|
||||
Btree *p, /* The btree to be checked */
|
||||
Pgno *aRoot, /* An array of root pages numbers for individual trees */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr /* Write number of errors seen to this variable */
|
||||
int *pnErr, /* OUT: Write number of errors seen to this variable */
|
||||
char **pzOut /* OUT: Write the error message string here */
|
||||
){
|
||||
Pgno i;
|
||||
IntegrityCk sCheck;
|
||||
@@ -10703,18 +10764,12 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
|
||||
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
|
||||
assert( nRef>=0 );
|
||||
memset(&sCheck, 0, sizeof(sCheck));
|
||||
sCheck.db = db;
|
||||
sCheck.pBt = pBt;
|
||||
sCheck.pPager = pBt->pPager;
|
||||
sCheck.nPage = btreePagecount(sCheck.pBt);
|
||||
sCheck.mxErr = mxErr;
|
||||
sCheck.nErr = 0;
|
||||
sCheck.bOomFault = 0;
|
||||
sCheck.zPfx = 0;
|
||||
sCheck.v1 = 0;
|
||||
sCheck.v2 = 0;
|
||||
sCheck.aPgRef = 0;
|
||||
sCheck.heap = 0;
|
||||
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
|
||||
sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL;
|
||||
if( sCheck.nPage==0 ){
|
||||
@@ -10723,12 +10778,12 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
|
||||
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
|
||||
if( !sCheck.aPgRef ){
|
||||
sCheck.bOomFault = 1;
|
||||
checkOom(&sCheck);
|
||||
goto integrity_ck_cleanup;
|
||||
}
|
||||
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||
if( sCheck.heap==0 ){
|
||||
sCheck.bOomFault = 1;
|
||||
checkOom(&sCheck);
|
||||
goto integrity_ck_cleanup;
|
||||
}
|
||||
|
||||
@@ -10809,16 +10864,17 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
integrity_ck_cleanup:
|
||||
sqlite3PageFree(sCheck.heap);
|
||||
sqlite3_free(sCheck.aPgRef);
|
||||
if( sCheck.bOomFault ){
|
||||
sqlite3_str_reset(&sCheck.errMsg);
|
||||
sCheck.nErr++;
|
||||
}
|
||||
*pnErr = sCheck.nErr;
|
||||
if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
|
||||
if( sCheck.nErr==0 ){
|
||||
sqlite3_str_reset(&sCheck.errMsg);
|
||||
*pzOut = 0;
|
||||
}else{
|
||||
*pzOut = sqlite3StrAccumFinish(&sCheck.errMsg);
|
||||
}
|
||||
/* Make sure this analysis did not leave any unref() pages. */
|
||||
assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
|
||||
sqlite3BtreeLeave(p);
|
||||
return sqlite3StrAccumFinish(&sCheck.errMsg);
|
||||
return sCheck.rc;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
|
||||
+9
-1
@@ -329,7 +329,15 @@ const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
|
||||
u32 sqlite3BtreePayloadSize(BtCursor*);
|
||||
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
|
||||
|
||||
char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,Pgno*aRoot,int nRoot,int,int*);
|
||||
int sqlite3BtreeIntegrityCheck(
|
||||
sqlite3 *db, /* Database connection that is running the check */
|
||||
Btree *p, /* The btree to be checked */
|
||||
Pgno *aRoot, /* An array of root pages numbers for individual trees */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr, /* OUT: Write number of errors seen to this variable */
|
||||
char **pzOut /* OUT: Write the error message string here */
|
||||
);
|
||||
struct Pager *sqlite3BtreePager(Btree*);
|
||||
i64 sqlite3BtreeRowCountEst(BtCursor*);
|
||||
|
||||
|
||||
+4
-3
@@ -681,8 +681,8 @@ struct BtCursor {
|
||||
|
||||
|
||||
/*
|
||||
** This structure is passed around through all the sanity checking routines
|
||||
** in order to keep track of some global state information.
|
||||
** This structure is passed around through all the PRAGMA integrity_check
|
||||
** checking routines in order to keep track of some global state information.
|
||||
**
|
||||
** The aRef[] array is allocated so that there is 1 bit for each page in
|
||||
** the database. As the integrity-check proceeds, for each page used in
|
||||
@@ -698,7 +698,8 @@ struct IntegrityCk {
|
||||
Pgno nPage; /* Number of pages in the database */
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
int bOomFault; /* A memory allocation error has occurred */
|
||||
int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */
|
||||
u32 nStep; /* Number of steps into the integrity_check process */
|
||||
const char *zPfx; /* Error message prefix */
|
||||
Pgno v1; /* Value for first %u substitution in zPfx */
|
||||
int v2; /* Value for second %d substitution in zPfx */
|
||||
|
||||
@@ -307,6 +307,7 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
char saveBuf[PARSE_TAIL_SZ];
|
||||
|
||||
if( pParse->nErr ) return;
|
||||
if( pParse->eParseMode ) return;
|
||||
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3VMPrintf(db, zFormat, ap);
|
||||
|
||||
+2
-1
@@ -166,12 +166,13 @@ static HashElem *findElementWithHash(
|
||||
count = pH->count;
|
||||
}
|
||||
if( pHash ) *pHash = h;
|
||||
while( count-- ){
|
||||
while( count ){
|
||||
assert( elem!=0 );
|
||||
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
|
||||
return elem;
|
||||
}
|
||||
elem = elem->next;
|
||||
count--;
|
||||
}
|
||||
return &nullElement;
|
||||
}
|
||||
|
||||
+3
-1
@@ -510,7 +510,9 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
#endif
|
||||
sqlite3_db_name,
|
||||
/* Version 3.40.0 and later */
|
||||
sqlite3_value_encoding
|
||||
sqlite3_value_encoding,
|
||||
/* Version 3.41.0 and later */
|
||||
sqlite3_is_interrupted
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
+21
-4
@@ -1796,7 +1796,9 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
||||
*/
|
||||
void sqlite3_interrupt(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){
|
||||
if( !sqlite3SafetyCheckOk(db)
|
||||
&& (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
|
||||
){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return;
|
||||
}
|
||||
@@ -1804,6 +1806,21 @@ void sqlite3_interrupt(sqlite3 *db){
|
||||
AtomicStore(&db->u1.isInterrupted, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true or false depending on whether or not an interrupt is
|
||||
** pending on connection db.
|
||||
*/
|
||||
int sqlite3_is_interrupted(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db)
|
||||
&& (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
|
||||
){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return AtomicLoad(&db->u1.isInterrupted)!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is exactly the same as sqlite3_create_function(), except
|
||||
@@ -1848,7 +1865,7 @@ int sqlite3CreateFunc(
|
||||
/* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
|
||||
** the meaning is inverted. So flip the bit. */
|
||||
assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS );
|
||||
extraFlags ^= SQLITE_FUNC_UNSAFE;
|
||||
extraFlags ^= SQLITE_FUNC_UNSAFE; /* tag-20230109-1 */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -1866,11 +1883,11 @@ int sqlite3CreateFunc(
|
||||
case SQLITE_ANY: {
|
||||
int rc;
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
||||
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
(SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1 */
|
||||
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
||||
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
|
||||
(SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE, /* tag-20230109-1*/
|
||||
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
||||
+6
-2
@@ -424,9 +424,13 @@ static int memsys5Roundup(int n){
|
||||
if( n<=mem5.szAtom ) return mem5.szAtom;
|
||||
return mem5.szAtom*2;
|
||||
}
|
||||
if( n>0x40000000 ) return 0;
|
||||
if( n>0x10000000 ){
|
||||
if( n>0x40000000 ) return 0;
|
||||
if( n>0x20000000 ) return 0x40000000;
|
||||
return 0x20000000;
|
||||
}
|
||||
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
|
||||
if( (iFullSz/2)>=n ) return iFullSz/2;
|
||||
if( (iFullSz/2)>=(i64)n ) return iFullSz/2;
|
||||
return iFullSz;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -417,8 +417,7 @@ static int kvvfsDecode(const char *a, char *aOut, int nOut){
|
||||
if( j+n>nOut ) return -1;
|
||||
memset(&aOut[j], 0, n);
|
||||
j += n;
|
||||
c = aIn[i];
|
||||
if( c==0 ) break;
|
||||
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
|
||||
}else{
|
||||
aOut[j] = c<<4;
|
||||
c = kvvfsHexValue[aIn[++i]];
|
||||
|
||||
+3
-5
@@ -6506,12 +6506,10 @@ static void appendOnePathElement(
|
||||
if( zName[0]=='.' ){
|
||||
if( nName==1 ) return;
|
||||
if( zName[1]=='.' && nName==2 ){
|
||||
if( pPath->nUsed<=1 ){
|
||||
pPath->rc = SQLITE_ERROR;
|
||||
return;
|
||||
if( pPath->nUsed>1 ){
|
||||
assert( pPath->zOut[0]=='/' );
|
||||
while( pPath->zOut[--pPath->nUsed]!='/' ){}
|
||||
}
|
||||
assert( pPath->zOut[0]=='/' );
|
||||
while( pPath->zOut[--pPath->nUsed]!='/' ){}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+22
-2
@@ -1958,7 +1958,8 @@ void sqlite3Pragma(
|
||||
if( !isQuick ){ /* Omit the remaining tests for quick_check */
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
int jmp2, jmp3, jmp4, jmp5, label6;
|
||||
int kk;
|
||||
int ckUniq = sqlite3VdbeMakeLabel(pParse);
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
@@ -1976,13 +1977,32 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp4 = integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
|
||||
/* Any indexed columns with non-BINARY collations must still hold
|
||||
** the exact same text value as the table. */
|
||||
label6 = 0;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
if( pIdx->azColl[kk]==sqlite3StrBINARY ) continue;
|
||||
if( label6==0 ) label6 = sqlite3VdbeMakeLabel(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur+j, kk, 3);
|
||||
sqlite3VdbeAddOp3(v, OP_Ne, 3, label6, r1+kk); VdbeCoverage(v);
|
||||
}
|
||||
if( label6 ){
|
||||
int jmp6 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeResolveLabel(v, label6);
|
||||
sqlite3VdbeLoadString(v, 3, "row ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
|
||||
sqlite3VdbeLoadString(v, 4, " values differ from index ");
|
||||
sqlite3VdbeGoto(v, jmp5-1);
|
||||
sqlite3VdbeJumpHere(v, jmp6);
|
||||
}
|
||||
|
||||
/* For UNIQUE indexes, verify that only one entry exists with the
|
||||
** current key. The entry is unique if (1) any column is NULL
|
||||
** or (2) the next entry has a different key */
|
||||
if( IsUniqueIndex(pIdx) ){
|
||||
int uniqOk = sqlite3VdbeMakeLabel(pParse);
|
||||
int jmp6;
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
|
||||
+29
-25
@@ -1870,7 +1870,6 @@ static void generateSortTail(
|
||||
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
|
||||
# define columnType(A,B,C,D,E) columnTypeImpl(A,B)
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_DECLTYPE
|
||||
static const char *columnTypeImpl(
|
||||
NameContext *pNC,
|
||||
#ifndef SQLITE_ENABLE_COLUMN_METADATA
|
||||
@@ -1901,7 +1900,7 @@ static const char *columnTypeImpl(
|
||||
Table *pTab = 0; /* Table structure column is extracted from */
|
||||
Select *pS = 0; /* Select the column is extracted from */
|
||||
int iCol = pExpr->iColumn; /* Index of column in pTab */
|
||||
while( ALWAYS(pNC) && !pTab ){
|
||||
while( pNC && !pTab ){
|
||||
SrcList *pTabList = pNC->pSrcList;
|
||||
for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
|
||||
if( j<pTabList->nSrc ){
|
||||
@@ -1912,7 +1911,7 @@ static const char *columnTypeImpl(
|
||||
}
|
||||
}
|
||||
|
||||
if( NEVER(pTab==0) ){
|
||||
if( pTab==0 ){
|
||||
/* At one time, code such as "SELECT new.x" within a trigger would
|
||||
** cause this condition to run. Since then, we have restructured how
|
||||
** trigger code is generated and so this condition is no longer
|
||||
@@ -2017,7 +2016,6 @@ static const char *columnTypeImpl(
|
||||
#endif
|
||||
return zType;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
|
||||
|
||||
/*
|
||||
** Generate code that will tell the VDBE the declaration types of columns
|
||||
@@ -2311,6 +2309,7 @@ void sqlite3SubqueryColumnTypes(
|
||||
int i,j;
|
||||
Expr *p;
|
||||
struct ExprList_item *a;
|
||||
NameContext sNC;
|
||||
|
||||
assert( pSelect!=0 );
|
||||
assert( (pSelect->selFlags & SF_Resolved)!=0 );
|
||||
@@ -2319,6 +2318,8 @@ void sqlite3SubqueryColumnTypes(
|
||||
if( db->mallocFailed ) return;
|
||||
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
|
||||
a = pSelect->pEList->a;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pSrcList = pSelect->pSrc;
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
const char *zType;
|
||||
i64 n;
|
||||
@@ -2344,28 +2345,31 @@ void sqlite3SubqueryColumnTypes(
|
||||
pCol->affinity = SQLITE_AFF_BLOB;
|
||||
}
|
||||
}
|
||||
if( pCol->affinity==SQLITE_AFF_NUMERIC
|
||||
|| pCol->affinity==SQLITE_AFF_FLEXNUM
|
||||
){
|
||||
zType = "NUM";
|
||||
}else{
|
||||
zType = 0;
|
||||
for(j=1; j<SQLITE_N_STDTYPE; j++){
|
||||
if( sqlite3StdTypeAffinity[j]==pCol->affinity ){
|
||||
zType = sqlite3StdType[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( zType ){
|
||||
i64 m = sqlite3Strlen30(zType);
|
||||
n = sqlite3Strlen30(pCol->zCnName);
|
||||
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
|
||||
if( pCol->zCnName ){
|
||||
memcpy(&pCol->zCnName[n+1], zType, m+1);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
zType = columnType(&sNC, p, 0, 0, 0);
|
||||
if( zType==0 || pCol->affinity!=sqlite3AffinityType(zType, 0) ){
|
||||
if( pCol->affinity==SQLITE_AFF_NUMERIC
|
||||
|| pCol->affinity==SQLITE_AFF_FLEXNUM
|
||||
){
|
||||
zType = "NUM";
|
||||
}else{
|
||||
testcase( pCol->colFlags & COLFLAG_HASTYPE );
|
||||
zType = 0;
|
||||
for(j=1; j<SQLITE_N_STDTYPE; j++){
|
||||
if( sqlite3StdTypeAffinity[j]==pCol->affinity ){
|
||||
zType = sqlite3StdType[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( zType ){
|
||||
i64 m = sqlite3Strlen30(zType);
|
||||
n = sqlite3Strlen30(pCol->zCnName);
|
||||
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
|
||||
if( pCol->zCnName ){
|
||||
memcpy(&pCol->zCnName[n+1], zType, m+1);
|
||||
pCol->colFlags |= COLFLAG_HASTYPE;
|
||||
}else{
|
||||
testcase( pCol->colFlags & COLFLAG_HASTYPE );
|
||||
pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-4
@@ -166,6 +166,14 @@ typedef unsigned char u8;
|
||||
# define SHELL_USE_LOCAL_GETLINE 1
|
||||
#endif
|
||||
|
||||
#ifndef deliberate_fall_through
|
||||
/* Quiet some compilers about some of our intentional code. */
|
||||
# if GCC_VERSION>=7000000
|
||||
# define deliberate_fall_through __attribute__((fallthrough));
|
||||
# else
|
||||
# define deliberate_fall_through
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# if SQLITE_OS_WINRT
|
||||
@@ -4681,7 +4689,7 @@ static const char *(azHelp[]) = {
|
||||
#endif
|
||||
".prompt MAIN CONTINUE Replace the standard prompts",
|
||||
#ifndef SQLITE_SHELL_FIDDLE
|
||||
".quit Exit this program",
|
||||
".quit Stop interpreting input stream, exit if primary.",
|
||||
".read FILE Read input from FILE or command output",
|
||||
" If FILE begins with \"|\", it is a command that generates the input.",
|
||||
#endif
|
||||
@@ -6839,7 +6847,7 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
break;
|
||||
case AR_SWITCH_APPEND:
|
||||
pAr->bAppend = 1;
|
||||
/* Fall thru into --file */
|
||||
deliberate_fall_through;
|
||||
case AR_SWITCH_FILE:
|
||||
pAr->zFile = zArg;
|
||||
break;
|
||||
@@ -11167,7 +11175,7 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
||||
break;
|
||||
case '[':
|
||||
cin = ']';
|
||||
/* fall thru */
|
||||
deliberate_fall_through;
|
||||
case '`': case '\'': case '"':
|
||||
cWait = cin;
|
||||
qss = QSS_HasDark | cWait;
|
||||
@@ -11203,7 +11211,7 @@ static QuickScanState quickscan(char *zLine, QuickScanState qss,
|
||||
++zLine;
|
||||
continue;
|
||||
}
|
||||
/* fall thru */
|
||||
deliberate_fall_through;
|
||||
case ']':
|
||||
cWait = 0;
|
||||
CONTINUE_PROMPT_AWAITC(pst, 0);
|
||||
|
||||
+35
-11
@@ -2679,8 +2679,12 @@ sqlite3_int64 sqlite3_total_changes64(sqlite3*);
|
||||
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
|
||||
** SQL statements is a no-op and has no effect on SQL statements
|
||||
** that are started after the sqlite3_interrupt() call returns.
|
||||
**
|
||||
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
|
||||
** or not an interrupt is currently in effect for [database connection] D.
|
||||
*/
|
||||
void sqlite3_interrupt(sqlite3*);
|
||||
int sqlite3_is_interrupted(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If An SQL Statement Is Complete
|
||||
@@ -3298,8 +3302,8 @@ SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
||||
** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same
|
||||
** information as is provided by the [sqlite3_profile()] callback.
|
||||
** ^The P argument is a pointer to the [prepared statement] and the
|
||||
** X argument points to a 64-bit integer which is the estimated of
|
||||
** the number of nanosecond that the prepared statement took to run.
|
||||
** X argument points to a 64-bit integer which is approximately
|
||||
** the number of nanoseconds that the prepared statement took to run.
|
||||
** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes.
|
||||
**
|
||||
** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>
|
||||
@@ -3423,13 +3427,18 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
**
|
||||
** <dl>
|
||||
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
|
||||
** <dd>The database is opened in read-only mode. If the database does not
|
||||
** already exist, an error is returned.</dd>)^
|
||||
** <dd>The database is opened in read-only mode. If the database does
|
||||
** not already exist, an error is returned.</dd>)^
|
||||
**
|
||||
** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
|
||||
** <dd>The database is opened for reading and writing if possible, or reading
|
||||
** only if the file is write protected by the operating system. In either
|
||||
** case the database must already exist, otherwise an error is returned.</dd>)^
|
||||
** <dd>The database is opened for reading and writing if possible, or
|
||||
** reading only if the file is write protected by the operating
|
||||
** system. In either case the database must already exist, otherwise
|
||||
** an error is returned. For historical reasons, if opening in
|
||||
** read-write mode fails due to OS-level permissions, an attempt is
|
||||
** made to open it in read-only mode. [sqlite3_db_readonly()] can be
|
||||
** used to determine whether the database is actually
|
||||
** read-write.</dd>)^
|
||||
**
|
||||
** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
|
||||
** <dd>The database is opened for reading and writing, and is created if
|
||||
@@ -5410,10 +5419,21 @@ int sqlite3_create_window_function(
|
||||
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
|
||||
** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
||||
** [expression indexes], [partial indexes], or [generated columns].
|
||||
** The SQLITE_DIRECTONLY flags is a security feature which is recommended
|
||||
** for all [application-defined SQL functions], and especially for functions
|
||||
** that have side-effects or that could potentially leak sensitive
|
||||
** information.
|
||||
** <p>
|
||||
** The SQLITE_DIRECTONLY flag is recommended for any
|
||||
** [application-defined SQL function]
|
||||
** that has side-effects or that could potentially leak sensitive information.
|
||||
** This will prevent attacks in which an application is tricked
|
||||
** into using a database file that has had its schema surreptiously
|
||||
** modified to invoke the application-defined function in ways that are
|
||||
** harmful.
|
||||
** <p>
|
||||
** Some people say it is good practice to set SQLITE_DIRECTONLY on all
|
||||
** [application-defined SQL functions], regardless of whether or not they
|
||||
** are security sensitive, as doing so prevents those functions from being used
|
||||
** inside of the database schema, and thus ensures that the database
|
||||
** can be inspected and modified using generic tools (such as the [CLI])
|
||||
** that do not have access to the application-defined functions.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
|
||||
@@ -10097,6 +10117,10 @@ int sqlite3_db_cacheflush(sqlite3*);
|
||||
** function is not defined for operations on WITHOUT ROWID tables, or for
|
||||
** DELETE operations on rowid tables.
|
||||
**
|
||||
** ^The sqlite3_update_hook(D,C,P) function returns the P argument from
|
||||
** the previous call on the same [database connection] D, or NULL for
|
||||
** the first call on D.
|
||||
**
|
||||
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
|
||||
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
|
||||
** provide additional information about a preupdate event. These routines
|
||||
|
||||
@@ -359,6 +359,8 @@ struct sqlite3_api_routines {
|
||||
const char *(*db_name)(sqlite3*,int);
|
||||
/* Version 3.40.0 and later */
|
||||
int (*value_encoding)(sqlite3_value*);
|
||||
/* Version 3.41.0 and later */
|
||||
int (*is_interrupted)(sqlite3*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -685,6 +687,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_db_name sqlite3_api->db_name
|
||||
/* Version 3.40.0 and later */
|
||||
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
||||
/* Version 3.41.0 and later */
|
||||
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+9
-5
@@ -1929,8 +1929,14 @@ struct FuncDestructor {
|
||||
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
|
||||
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
|
||||
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
|
||||
** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
|
||||
** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!!
|
||||
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
|
||||
**
|
||||
** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the
|
||||
** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is
|
||||
** used internally and if set means tha the function has side effects.
|
||||
** SQLITE_INNOCUOUS is used by application code and means "not unsafe".
|
||||
** See multiple instances of tag-20230109-1.
|
||||
*/
|
||||
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
||||
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
|
||||
@@ -2047,7 +2053,7 @@ struct FuncDestructor {
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define JFUNCTION(zName, nArg, iArg, xFunc) \
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|\
|
||||
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|\
|
||||
SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
||||
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
|
||||
@@ -4496,13 +4502,11 @@ int sqlite3HeapNearlyFull(void);
|
||||
#ifdef SQLITE_USE_ALLOCA
|
||||
# define sqlite3StackAllocRaw(D,N) alloca(N)
|
||||
# define sqlite3StackAllocRawNN(D,N) alloca(N)
|
||||
# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
|
||||
# define sqlite3StackFree(D,P)
|
||||
# define sqlite3StackFreeNN(D,P)
|
||||
#else
|
||||
# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
|
||||
# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N)
|
||||
# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
|
||||
# define sqlite3StackFree(D,P) sqlite3DbFree(D,P)
|
||||
# define sqlite3StackFreeNN(D,P) sqlite3DbFreeNN(D,P)
|
||||
#endif
|
||||
@@ -5004,7 +5008,7 @@ int sqlite3FixExpr(DbFixer*, Expr*);
|
||||
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
|
||||
int sqlite3RealSameAsInt(double,sqlite3_int64);
|
||||
i64 sqlite3RealToI64(double);
|
||||
void sqlite3Int64ToText(i64,char*);
|
||||
int sqlite3Int64ToText(i64,char*);
|
||||
int sqlite3AtoF(const char *z, double*, int, u8);
|
||||
int sqlite3GetInt32(const char *, int*);
|
||||
int sqlite3GetUInt32(const char*, u32*);
|
||||
|
||||
+24
-1
@@ -5537,7 +5537,6 @@ static int SQLITE_TCLAPI test_stmt_int(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_interrupt DB
|
||||
**
|
||||
@@ -5559,6 +5558,29 @@ static int SQLITE_TCLAPI test_interrupt(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_is_interrupted DB
|
||||
**
|
||||
** return true if an interrupt is current in effect on DB
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_is_interrupted(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int argc,
|
||||
char **argv
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
if( argc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
rc = sqlite3_is_interrupted(db);
|
||||
Tcl_AppendResult(interp, rc ? "1" : "0", (void*)0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite_delete_function DB function-name
|
||||
**
|
||||
@@ -8631,6 +8653,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_key", (Tcl_CmdProc*)test_key },
|
||||
{ "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
|
||||
{ "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
|
||||
{ "sqlite3_is_interrupted", (Tcl_CmdProc*)test_is_interrupted },
|
||||
{ "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
|
||||
{ "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
|
||||
{ "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
|
||||
|
||||
+99
-3
@@ -101,8 +101,10 @@
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
||||
typedef struct tcl_vtab tcl_vtab;
|
||||
typedef struct tcl_cursor tcl_cursor;
|
||||
typedef struct TestFindFunction TestFindFunction;
|
||||
|
||||
/*
|
||||
** A fs virtual-table object
|
||||
@@ -111,6 +113,7 @@ struct tcl_vtab {
|
||||
sqlite3_vtab base;
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pCmd;
|
||||
TestFindFunction *pFindFunctionList;
|
||||
sqlite3 *db;
|
||||
};
|
||||
|
||||
@@ -120,6 +123,13 @@ struct tcl_cursor {
|
||||
sqlite3_stmt *pStmt; /* Read data from here */
|
||||
};
|
||||
|
||||
struct TestFindFunction {
|
||||
tcl_vtab *pTab;
|
||||
const char *zName;
|
||||
TestFindFunction *pNext;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Dequote string z in place.
|
||||
*/
|
||||
@@ -223,6 +233,11 @@ static int tclConnect(
|
||||
/* The xDisconnect and xDestroy methods are also the same */
|
||||
static int tclDisconnect(sqlite3_vtab *pVtab){
|
||||
tcl_vtab *pTab = (tcl_vtab*)pVtab;
|
||||
while( pTab->pFindFunctionList ){
|
||||
TestFindFunction *p = pTab->pFindFunctionList;
|
||||
pTab->pFindFunctionList = p->pNext;
|
||||
sqlite3_free(p);
|
||||
}
|
||||
Tcl_DecrRefCount(pTab->pCmd);
|
||||
sqlite3_free(pTab);
|
||||
return SQLITE_OK;
|
||||
@@ -398,7 +413,7 @@ static void testBestIndexObjConstraints(
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
|
||||
Tcl_Obj *pElem = Tcl_NewObj();
|
||||
const char *zOp = "?";
|
||||
const char *zOp = 0;
|
||||
|
||||
Tcl_IncrRefCount(pElem);
|
||||
|
||||
@@ -438,7 +453,11 @@ static void testBestIndexObjConstraints(
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1));
|
||||
if( zOp ){
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zOp, -1));
|
||||
}else{
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->op));
|
||||
}
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("column", -1));
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pCons->iColumn));
|
||||
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("usable", -1));
|
||||
@@ -693,6 +712,83 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void tclFunction(sqlite3_context *pCtx, int nArg, sqlite3_value **apArg){
|
||||
TestFindFunction *p = (TestFindFunction*)sqlite3_user_data(pCtx);
|
||||
Tcl_Interp *interp = p->pTab->interp;
|
||||
Tcl_Obj *pScript = 0;
|
||||
Tcl_Obj *pRet = 0;
|
||||
int ii;
|
||||
|
||||
pScript = Tcl_DuplicateObj(p->pTab->pCmd);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj("function", -1));
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(p->zName, -1));
|
||||
|
||||
for(ii=0; ii<nArg; ii++){
|
||||
const char *zArg = (const char*)sqlite3_value_text(apArg[ii]);
|
||||
Tcl_ListObjAppendElement(interp, pScript,
|
||||
(zArg ? Tcl_NewStringObj(zArg, -1) : Tcl_NewObj())
|
||||
);
|
||||
}
|
||||
Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
|
||||
Tcl_DecrRefCount(pScript);
|
||||
|
||||
pRet = Tcl_GetObjResult(interp);
|
||||
sqlite3_result_text(pCtx, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
static int tclFindFunction(
|
||||
sqlite3_vtab *tab,
|
||||
int nArg,
|
||||
const char *zName,
|
||||
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT */
|
||||
void **ppArg /* OUT */
|
||||
){
|
||||
int iRet = 0;
|
||||
tcl_vtab *pTab = (tcl_vtab*)tab;
|
||||
Tcl_Interp *interp = pTab->interp;
|
||||
Tcl_Obj *pScript = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pScript = Tcl_DuplicateObj(pTab->pCmd);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pScript, Tcl_NewStringObj("xFindFunction", -1)
|
||||
);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewIntObj(nArg));
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zName, -1));
|
||||
rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL);
|
||||
Tcl_DecrRefCount(pScript);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_Obj *pObj = Tcl_GetObjResult(interp);
|
||||
|
||||
if( Tcl_GetIntFromObj(interp, pObj, &iRet) ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else if( iRet>0 ){
|
||||
int nName = strlen(zName);
|
||||
int nByte = nName + 1 + sizeof(TestFindFunction);
|
||||
TestFindFunction *pNew = 0;
|
||||
|
||||
pNew = (TestFindFunction*)sqlite3_malloc(nByte);
|
||||
if( pNew==0 ){
|
||||
iRet = 0;
|
||||
}else{
|
||||
memset(pNew, 0, nByte);
|
||||
pNew->zName = (const char*)&pNew[1];
|
||||
memcpy((char*)pNew->zName, zName, nName);
|
||||
pNew->pTab = pTab;
|
||||
pNew->pNext = pTab->pFindFunctionList;
|
||||
pTab->pFindFunctionList = pNew;
|
||||
*ppArg = (void*)pNew;
|
||||
*pxFunc = tclFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** A virtual table module that provides read-only access to a
|
||||
** Tcl global variable namespace.
|
||||
@@ -716,7 +812,7 @@ static sqlite3_module tclModule = {
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
tclFindFunction, /* xFindFunction */
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
|
||||
+6
-2
@@ -632,11 +632,14 @@ do_atof_calc:
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Render an signed 64-bit integer as text. Store the result in zOut[].
|
||||
** Render an signed 64-bit integer as text. Store the result in zOut[] and
|
||||
** return the length of the string that was stored, in bytes. The value
|
||||
** returned does not include the zero terminator at the end of the output
|
||||
** string.
|
||||
**
|
||||
** The caller must ensure that zOut[] is at least 21 bytes in size.
|
||||
*/
|
||||
void sqlite3Int64ToText(i64 v, char *zOut){
|
||||
int sqlite3Int64ToText(i64 v, char *zOut){
|
||||
int i;
|
||||
u64 x;
|
||||
char zTemp[22];
|
||||
@@ -653,6 +656,7 @@ void sqlite3Int64ToText(i64 v, char *zOut){
|
||||
}while( x );
|
||||
if( v<0 ) zTemp[i--] = '-';
|
||||
memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i);
|
||||
return sizeof(zTemp)-2-i;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+22
-9
@@ -394,7 +394,7 @@ static void applyAffinity(
|
||||
assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL
|
||||
|| affinity==SQLITE_AFF_NUMERIC || affinity==SQLITE_AFF_FLEXNUM );
|
||||
if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
||||
if( (pRec->flags & MEM_Real)==0 ){
|
||||
if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){
|
||||
if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1);
|
||||
}else if( affinity<=SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeIntegerAffinity(pRec);
|
||||
@@ -1150,6 +1150,12 @@ case OP_Halt: {
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
|
||||
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
|
||||
** something is wrong with the code generator. Raise and assertion in order
|
||||
** to bring this to the attention of fuzzers and other testing tools. */
|
||||
assert( pOp->p1!=SQLITE_INTERNAL );
|
||||
|
||||
if( p->pFrame && pOp->p1==SQLITE_OK ){
|
||||
/* Halt the sub-program. Return control to the parent frame. */
|
||||
pFrame = p->pFrame;
|
||||
@@ -3142,7 +3148,7 @@ case OP_TypeCheck: {
|
||||
}
|
||||
case COLTYPE_REAL: {
|
||||
testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real );
|
||||
testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal );
|
||||
assert( (pIn1->flags & MEM_IntReal)==0 );
|
||||
if( pIn1->flags & MEM_Int ){
|
||||
/* When applying REAL affinity, if the result is still an MEM_Int
|
||||
** that will fit in 6 bytes, then change the type to MEM_IntReal
|
||||
@@ -6120,6 +6126,9 @@ case OP_Sort: { /* jump */
|
||||
** If the table or index is not empty, fall through to the following
|
||||
** instruction.
|
||||
**
|
||||
** If P2 is zero, that is an assertion that the P1 table is never
|
||||
** empty and hence the jump will never be taken.
|
||||
**
|
||||
** This opcode leaves the cursor configured to move in forward order,
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
** configured to use Next, not Prev.
|
||||
@@ -6131,6 +6140,8 @@ case OP_Rewind: { /* jump, ncycle */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p5==0 );
|
||||
assert( pOp->p2>=0 && pOp->p2<p->nOp );
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
|
||||
@@ -6150,9 +6161,10 @@ case OP_Rewind: { /* jump, ncycle */
|
||||
}
|
||||
if( rc ) goto abort_due_to_error;
|
||||
pC->nullRow = (u8)res;
|
||||
assert( pOp->p2>0 && pOp->p2<p->nOp );
|
||||
VdbeBranchTaken(res!=0,2);
|
||||
if( res ) goto jump_to_p2;
|
||||
if( pOp->p2>0 ){
|
||||
VdbeBranchTaken(res!=0,2);
|
||||
if( res ) goto jump_to_p2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6958,13 +6970,14 @@ case OP_IntegrityCk: {
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( pOp->p5<db->nDb );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p5) );
|
||||
z = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
|
||||
(int)pnErr->u.i+1, &nErr);
|
||||
rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
|
||||
(int)pnErr->u.i+1, &nErr, &z);
|
||||
sqlite3VdbeMemSetNull(pIn1);
|
||||
if( nErr==0 ){
|
||||
assert( z==0 );
|
||||
}else if( z==0 ){
|
||||
goto no_mem;
|
||||
}else if( rc ){
|
||||
sqlite3_free(z);
|
||||
goto abort_due_to_error;
|
||||
}else{
|
||||
pnErr->u.i -= nErr-1;
|
||||
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
|
||||
|
||||
+28
-22
@@ -114,9 +114,9 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
|
||||
i64 x;
|
||||
assert( (p->flags&MEM_Int)*2==sizeof(x) );
|
||||
memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
|
||||
sqlite3Int64ToText(x, zBuf);
|
||||
p->n = sqlite3Int64ToText(x, zBuf);
|
||||
#else
|
||||
sqlite3Int64ToText(p->u.i, zBuf);
|
||||
p->n = sqlite3Int64ToText(p->u.i, zBuf);
|
||||
#endif
|
||||
}else{
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
|
||||
@@ -124,6 +124,7 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
|
||||
(p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
|
||||
assert( acc.zText==zBuf && acc.mxAlloc<=0 );
|
||||
zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
|
||||
p->n = acc.nChar;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +152,7 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
|
||||
** This routine is for use inside of assert() statements only.
|
||||
*/
|
||||
int sqlite3VdbeMemValidStrRep(Mem *p){
|
||||
Mem tmp;
|
||||
char zBuf[100];
|
||||
char *z;
|
||||
int i, j, incr;
|
||||
@@ -167,7 +169,8 @@ int sqlite3VdbeMemValidStrRep(Mem *p){
|
||||
assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
|
||||
}
|
||||
if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
|
||||
vdbeMemRenderNum(sizeof(zBuf), zBuf, p);
|
||||
memcpy(&tmp, p, sizeof(tmp));
|
||||
vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp);
|
||||
z = p->z;
|
||||
i = j = 0;
|
||||
incr = 1;
|
||||
@@ -436,7 +439,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
|
||||
|
||||
vdbeMemRenderNum(nByte, pMem->z, pMem);
|
||||
assert( pMem->z!=0 );
|
||||
pMem->n = sqlite3Strlen30NN(pMem->z);
|
||||
assert( pMem->n==sqlite3Strlen30NN(pMem->z) );
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem->flags |= MEM_Str|MEM_Term;
|
||||
if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
|
||||
@@ -676,32 +679,35 @@ int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
|
||||
}
|
||||
|
||||
/*
|
||||
** The MEM structure is already a MEM_Real. Try to also make it a
|
||||
** MEM_Int if we can.
|
||||
** The MEM structure is already a MEM_Real or MEM_IntReal. Try to
|
||||
** make it a MEM_Int if we can.
|
||||
*/
|
||||
void sqlite3VdbeIntegerAffinity(Mem *pMem){
|
||||
i64 ix;
|
||||
assert( pMem!=0 );
|
||||
assert( pMem->flags & MEM_Real );
|
||||
assert( pMem->flags & (MEM_Real|MEM_IntReal) );
|
||||
assert( !sqlite3VdbeMemIsRowSet(pMem) );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
||||
|
||||
ix = doubleToInt64(pMem->u.r);
|
||||
|
||||
/* Only mark the value as an integer if
|
||||
**
|
||||
** (1) the round-trip conversion real->int->real is a no-op, and
|
||||
** (2) The integer is neither the largest nor the smallest
|
||||
** possible integer (ticket #3922)
|
||||
**
|
||||
** The second and third terms in the following conditional enforces
|
||||
** the second condition under the assumption that addition overflow causes
|
||||
** values to wrap around.
|
||||
*/
|
||||
if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
|
||||
pMem->u.i = ix;
|
||||
if( pMem->flags & MEM_IntReal ){
|
||||
MemSetTypeFlag(pMem, MEM_Int);
|
||||
}else{
|
||||
i64 ix = doubleToInt64(pMem->u.r);
|
||||
|
||||
/* Only mark the value as an integer if
|
||||
**
|
||||
** (1) the round-trip conversion real->int->real is a no-op, and
|
||||
** (2) The integer is neither the largest nor the smallest
|
||||
** possible integer (ticket #3922)
|
||||
**
|
||||
** The second and third terms in the following conditional enforces
|
||||
** the second condition under the assumption that addition overflow causes
|
||||
** values to wrap around.
|
||||
*/
|
||||
if( pMem->u.r==ix && ix>SMALLEST_INT64 && ix<LARGEST_INT64 ){
|
||||
pMem->u.i = ix;
|
||||
MemSetTypeFlag(pMem, MEM_Int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1620,6 +1620,13 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
|
||||
assert( pWC->a[ii].eOperator==WO_ROWVAL );
|
||||
continue;
|
||||
}
|
||||
if( pWC->a[ii].nChild ){
|
||||
/* If this term has child terms, then they are also part of the
|
||||
** pWC->a[] array. So this term can be ignored, as a LIMIT clause
|
||||
** will only be added if each of the child terms passes the
|
||||
** (leftCursor==iCsr) test below. */
|
||||
continue;
|
||||
}
|
||||
if( pWC->a[ii].leftCursor!=iCsr ) return;
|
||||
}
|
||||
|
||||
|
||||
+4
-8
@@ -2944,8 +2944,7 @@ void sqlite3WindowCodeStep(
|
||||
VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound <expr> */
|
||||
VdbeCoverageNeverNullIf(v, op==OP_Le); /* values previously checked */
|
||||
windowAggFinal(&s, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr);
|
||||
windowReturnOneRow(&s);
|
||||
sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd);
|
||||
@@ -2957,13 +2956,10 @@ void sqlite3WindowCodeStep(
|
||||
}
|
||||
|
||||
if( pMWin->eStart!=TK_UNBOUNDED ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, s.start.csr, 1);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Rewind, s.start.csr);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, s.end.csr, 1);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
sqlite3VdbeAddOp1(v, OP_Rewind, s.current.csr);
|
||||
sqlite3VdbeAddOp1(v, OP_Rewind, s.end.csr);
|
||||
if( regPeer && pOrderBy ){
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1);
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1);
|
||||
|
||||
@@ -2246,6 +2246,19 @@ ifcapable altertable&&vtab {
|
||||
} {main t1 {} {}}
|
||||
}
|
||||
|
||||
# 2022-12-28
|
||||
# The sqlite3_declare_vtab() call that occurs during pragma_table_list
|
||||
# should not cause an authentication failure.
|
||||
#
|
||||
do_test auth-1.359 {
|
||||
proc auth {code arg1 arg2 arg3 arg4 args} {
|
||||
if {$code=="SQLITE_UPDATE"} {
|
||||
return SQLITE_DENY
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
catchsql {SELECT * FROM pragma_table_list WHERE name='xyzzy';}
|
||||
} {0 {}}
|
||||
|
||||
do_test auth-2.1 {
|
||||
proc auth {code arg1 arg2 arg3 arg4 args} {
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
# 2020-01-29
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bestindexA
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
proc vtab_command {method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE x(a, b, c)"
|
||||
}
|
||||
|
||||
xBestIndex {
|
||||
set hdl [lindex $args 0]
|
||||
set clist [$hdl constraints]
|
||||
foreach c $clist {
|
||||
array set C $c
|
||||
lappend ::vtab_constraints [list $C(op) $C(column)]
|
||||
}
|
||||
return [list]
|
||||
}
|
||||
|
||||
xFilter {
|
||||
return ""
|
||||
}
|
||||
|
||||
xFindFunction {
|
||||
foreach {nArg name} $args {}
|
||||
if {$nArg==2 && $name=="even"} {
|
||||
return 152
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
register_tcl_module db
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING tcl(vtab_command);
|
||||
}
|
||||
|
||||
proc do_xbestindex_test {tn sql res} {
|
||||
set script [subst {
|
||||
execsql "$sql"
|
||||
set ::vtab_constraints
|
||||
}]
|
||||
|
||||
uplevel [list do_test $tn $script [list {*}$res]]
|
||||
set ::vtab_constraints [list]
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.1 {
|
||||
SELECT * FROM t1 WHERE a=?
|
||||
} {
|
||||
{eq 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a=? LIMIT 10
|
||||
} {
|
||||
{eq 0}
|
||||
{limit 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.3 {
|
||||
SELECT * FROM t1 WHERE a=? AND (b+1)=? LIMIT 10
|
||||
} {
|
||||
{eq 0}
|
||||
}
|
||||
|
||||
proc error_function {args} { error "not a function!" }
|
||||
db function even error_function
|
||||
|
||||
do_xbestindex_test 1.4 {
|
||||
SELECT * FROM t1 WHERE even(a, ?)
|
||||
} {
|
||||
{152 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.5 {
|
||||
SELECT * FROM t1 WHERE b=10 AND even(a, ?)
|
||||
} {
|
||||
{eq 1}
|
||||
{152 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.6 {
|
||||
SELECT * FROM t1 WHERE b=10 LIMIT 10
|
||||
} {
|
||||
{eq 1}
|
||||
{limit 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.7 {
|
||||
SELECT * FROM t1 WHERE even(b,?) LIMIT 10
|
||||
} {
|
||||
{152 1}
|
||||
{limit 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.8 {
|
||||
SELECT * FROM t1 WHERE b!=? LIMIT 10
|
||||
} {
|
||||
{ne 1}
|
||||
{limit 0}
|
||||
}
|
||||
|
||||
do_xbestindex_test 1.9 {
|
||||
SELECT * FROM t1 WHERE ?=a LIMIT 10
|
||||
} {
|
||||
{eq 0}
|
||||
{limit 0}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# sqlite_commit_hook (tests hook-1..hook-3 inclusive)
|
||||
# sqlite_update_hook (tests hook-4-*)
|
||||
# sqlite_rollback_hook (tests hook-5.*)
|
||||
# sqlite_preupdate_hook (tests hook-7..hook-12)
|
||||
#
|
||||
# $Id: hook.test,v 1.15 2009/04/07 14:14:23 danielk1977 Exp $
|
||||
|
||||
|
||||
+16
-2
@@ -94,14 +94,28 @@ ifcapable {vacuum && !default_autovacuum} {
|
||||
} 1
|
||||
}
|
||||
ifcapable {explain} {
|
||||
do_test interrupt-2.5 {
|
||||
do_test interrupt-2.5.1 {
|
||||
sqlite3_is_interrupted $DB
|
||||
} {0}
|
||||
do_test interrupt-2.5.2 {
|
||||
unset -nocomplain ::interrupt_count
|
||||
set ::interrupt_count 0
|
||||
set sql {EXPLAIN SELECT max(a,b), a, b FROM t1}
|
||||
execsql $sql
|
||||
set rc [catch {db eval $sql {sqlite3_interrupt $DB}} msg]
|
||||
set rc [catch {db eval $sql {
|
||||
sqlite3_interrupt $DB;
|
||||
incr ::interrupt_count [sqlite3_is_interrupted $DB];
|
||||
}} msg]
|
||||
lappend rc $msg
|
||||
} {1 interrupted}
|
||||
do_test interrupt-2.5.3 {
|
||||
set ::interrupt_count
|
||||
} {1}
|
||||
}
|
||||
integrity_check interrupt-2.6
|
||||
do_test interrupt-2.7 {
|
||||
sqlite3_is_interrupted $DB
|
||||
} {0}
|
||||
|
||||
# Ticket #594. If an interrupt occurs in the middle of a transaction
|
||||
# and that transaction is later rolled back, the internal schema tables do
|
||||
|
||||
@@ -95,4 +95,22 @@ do_execsql_test 3.0 {
|
||||
PRAGMA integrity_check;
|
||||
} {a {} ok}
|
||||
|
||||
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a REAL, b AS ('expr') );
|
||||
}
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO t1 VALUES( REPLACE(0, '', 'expr') );
|
||||
}
|
||||
do_execsql_test 4.2 {
|
||||
INSERT INTO t1 SELECT REPLACE(4, '', 'expr');
|
||||
}
|
||||
do_execsql_test 4.3 {
|
||||
SELECT typeof(a), a FROM t1;
|
||||
} {
|
||||
real 0.0
|
||||
real 4.0
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -582,6 +582,59 @@ do_test pragma-3.30 {
|
||||
}
|
||||
} {}
|
||||
|
||||
# The values stored in indexes must be byte-for-byte identical to the
|
||||
# values stored in tables.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test pragma-3.40 {
|
||||
CREATE TABLE t1(
|
||||
a INTEGER PRIMARY KEY,
|
||||
b TEXT COLLATE nocase,
|
||||
c INT COLLATE nocase,
|
||||
d TEXT
|
||||
);
|
||||
INSERT INTO t1(a,b,c,d) VALUES
|
||||
(1, 'one','one','one'),
|
||||
(2, 'two','two','two'),
|
||||
(3, 'three','three','three'),
|
||||
(4, 'four','four','four'),
|
||||
(5, 'five','five','five');
|
||||
CREATE INDEX t1bcd ON t1(b,c,d);
|
||||
CREATE TABLE t2(
|
||||
a INTEGER PRIMARY KEY,
|
||||
b TEXT COLLATE nocase,
|
||||
c INT COLLATE nocase,
|
||||
d TEXT
|
||||
);
|
||||
INSERT INTO t2(a,b,c,d) VALUES
|
||||
(1, 'one','one','one'),
|
||||
(2, 'two','two','TWO'),
|
||||
(3, 'three','THREE','three'),
|
||||
(4, 'FOUR','four','four'),
|
||||
(5, 'FIVE','FIVE','five');
|
||||
CREATE INDEX t2bcd ON t2(b,c,d);
|
||||
CREATE TEMP TABLE saved_schema AS SELECT name, rootpage FROM sqlite_schema;
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_schema
|
||||
SET rootpage=(SELECT rootpage FROM saved_schema WHERE name='t2bcd')
|
||||
WHERE name='t1bcd';
|
||||
UPDATE sqlite_schema
|
||||
SET rootpage=(SELECT rootpage FROM saved_schema WHERE name='t1bcd')
|
||||
WHERE name='t2bcd';
|
||||
PRAGMA Writable_schema=RESET;
|
||||
SELECT integrity_check AS x FROM pragma_integrity_check ORDER BY 1;
|
||||
} {
|
||||
{row 2 missing from index t1bcd}
|
||||
{row 2 missing from index t2bcd}
|
||||
{row 3 values differ from index t1bcd}
|
||||
{row 3 values differ from index t2bcd}
|
||||
{row 4 values differ from index t1bcd}
|
||||
{row 4 values differ from index t2bcd}
|
||||
{row 5 values differ from index t1bcd}
|
||||
{row 5 values differ from index t2bcd}
|
||||
}
|
||||
db eval {DROP TABLE t2}
|
||||
|
||||
# Test modifying the cache_size of an attached database.
|
||||
ifcapable pager_pragmas&&attach {
|
||||
do_test pragma-4.1 {
|
||||
|
||||
@@ -207,4 +207,32 @@ do_test 4.4.2 {
|
||||
list [file exists x/test.db-wal] [file exists w/test.db-wal]
|
||||
} {1 0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that extra ".." in a path are ignored.
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE xyz(x, y, z);
|
||||
INSERT INTO xyz VALUES(1, 2, 3);
|
||||
}
|
||||
|
||||
set path [pwd]
|
||||
set nLink [llength [split $path /]]
|
||||
set path "[string repeat ../ [expr $nLink*2]]..${path}/test.db"
|
||||
|
||||
sqlite3 db2 $path
|
||||
do_execsql_test -db db2 5.1 {
|
||||
SELECT * FROM xyz;
|
||||
} {1 2 3}
|
||||
db close
|
||||
|
||||
forcedelete test.db2
|
||||
file link test.db2 $path
|
||||
sqlite3 db2 test.db2
|
||||
do_execsql_test -db db2 5.2 {
|
||||
SELECT * FROM xyz;
|
||||
} {1 2 3}
|
||||
forcedelete test.db2
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -247,5 +247,16 @@ do_execsql_test 3.131 {
|
||||
SELECT * FROM t2;
|
||||
} {}
|
||||
|
||||
# 2023-01-09 https://sqlite.org/forum/forumpost/c88a671ad083d153
|
||||
#
|
||||
do_execsql_test 4.1 {
|
||||
PRAGMA trusted_schema=OFF;
|
||||
CREATE VIEW test41(x) AS SELECT json_extract('{"a":123}','$.a');
|
||||
SELECT * FROM test41;
|
||||
} 123
|
||||
do_execsql_test 4.2 {
|
||||
PRAGMA trusted_schema=ON;
|
||||
SELECT * FROM test41;
|
||||
} 123
|
||||
|
||||
finish_test
|
||||
|
||||
+4
-4
@@ -123,16 +123,16 @@ do_execsql_test view-1.10 {
|
||||
} {}
|
||||
do_execsql_test view-1.11 {
|
||||
PRAGMA table_info(v9a);
|
||||
} {0 x INT 0 {} 0}
|
||||
} {0 x INTEGER 0 {} 0}
|
||||
do_execsql_test view-1.12 {
|
||||
PRAGMA table_info(v9b);
|
||||
} {0 x INT 0 {} 0}
|
||||
} {0 x INTEGER 0 {} 0}
|
||||
do_execsql_test view-1.13 {
|
||||
PRAGMA table_info(v9c);
|
||||
} {0 x INT 0 {} 0}
|
||||
} {0 x INTEGER 0 {} 0}
|
||||
do_execsql_test view-1.14 {
|
||||
PRAGMA table_info(v9d);
|
||||
} {0 x INT 0 {} 0}
|
||||
} {0 x INTEGER 0 {} 0}
|
||||
|
||||
do_test view-2.1 {
|
||||
execsql {
|
||||
|
||||
@@ -854,5 +854,13 @@ do_execsql_test 17.1 {
|
||||
SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist;
|
||||
} {blob}
|
||||
|
||||
# 2023-01-04
|
||||
# https://sqlite.org/forum/forumpost/d1c96a9032e564f8
|
||||
# Call to fopen() with a NULL filename.
|
||||
#
|
||||
do_catchsql_test 18.1 {
|
||||
SELECT * FROM zipfile(NULL);
|
||||
} {1 {cannot open file: }}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+7
-1
@@ -11,7 +11,13 @@ if uname | grep -i openbsd ; then
|
||||
else
|
||||
# Use these for testing on Linux and Mac OSX:
|
||||
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
|
||||
WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
|
||||
gccvers=`gcc -v 2>&1 | grep '^gcc version'`
|
||||
if test "$gccvers" '<' 'gcc version 6'
|
||||
then
|
||||
WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
|
||||
else
|
||||
WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra -Wimplicit-fallthrough=0"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f sqlite3.c
|
||||
|
||||
Reference in New Issue
Block a user