| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 716782abe939083b7732289d862ddfd84105 with changes in files: |
| 21 | +** 88901fffcd445ccb97e4e379ea15d8b06d87 with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -467,14 +467,14 @@ |
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | 470 | #define SQLITE_VERSION "3.54.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3054000 |
| 472 | | -#define SQLITE_SOURCE_ID "2026-06-26 19:31:46 716782abe939083b7732289d862ddfd841057d3458814f96e5e6d7826ec7fa5c" |
| 472 | +#define SQLITE_SOURCE_ID "2026-07-01 12:11:41 88901fffcd445ccb97e4e379ea15d8b06d87b8170cad0f717c909944ff21851f" |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | | -#define SQLITE_SCM_DATETIME "2026-06-26T19:31:46.902Z" |
| 475 | +#define SQLITE_SCM_DATETIME "2026-07-01T12:11:41.802Z" |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| | @@ -26375,10 +26375,53 @@ |
| 26375 | 26375 | clearYMD_HMS_TZ(p); |
| 26376 | 26376 | rc = 0; |
| 26377 | 26377 | p->nFloor = 0; |
| 26378 | 26378 | } |
| 26379 | 26379 | break; |
| 26380 | + } |
| 26381 | + case 'e': { |
| 26382 | + /* |
| 26383 | + ** end of day |
| 26384 | + ** end of month |
| 26385 | + ** end of year |
| 26386 | + ** |
| 26387 | + ** Move the date forwards to the last millisecond of the current |
| 26388 | + ** day, month or year. |
| 26389 | + */ |
| 26390 | + if( sqlite3_strnicmp(z, "end of ", 7)!=0 ){ |
| 26391 | + break; |
| 26392 | + } |
| 26393 | + if( !p->validJD && !p->validYMD && !p->validHMS ) break; |
| 26394 | + z += 7; |
| 26395 | + computeYMD(p); |
| 26396 | + p->validHMS = 1; |
| 26397 | + p->h = 23; |
| 26398 | + p->m = 59; |
| 26399 | + p->s = 59.999; |
| 26400 | + p->rawS = 0; |
| 26401 | + p->tz = 0; |
| 26402 | + p->validJD = 0; |
| 26403 | + if( sqlite3_stricmp(z,"month")==0 ){ |
| 26404 | + p->D = 1; |
| 26405 | + p->M++; |
| 26406 | + if( p->M>12 ){ |
| 26407 | + p->Y++; |
| 26408 | + p->M = 1; |
| 26409 | + } |
| 26410 | + computeFloor(p); |
| 26411 | + computeJD(p); |
| 26412 | + p->iJD -= (p->nFloor+1)*86400000; |
| 26413 | + clearYMD_HMS_TZ(p); |
| 26414 | + rc = 0; |
| 26415 | + }else if( sqlite3_stricmp(z,"year")==0 ){ |
| 26416 | + p->M = 12; |
| 26417 | + p->D = 31; |
| 26418 | + rc = 0; |
| 26419 | + }else if( sqlite3_stricmp(z,"day")==0 ){ |
| 26420 | + rc = 0; |
| 26421 | + } |
| 26422 | + break; |
| 26380 | 26423 | } |
| 26381 | 26424 | case 'f': { |
| 26382 | 26425 | /* |
| 26383 | 26426 | ** floor |
| 26384 | 26427 | ** |
| | @@ -26478,34 +26521,44 @@ |
| 26478 | 26521 | break; |
| 26479 | 26522 | } |
| 26480 | 26523 | case 'w': { |
| 26481 | 26524 | /* |
| 26482 | 26525 | ** weekday N |
| 26526 | + ** weekday -N |
| 26483 | 26527 | ** |
| 26484 | | - ** Move the date to the same time on the next occurrence of |
| 26485 | | - ** weekday N where 0==Sunday, 1==Monday, and so forth. If the |
| 26486 | | - ** date is already on the appropriate weekday, this is a no-op. |
| 26528 | + ** Move the date forward (for N>=0) or backward (for N<=-0) to the |
| 26529 | + ** same time on the next/previous occurrence of weekday abs(N) |
| 26530 | + ** where 0==Sunday, 1==Monday, and so forth. If the date is already |
| 26531 | + ** on the appropriate weekday, this is a no-op. |
| 26487 | 26532 | */ |
| 26488 | 26533 | if( sqlite3_strnicmp(z, "weekday ", 8)==0 |
| 26489 | | - && sqlite3AtoF(&z[8], &r)>0 |
| 26490 | | - && r>=0.0 && r<7.0 && (n=(int)r)==r ){ |
| 26534 | + && sqlite3AtoF(&z[8], &r)>0 |
| 26535 | + && r>=-6.0 && r<=6.0 |
| 26536 | + && (n=(int)r)==r |
| 26537 | + ){ |
| 26491 | 26538 | sqlite3_int64 Z; |
| 26492 | 26539 | computeYMD_HMS(p); |
| 26493 | 26540 | p->tz = 0; |
| 26494 | 26541 | p->validJD = 0; |
| 26495 | 26542 | computeJD(p); |
| 26496 | 26543 | Z = ((p->iJD + 129600000)/86400000) % 7; |
| 26497 | | - if( Z>n ) Z -= 7; |
| 26498 | | - p->iJD += (n - Z)*86400000; |
| 26544 | + if( n<0 ) n = -n; |
| 26545 | + if( Z!=n ){ |
| 26546 | + if( Z>n ) Z -= 7; |
| 26547 | + p->iJD += (n - Z)*86400000; |
| 26548 | + if( strchr(z+8,'-')!=0 ) p->iJD -= 7*86400000; |
| 26549 | + } |
| 26499 | 26550 | clearYMD_HMS_TZ(p); |
| 26500 | 26551 | rc = 0; |
| 26501 | 26552 | } |
| 26502 | 26553 | break; |
| 26503 | 26554 | } |
| 26504 | 26555 | case 's': { |
| 26505 | 26556 | /* |
| 26506 | | - ** start of TTTTT |
| 26557 | + ** start of day |
| 26558 | + ** start of month |
| 26559 | + ** start of year |
| 26507 | 26560 | ** |
| 26508 | 26561 | ** Move the date backwards to the beginning of the current day, |
| 26509 | 26562 | ** or month or year. |
| 26510 | 26563 | ** |
| 26511 | 26564 | ** subsecond |
| | @@ -33777,10 +33830,11 @@ |
| 33777 | 33830 | ** work (enlarging the buffer) using tail recursion, so that the |
| 33778 | 33831 | ** sqlite3_str_append() routine can use fast calling semantics. |
| 33779 | 33832 | */ |
| 33780 | 33833 | static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ |
| 33781 | 33834 | N = sqlite3StrAccumEnlarge(p, N); |
| 33835 | + assert( z!=0 || N==0 ); |
| 33782 | 33836 | if( N>0 ){ |
| 33783 | 33837 | memcpy(&p->zText[p->nChar], z, N); |
| 33784 | 33838 | p->nChar += N; |
| 33785 | 33839 | } |
| 33786 | 33840 | } |
| | @@ -74498,12 +74552,15 @@ |
| 74498 | 74552 | /* Freeblock off the end of the page */ |
| 74499 | 74553 | return SQLITE_CORRUPT_PAGE(pPage); |
| 74500 | 74554 | } |
| 74501 | 74555 | next = get2byte(&data[pc]); |
| 74502 | 74556 | size = get2byte(&data[pc+2]); |
| 74503 | | - if( size<4 ){ |
| 74504 | | - /* Minimum freeblock size is 4 */ |
| 74557 | + if( size<4 && sqlite3FaultSim(422)==SQLITE_OK ){ |
| 74558 | + /* Minimum freeblock size is 4. Enable fault-sim 422 to disable this |
| 74559 | + ** check to reach interesting error stats. However, disabling this |
| 74560 | + ** check can cause assertion faults due to min-heap overflow. All |
| 74561 | + ** fault-sims are for testing use only, but this one especially so. */ |
| 74505 | 74562 | return SQLITE_CORRUPT_PAGE(pPage); |
| 74506 | 74563 | } |
| 74507 | 74564 | nFree = nFree + size; |
| 74508 | 74565 | if( next<pc+size+4 ) break; |
| 74509 | 74566 | pc = next; |
| | @@ -83387,11 +83444,11 @@ |
| 83387 | 83444 | checkAppendMsg(pCheck, "Child page depth differs"); |
| 83388 | 83445 | depth = d2; |
| 83389 | 83446 | } |
| 83390 | 83447 | }else{ |
| 83391 | 83448 | /* Populate the coverage-checking heap for leaf pages */ |
| 83392 | | - assert( heap[0] < pCheck->mxHeap ); |
| 83449 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); |
| 83393 | 83450 | btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1)); |
| 83394 | 83451 | } |
| 83395 | 83452 | } |
| 83396 | 83453 | *piMinKey = maxKey; |
| 83397 | 83454 | |
| | @@ -83407,11 +83464,11 @@ |
| 83407 | 83464 | heap[0] = 0; |
| 83408 | 83465 | for(i=nCell-1; i>=0; i--){ |
| 83409 | 83466 | u32 size; |
| 83410 | 83467 | pc = get2byteAligned(&data[cellStart+i*2]); |
| 83411 | 83468 | size = pPage->xCellSize(pPage, &data[pc]); |
| 83412 | | - assert( heap[0] < pCheck->mxHeap ); |
| 83469 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); |
| 83413 | 83470 | btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); |
| 83414 | 83471 | } |
| 83415 | 83472 | } |
| 83416 | 83473 | assert( heap!=0 ); |
| 83417 | 83474 | /* Add the freeblocks to the min-heap |
| | @@ -83424,11 +83481,11 @@ |
| 83424 | 83481 | while( i>0 ){ |
| 83425 | 83482 | int size, j; |
| 83426 | 83483 | assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ |
| 83427 | 83484 | size = get2byte(&data[i+2]); |
| 83428 | 83485 | assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */ |
| 83429 | | - assert( heap[0] < pCheck->mxHeap ); |
| 83486 | + assert( heap!=0 && heap[0] < pCheck->mxHeap ); |
| 83430 | 83487 | btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); |
| 83431 | 83488 | /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a |
| 83432 | 83489 | ** big-endian integer which is the offset in the b-tree page of the next |
| 83433 | 83490 | ** freeblock in the chain, or zero if the freeblock is the last on the |
| 83434 | 83491 | ** chain. */ |
| | @@ -84047,12 +84104,14 @@ |
| 84047 | 84104 | ** If the "temp" database is requested, it may need to be opened by this |
| 84048 | 84105 | ** function. If an error occurs while doing so, return 0 and write an |
| 84049 | 84106 | ** error message to pErrorDb. |
| 84050 | 84107 | */ |
| 84051 | 84108 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ |
| 84052 | | - int i = sqlite3FindDbName(pDb, zDb); |
| 84109 | + int i; |
| 84053 | 84110 | |
| 84111 | + assert( pDb!=0 ); |
| 84112 | + i = sqlite3FindDbName(pDb, zDb); |
| 84054 | 84113 | if( i==1 ){ |
| 84055 | 84114 | Parse sParse; |
| 84056 | 84115 | int rc = 0; |
| 84057 | 84116 | sqlite3ParseObjectInit(&sParse,pDb); |
| 84058 | 84117 | if( sqlite3OpenTempDatabase(&sParse) ){ |
| | @@ -128460,18 +128519,15 @@ |
| 128460 | 128519 | |
| 128461 | 128520 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128462 | 128521 | /* |
| 128463 | 128522 | ** Return true if zName is a shadow table name in the current database |
| 128464 | 128523 | ** connection. |
| 128465 | | -** |
| 128466 | | -** zName is temporarily modified while this routine is running, but is |
| 128467 | | -** restored to its original value prior to this routine returning. |
| 128468 | 128524 | */ |
| 128469 | 128525 | SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ |
| 128470 | 128526 | const char *zTail; /* Pointer to the last "_" in zName */ |
| 128471 | 128527 | Table *pTab; /* Table that zName is a shadow of */ |
| 128472 | | - char *zCopy; |
| 128528 | + char *zCopy; /* Transient copy of zName after last "_" */ |
| 128473 | 128529 | zTail = strrchr(zName, '_'); |
| 128474 | 128530 | if( zTail==0 ) return 0; |
| 128475 | 128531 | zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName)); |
| 128476 | 128532 | pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0; |
| 128477 | 128533 | sqlite3DbFree(db, zCopy); |
| | @@ -148036,10 +148092,11 @@ |
| 148036 | 148092 | ** |
| 148037 | 148093 | ** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which |
| 148038 | 148094 | ** is generated by Lemon. |
| 148039 | 148095 | */ |
| 148040 | 148096 | SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){ |
| 148097 | + assert( db!=0 ); |
| 148041 | 148098 | memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ); |
| 148042 | 148099 | memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); |
| 148043 | 148100 | assert( db->pParse!=pParse ); |
| 148044 | 148101 | pParse->pOuterParse = db->pParse; |
| 148045 | 148102 | db->pParse = pParse; |
| | @@ -149134,11 +149191,10 @@ |
| 149134 | 149191 | pRight->fg.isOn = 1; |
| 149135 | 149192 | p->selFlags |= SF_OnToWhere; |
| 149136 | 149193 | } |
| 149137 | 149194 | |
| 149138 | 149195 | if( pRight->fg.isTabFunc && joinType==EP_OuterON && pRight->u1.pFuncArg ){ |
| 149139 | | - assert( IsVirtual(pRightTab) ); |
| 149140 | 149196 | p->selFlags |= SF_OnToWhere; |
| 149141 | 149197 | } |
| 149142 | 149198 | } |
| 149143 | 149199 | return 0; |
| 149144 | 149200 | } |
| | @@ -162084,10 +162140,12 @@ |
| 162084 | 162140 | char *zErr = 0; |
| 162085 | 162141 | rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); |
| 162086 | 162142 | if( rc!=SQLITE_OK ){ |
| 162087 | 162143 | sqlite3ErrorMsg(pParse, "%s", zErr); |
| 162088 | 162144 | pParse->rc = rc; |
| 162145 | + }else{ |
| 162146 | + sqlite3MarkAllShadowTablesOf(db, pTab); |
| 162089 | 162147 | } |
| 162090 | 162148 | sqlite3DbFree(db, zErr); |
| 162091 | 162149 | } |
| 162092 | 162150 | |
| 162093 | 162151 | return rc; |
| | @@ -168316,10 +168374,14 @@ |
| 168316 | 168374 | Expr *pColRef; |
| 168317 | 168375 | Expr *pTerm; |
| 168318 | 168376 | if( pItem->fg.isTabFunc==0 ) return; |
| 168319 | 168377 | pTab = pItem->pSTab; |
| 168320 | 168378 | assert( pTab!=0 ); |
| 168379 | + if( !IsVirtual(pTab) ){ |
| 168380 | + sqlite3ErrorMsg(pParse, "'%s' is not a function", pItem->zName); |
| 168381 | + return; |
| 168382 | + } |
| 168321 | 168383 | pArgs = pItem->u1.pFuncArg; |
| 168322 | 168384 | if( pArgs==0 ) return; |
| 168323 | 168385 | for(j=k=0; j<pArgs->nExpr; j++){ |
| 168324 | 168386 | Expr *pRhs; |
| 168325 | 168387 | u32 joinType; |
| | @@ -253274,10 +253336,14 @@ |
| 253274 | 253336 | const u8 *a = pIter->pLeaf->p; |
| 253275 | 253337 | int iTermOff = 0; |
| 253276 | 253338 | |
| 253277 | 253339 | pIter->iPgidxOff = pIter->pLeaf->szLeaf; |
| 253278 | 253340 | pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff); |
| 253341 | + if( iTermOff > pIter->pLeaf->szLeaf ){ |
| 253342 | + p->rc = FTS5_CORRUPT; |
| 253343 | + return; |
| 253344 | + } |
| 253279 | 253345 | pIter->iLeafOffset = iTermOff; |
| 253280 | 253346 | fts5SegIterLoadTerm(p, pIter, 0); |
| 253281 | 253347 | fts5SegIterLoadNPos(p, pIter); |
| 253282 | 253348 | if( bDlidx ) fts5SegIterLoadDlidx(p, pIter); |
| 253283 | 253349 | |
| | @@ -258983,11 +259049,11 @@ |
| 258983 | 259049 | iRowidOff = fts5LeafFirstRowidOff(pLeaf); |
| 258984 | 259050 | if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){ |
| 258985 | 259051 | FTS5_CORRUPT_ROWID(p, iRow); |
| 258986 | 259052 | }else{ |
| 258987 | 259053 | iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); |
| 258988 | | - if( iOff+nTerm>pLeaf->szLeaf ){ |
| 259054 | + if( (i64)iOff+(i64)nTerm>(i64)pLeaf->szLeaf ){ |
| 258989 | 259055 | FTS5_CORRUPT_ROWID(p, iRow); |
| 258990 | 259056 | }else{ |
| 258991 | 259057 | res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); |
| 258992 | 259058 | if( res==0 ) res = nTerm - nIdxTerm; |
| 258993 | 259059 | if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow); |
| | @@ -263631,11 +263697,11 @@ |
| 263631 | 263697 | int nArg, /* Number of args */ |
| 263632 | 263698 | sqlite3_value **apUnused /* Function arguments */ |
| 263633 | 263699 | ){ |
| 263634 | 263700 | assert( nArg==0 ); |
| 263635 | 263701 | UNUSED_PARAM2(nArg, apUnused); |
| 263636 | | - sqlite3_result_text(pCtx, "fts5: 2026-06-26 19:31:46 716782abe939083b7732289d862ddfd841057d3458814f96e5e6d7826ec7fa5c", -1, SQLITE_TRANSIENT); |
| 263702 | + sqlite3_result_text(pCtx, "fts5: 2026-07-01 12:11:41 88901fffcd445ccb97e4e379ea15d8b06d87b8170cad0f717c909944ff21851f", -1, SQLITE_TRANSIENT); |
| 263637 | 263703 | } |
| 263638 | 263704 | |
| 263639 | 263705 | /* |
| 263640 | 263706 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 263641 | 263707 | ** |
| 263642 | 263708 | |