erdbpro 2.4.5 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/assets/index-Bmk-1vOU.js +12701 -0
  2. package/dist/assets/index-DJM3xl0X.js +12701 -0
  3. package/dist/index.html +1 -1
  4. package/dist-server/index.js +1 -1
  5. package/dist-server/node_modules/better-sqlite3/build/Makefile +2 -2
  6. package/dist-server/node_modules/better-sqlite3/build/Release/.deps/4292fa9a667d77b27488aa109b010a85bce8e4e7a1c7aa0370cea902395c3866.intermediate.d +1 -1
  7. package/dist-server/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/better_sqlite3/src/better_sqlite3.o.d.raw +82 -0
  8. package/dist-server/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o.d +4 -0
  9. package/dist-server/node_modules/better-sqlite3/build/Release/.deps/Release/sqlite3.a.d +1 -0
  10. package/dist-server/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
  11. package/dist-server/node_modules/better-sqlite3/build/Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o +0 -0
  12. package/dist-server/node_modules/better-sqlite3/build/Release/sqlite3.a +0 -0
  13. package/dist-server/node_modules/better-sqlite3/deps/download.sh +1 -1
  14. package/dist-server/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +692 -176
  15. package/dist-server/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +17 -5
  16. package/dist-server/node_modules/better-sqlite3/package.json +1 -1
  17. package/dist-server/node_modules/better-sqlite3/src/better_sqlite3.cpp +1 -1
  18. package/dist-server/node_modules/better-sqlite3/src/util/helpers.cpp +1 -1
  19. package/dist-server/node_modules/better-sqlite3/src/util/macros.cpp +8 -1
  20. package/menubar/ERDBProTray.app/Contents/Info.plist +20 -0
  21. package/menubar/ERDBProTray.app/Contents/MacOS/ERDBProTray +0 -0
  22. package/menubar/ERDBProTray.swift +129 -0
  23. package/menubar/erdbpro-tray +0 -0
  24. package/menubar/icon.svg +14 -0
  25. package/menubar/launch.sh +4 -0
  26. package/menubar/tray.sh +59 -0
  27. package/package.json +9 -7
@@ -1,6 +1,6 @@
1
1
  /******************************************************************************
2
2
  ** This file is an amalgamation of many separate C source files from SQLite
3
- ** version 3.53.1. By combining all the individual C code files into this
3
+ ** version 3.53.2. By combining all the individual C code files into this
4
4
  ** single large file, the entire code can be compiled as a single translation
5
5
  ** unit. This allows many compilers to do optimizations that would not be
6
6
  ** possible if the files were compiled separately. Performance improvements
@@ -18,7 +18,7 @@
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
- ** c88b22011a54b4f6fbd149e9f8e4de77658c with changes in files:
21
+ ** d6e03d8c777cfa2d35e3b60d8ec3e0187f3e with changes in files:
22
22
  **
23
23
  **
24
24
  */
@@ -468,12 +468,12 @@ extern "C" {
468
468
  ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
469
469
  ** [sqlite_version()] and [sqlite_source_id()].
470
470
  */
471
- #define SQLITE_VERSION "3.53.1"
472
- #define SQLITE_VERSION_NUMBER 3053001
473
- #define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9"
471
+ #define SQLITE_VERSION "3.53.2"
472
+ #define SQLITE_VERSION_NUMBER 3053002
473
+ #define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
474
474
  #define SQLITE_SCM_BRANCH "branch-3.53"
475
- #define SQLITE_SCM_TAGS "release version-3.53.1"
476
- #define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z"
475
+ #define SQLITE_SCM_TAGS "release version-3.53.2"
476
+ #define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
477
477
 
478
478
  /*
479
479
  ** CAPI3REF: Run-Time Library Version Numbers
@@ -13175,11 +13175,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
13175
13175
  ** database behave as if they were declared with "ON UPDATE NO ACTION ON
13176
13176
  ** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
13177
13177
  ** or SET DEFAULT.
13178
+ **
13179
+ ** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
13180
+ ** Sometimes, a changeset contains two or more update statements such that
13181
+ ** although after applying all updates the database will contain no
13182
+ ** constraint violations, no single update can be applied before the others.
13183
+ ** The simplest example of this is a pair of UPDATEs that have "swapped"
13184
+ ** two column values with a UNIQUE constraint.
13185
+ ** <p>
13186
+ ** Usually, sqlite3changeset_apply() and similar functions work hard to try
13187
+ ** to find a way to apply such a changeset. However, if this flag is set,
13188
+ ** then all such updates are considered CONSTRAINT conflicts.
13178
13189
  */
13179
13190
  #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
13180
13191
  #define SQLITE_CHANGESETAPPLY_INVERT 0x0002
13181
13192
  #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
13182
13193
  #define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
13194
+ #define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
13183
13195
 
13184
13196
  /*
13185
13197
  ** CAPI3REF: Constants Passed To The Conflict Handler
@@ -22449,7 +22461,15 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void);
22449
22461
  SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
22450
22462
  SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
22451
22463
  SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
22452
- SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
22464
+ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
22465
+ Parse *pParse, /* Parse context */
22466
+ SrcList *pSrc, /* Table to add constraint to */
22467
+ Token *pFirst, /* First token of new constraint */
22468
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
22469
+ const char *zExpr, /* Text of CHECK expression */
22470
+ int nExpr, /* Size of pExpr in bytes */
22471
+ Expr *pExpr /* The parsed CHECK expression */
22472
+ );
22453
22473
  SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
22454
22474
  SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
22455
22475
  SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
@@ -33258,8 +33278,8 @@ SQLITE_API void sqlite3_str_vappendf(
33258
33278
  ** all control characters, and for backslash itself.
33259
33279
  ** For %#Q, do the same but only if there is at least
33260
33280
  ** one control character. */
33261
- u32 nBack = 0;
33262
- u32 nCtrl = 0;
33281
+ i64 nBack = 0;
33282
+ i64 nCtrl = 0;
33263
33283
  for(k=0; k<i; k++){
33264
33284
  if( escarg[k]=='\\' ){
33265
33285
  nBack++;
@@ -45308,9 +45328,9 @@ static int unixShmMap(
45308
45328
  nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
45309
45329
 
45310
45330
  if( pShmNode->nRegion<nReqRegion ){
45311
- char **apNew; /* New apRegion[] array */
45312
- int nByte = nReqRegion*szRegion; /* Minimum required file size */
45313
- struct stat sStat; /* Used by fstat() */
45331
+ char **apNew; /* New apRegion[] array */
45332
+ i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
45333
+ struct stat sStat; /* Used by fstat() */
45314
45334
 
45315
45335
  pShmNode->szRegion = szRegion;
45316
45336
 
@@ -45341,7 +45361,7 @@ static int unixShmMap(
45341
45361
  */
45342
45362
  else{
45343
45363
  static const int pgsz = 4096;
45344
- int iPg;
45364
+ i64 iPg;
45345
45365
 
45346
45366
  /* Write to the last byte of each newly allocated or extended page */
45347
45367
  assert( (nByte % pgsz)==0 );
@@ -45367,8 +45387,8 @@ static int unixShmMap(
45367
45387
  }
45368
45388
  pShmNode->apRegion = apNew;
45369
45389
  while( pShmNode->nRegion<nReqRegion ){
45370
- int nMap = szRegion*nShmPerMap;
45371
- int i;
45390
+ i64 nMap = (i64)szRegion*(i64)nShmPerMap;
45391
+ i64 i;
45372
45392
  void *pMem;
45373
45393
  if( pShmNode->hShm>=0 ){
45374
45394
  pMem = osMmap(0, nMap,
@@ -53342,7 +53362,7 @@ static int winShmMap(
53342
53362
  if( pShmNode->nRegion<=iRegion ){
53343
53363
  HANDLE hShared = pShmNode->hSharedShm;
53344
53364
  struct ShmRegion *apNew; /* New aRegion[] array */
53345
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
53365
+ i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
53346
53366
  sqlite3_int64 sz; /* Current size of wal-index file */
53347
53367
 
53348
53368
  pShmNode->szRegion = szRegion;
@@ -53373,7 +53393,7 @@ static int winShmMap(
53373
53393
 
53374
53394
  /* Map the requested memory region into this processes address space. */
53375
53395
  apNew = (struct ShmRegion*)sqlite3_realloc64(
53376
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
53396
+ pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
53377
53397
  );
53378
53398
  if( !apNew ){
53379
53399
  rc = SQLITE_IOERR_NOMEM_BKPT;
@@ -53395,15 +53415,14 @@ static int winShmMap(
53395
53415
  #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
53396
53416
  hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
53397
53417
  #endif
53398
-
53399
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
53418
+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
53400
53419
  osGetCurrentProcessId(), pShmNode->nRegion, nByte,
53401
53420
  hMap ? "ok" : "failed"));
53402
53421
  if( hMap ){
53403
- int iOffset = pShmNode->nRegion*szRegion;
53422
+ i64 iOffset = pShmNode->nRegion*szRegion;
53404
53423
  int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
53405
53424
  pMap = osMapViewOfFile(hMap, flags,
53406
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
53425
+ 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
53407
53426
  );
53408
53427
  OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
53409
53428
  osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
@@ -53425,7 +53444,7 @@ static int winShmMap(
53425
53444
 
53426
53445
  shmpage_out:
53427
53446
  if( pShmNode->nRegion>iRegion ){
53428
- int iOffset = iRegion*szRegion;
53447
+ i64 iOffset = (i64)iRegion*(i64)szRegion;
53429
53448
  int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
53430
53449
  char *p = (char *)pShmNode->aRegion[iRegion].pMap;
53431
53450
  *pp = (void *)&p[iOffsetShift];
@@ -62153,7 +62172,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
62153
62172
  if( rc!=SQLITE_OK ) goto delsuper_out;
62154
62173
  nSuperPtr = 1 + (i64)pVfs->mxPathname;
62155
62174
  assert( nSuperJournal>=0 && nSuperPtr>0 );
62156
- zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
62175
+ zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
62157
62176
  if( !zFree ){
62158
62177
  rc = SQLITE_NOMEM_BKPT;
62159
62178
  goto delsuper_out;
@@ -62414,10 +62433,10 @@ static int pager_playback(Pager *pPager, int isHot){
62414
62433
  **
62415
62434
  ** TODO: Technically the following is an error because it assumes that
62416
62435
  ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
62417
- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
62436
+ ** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
62418
62437
  ** mxPathname is 512, which is the same as the minimum allowable value
62419
- ** for pageSize.
62420
- */
62438
+ ** for pageSize, and so this assumption holds. But it might not for some
62439
+ ** custom VFS. */
62421
62440
  zSuper = pPager->pTmpSpace;
62422
62441
  rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
62423
62442
  if( rc==SQLITE_OK && zSuper[0] ){
@@ -78307,7 +78326,9 @@ static int accessPayload(
78307
78326
  ** means "not yet known" (the cache is lazily populated).
78308
78327
  */
78309
78328
  if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
78310
- int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
78329
+ i64 nOvfl = pCur->info.nPayload;
78330
+ testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
78331
+ nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
78311
78332
  if( pCur->aOverflow==0
78312
78333
  || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
78313
78334
  ){
@@ -78412,6 +78433,12 @@ static int accessPayload(
78412
78433
  (eOp==0 ? PAGER_GET_READONLY : 0)
78413
78434
  );
78414
78435
  if( rc==SQLITE_OK ){
78436
+ if( eOp!=0
78437
+ && (sqlite3PagerPageRefcount(pDbPage)!=1
78438
+ || NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit)) ){
78439
+ sqlite3PagerUnref(pDbPage);
78440
+ return SQLITE_CORRUPT_PAGE(pPage);
78441
+ }
78415
78442
  aPayload = sqlite3PagerGetData(pDbPage);
78416
78443
  nextPage = get4byte(aPayload);
78417
78444
  rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
@@ -111100,6 +111127,7 @@ static int lookupName(
111100
111127
  pExpr->op = TK_FUNCTION;
111101
111128
  pExpr->u.zToken = "coalesce";
111102
111129
  pExpr->x.pList = pFJMatch;
111130
+ pExpr->affExpr = SQLITE_AFF_DEFER;
111103
111131
  cnt = 1;
111104
111132
  goto lookupname_end;
111105
111133
  }else{
@@ -111268,6 +111296,26 @@ static int exprProbability(Expr *p){
111268
111296
  return (int)(r*134217728.0);
111269
111297
  }
111270
111298
 
111299
+ /*
111300
+ ** Set the EP_SubtArg property on every expression inside of
111301
+ ** pList. If any subexpression is actually a subquery, then
111302
+ ** also set the EP_SubtArg property on the first result-set
111303
+ ** column of that subquery.
111304
+ */
111305
+ static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
111306
+ int nn, ii;
111307
+ nn = pList ? pList->nExpr : 0;
111308
+ for(ii=0; ii<nn; ii++){
111309
+ Expr *pExpr = pList->a[ii].pExpr;
111310
+ ExprSetProperty(pExpr, EP_SubtArg);
111311
+ if( pExpr->op==TK_SELECT ){
111312
+ assert( ExprUseXSelect(pExpr) );
111313
+ assert( pExpr->x.pSelect!=0 );
111314
+ resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
111315
+ }
111316
+ }
111317
+ }
111318
+
111271
111319
  /*
111272
111320
  ** This routine is callback for sqlite3WalkExpr().
111273
111321
  **
@@ -111512,10 +111560,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
111512
111560
  if( (pDef->funcFlags & SQLITE_SUBTYPE)
111513
111561
  || ExprHasProperty(pExpr, EP_SubtArg)
111514
111562
  ){
111515
- int ii;
111516
- for(ii=0; ii<n; ii++){
111517
- ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
111518
- }
111563
+ resolveSetExprSubtypeArg(pList);
111519
111564
  }
111520
111565
 
111521
111566
  if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
@@ -116910,7 +116955,16 @@ static void sqlite3ExprCodeIN(
116910
116955
  CollSeq *pColl;
116911
116956
  int r3 = sqlite3GetTempReg(pParse);
116912
116957
  p = sqlite3VectorFieldSubexpr(pLeft, i);
116913
- pColl = sqlite3ExprCollSeq(pParse, p);
116958
+ if( ExprUseXSelect(pExpr) ){
116959
+ Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
116960
+ pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
116961
+ }else{
116962
+ /* If the RHS of the IN(...) expression are scalar expressions, do
116963
+ ** not consider their collation sequences. The documentation says
116964
+ ** "The collating sequence used for expressions of the form "x IN (y, z,
116965
+ ** ...)" is the collating sequence of x.". */
116966
+ pColl = sqlite3ExprCollSeq(pParse, p);
116967
+ }
116914
116968
  sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
116915
116969
  sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
116916
116970
  (void*)pColl, P4_COLLSEQ);
@@ -117333,26 +117387,37 @@ static int exprCodeInlineFunction(
117333
117387
  }
117334
117388
 
117335
117389
  /*
117336
- ** Expression Node callback for sqlite3ExprCanReturnSubtype().
117390
+ ** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
117391
+ ** pExpr is able to return a subtype, set pWalker->eCode and abort
117392
+ ** the search. If pExpr can never return a subtype, prune search.
117393
+ **
117394
+ ** The only expressions that can return a subtype are:
117395
+ **
117396
+ ** 1. A function
117397
+ ** 2. The no-op "+" operator
117398
+ ** 3. A CASE...END expression
117399
+ ** 4. A CAST() expression
117400
+ ** 5. A "expr COLLATE colseq" expression.
117337
117401
  **
117338
- ** Only a function call is able to return a subtype. So if the node
117339
- ** is not a function call, return WRC_Prune immediately.
117402
+ ** For any other kind of expression, prune the search.
117340
117403
  **
117341
- ** A function call is able to return a subtype if it has the
117342
- ** SQLITE_RESULT_SUBTYPE property.
117404
+ ** For case 1, the expression can yield a subtype if the function has
117405
+ ** the SQLITE_RESULT_SUBTYPE property. Functions can also return
117406
+ ** a subtype (via sqlite3_result_value()) if any of the arguments can
117407
+ ** return a subtype.
117343
117408
  **
117344
- ** Assume that every function is able to pass-through a subtype from
117345
- ** one of its argument (using sqlite3_result_value()). Most functions
117346
- ** are not this way, but we don't have a mechanism to distinguish those
117347
- ** that are from those that are not, so assume they all work this way.
117348
- ** That means that if one of its arguments is another function and that
117349
- ** other function is able to return a subtype, then this function is
117350
- ** able to return a subtype.
117409
+ ** In all cases 1 through 5, the expression might also return a subtype
117410
+ ** if any operand can return a subtype.
117351
117411
  */
117352
117412
  static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
117353
117413
  int n;
117354
117414
  FuncDef *pDef;
117355
117415
  sqlite3 *db;
117416
+ if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
117417
+ || pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
117418
+ ){
117419
+ return WRC_Continue;
117420
+ }
117356
117421
  if( pExpr->op!=TK_FUNCTION ){
117357
117422
  return WRC_Prune;
117358
117423
  }
@@ -117362,7 +117427,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
117362
117427
  pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
117363
117428
  if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
117364
117429
  pWalker->eCode = 1;
117365
- return WRC_Prune;
117430
+ return WRC_Abort;
117366
117431
  }
117367
117432
  return WRC_Continue;
117368
117433
  }
@@ -123340,19 +123405,31 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
123340
123405
  SrcList *pSrc, /* Table to add constraint to */
123341
123406
  Token *pFirst, /* First token of new constraint */
123342
123407
  Token *pName, /* Name of new constraint. NULL if name omitted. */
123343
- const char *pExpr, /* Text of CHECK expression */
123344
- int nExpr /* Size of pExpr in bytes */
123408
+ const char *zExpr, /* Text of CHECK expression */
123409
+ int nExpr, /* Size of pExpr in bytes */
123410
+ Expr *pExpr /* The parsed CHECK expression */
123345
123411
  ){
123346
123412
  Table *pTab = 0; /* Table identified by pSrc */
123347
123413
  int iDb = 0; /* Which schema does pTab live in */
123348
123414
  const char *zDb = 0; /* Name of the schema in which pTab lives */
123349
123415
  const char *pCons = 0; /* Text of the constraint */
123350
123416
  int nCons; /* Bytes of text to use from pCons[] */
123417
+ int rc; /* Result from error checking pExpr */
123351
123418
 
123352
123419
  /* Look up the table being altered. */
123353
123420
  assert( pSrc->nSrc==1 );
123354
123421
  pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
123355
- if( !pTab ) return;
123422
+ if( !pTab ){
123423
+ sqlite3ExprDelete(pParse->db, pExpr);
123424
+ return;
123425
+ }
123426
+
123427
+ /* Verify that the new CHECK constraint does not contain any
123428
+ ** internal-use-only function. Forum post 2026-05-10T01:11:28Z
123429
+ */
123430
+ rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
123431
+ sqlite3ExprDelete(pParse->db, pExpr);
123432
+ if( rc ) return;
123356
123433
 
123357
123434
  /* If this new constraint has a name, check that it is not a duplicate of
123358
123435
  ** an existing constraint. It is an error if it is. */
@@ -123373,7 +123450,7 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
123373
123450
  sqlite3NestedParse(pParse,
123374
123451
  "SELECT sqlite_fail('constraint failed', %d) "
123375
123452
  "FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
123376
- SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
123453
+ SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
123377
123454
  );
123378
123455
 
123379
123456
  /* Edit the SQL for the named table. */
@@ -134050,9 +134127,18 @@ static void printfFunc(
134050
134127
  sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
134051
134128
  str.printfFlags = SQLITE_PRINTF_SQLFUNC;
134052
134129
  sqlite3_str_appendf(&str, zFormat, &x);
134053
- n = str.nChar;
134054
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
134055
- SQLITE_DYNAMIC);
134130
+ if( str.accError==SQLITE_OK ){
134131
+ n = str.nChar;
134132
+ sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
134133
+ SQLITE_DYNAMIC);
134134
+ }else{
134135
+ if( str.accError==SQLITE_NOMEM ){
134136
+ sqlite3_result_error_nomem(context);
134137
+ }else{
134138
+ sqlite3_result_error_toobig(context);
134139
+ }
134140
+ sqlite3_str_reset(&str);
134141
+ }
134056
134142
  }
134057
134143
  }
134058
134144
 
@@ -135690,11 +135776,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
135690
135776
  assert( p->cnt>0 );
135691
135777
  p->cnt--;
135692
135778
  if( !p->approx ){
135693
- if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
135694
- p->ovrfl = 1;
135695
- p->approx = 1;
135779
+ i64 x = p->iSum;
135780
+ if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
135781
+ p->iSum = x;
135782
+ return;
135696
135783
  }
135697
- }else if( type==SQLITE_INTEGER ){
135784
+ p->ovrfl = 1;
135785
+ p->approx = 1;
135786
+ kahanBabuskaNeumaierInit(p, p->iSum);
135787
+ }
135788
+ if( type==SQLITE_INTEGER ){
135698
135789
  i64 iVal = sqlite3_value_int64(argv[0]);
135699
135790
  if( iVal!=SMALLEST_INT64 ){
135700
135791
  kahanBabuskaNeumaierStepInt64(p, -iVal);
@@ -136667,47 +136758,46 @@ static void percentSort(double *a, unsigned int n){
136667
136758
  int i; /* Loop counter */
136668
136759
  double rPivot; /* The pivot value */
136669
136760
 
136670
- assert( n>=2 );
136671
- if( a[0]>a[n-1] ){
136672
- SWAP_DOUBLE(a[0],a[n-1])
136673
- }
136674
- if( n==2 ) return;
136675
- iGt = n-1;
136676
- i = n/2;
136677
- if( a[0]>a[i] ){
136678
- SWAP_DOUBLE(a[0],a[i])
136679
- }else if( a[i]>a[iGt] ){
136680
- SWAP_DOUBLE(a[i],a[iGt])
136681
- }
136682
- if( n==3 ) return;
136683
- rPivot = a[i];
136684
- iLt = i = 1;
136685
- do{
136686
- if( a[i]<rPivot ){
136687
- if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
136688
- iLt++;
136689
- i++;
136690
- }else if( a[i]>rPivot ){
136691
- do{
136692
- iGt--;
136693
- }while( iGt>i && a[iGt]>rPivot );
136761
+ while( n>=2 ){
136762
+ if( a[0]>a[n-1] ){
136763
+ SWAP_DOUBLE(a[0],a[n-1])
136764
+ }
136765
+ if( n==2 ) return;
136766
+ iGt = n-1;
136767
+ i = n/2;
136768
+ if( a[0]>a[i] ){
136769
+ SWAP_DOUBLE(a[0],a[i])
136770
+ }else if( a[i]>a[iGt] ){
136694
136771
  SWAP_DOUBLE(a[i],a[iGt])
136772
+ }
136773
+ if( n==3 ) return;
136774
+ rPivot = a[i];
136775
+ iLt = i = 1;
136776
+ do{
136777
+ if( a[i]<rPivot ){
136778
+ if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
136779
+ iLt++;
136780
+ i++;
136781
+ }else if( a[i]>rPivot ){
136782
+ do{
136783
+ iGt--;
136784
+ }while( iGt>i && a[iGt]>rPivot );
136785
+ SWAP_DOUBLE(a[i],a[iGt])
136786
+ }else{
136787
+ i++;
136788
+ }
136789
+ }while( i<iGt );
136790
+ if( iLt>n/2 ){
136791
+ if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
136792
+ n = iLt;
136695
136793
  }else{
136696
- i++;
136794
+ if( iLt>=2 ) percentSort(a, iLt);
136795
+ a += iGt;
136796
+ n -= iGt;
136697
136797
  }
136698
- }while( i<iGt );
136699
- if( iLt>=2 ) percentSort(a, iLt);
136700
- if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
136701
-
136702
- /* Uncomment for testing */
136703
- #if 0
136704
- for(i=0; i<n-1; i++){
136705
- assert( a[i]<=a[i+1] );
136706
136798
  }
136707
- #endif
136708
136799
  }
136709
136800
 
136710
-
136711
136801
  /*
136712
136802
  ** The "inverse" function for percentile(Y,P) is called to remove a
136713
136803
  ** row that was previously inserted by "step".
@@ -156205,8 +156295,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
156205
156295
  ** does not refer to a table to the right of CheckOnCtx.iJoin. */
156206
156296
  do {
156207
156297
  SrcList *pSrc = pCtx->pSrc;
156298
+ int nSrc = pSrc->nSrc;
156208
156299
  int iTab = pExpr->iTable;
156209
- if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
156300
+ int ii;
156301
+ for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
156302
+ if( ii<nSrc ){
156210
156303
  if( pCtx->iJoin && iTab>pCtx->iJoin ){
156211
156304
  sqlite3ErrorMsg(pWalker->pParse,
156212
156305
  "%s references tables to its right",
@@ -166406,6 +166499,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
166406
166499
  WO_EQ|WO_IN|WO_IS, 0);
166407
166500
  if( pAlt==0 ) continue;
166408
166501
  if( pAlt->wtFlags & (TERM_CODED) ) continue;
166502
+ if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
166409
166503
  if( (pAlt->eOperator & WO_IN)
166410
166504
  && ExprUseXSelect(pAlt->pExpr)
166411
166505
  && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
@@ -167598,8 +167692,8 @@ static void exprAnalyzeOrTerm(
167598
167692
  ** 3. Not originating in the ON clause of an OUTER JOIN
167599
167693
  ** 4. The operator is not IS or else the query does not contain RIGHT JOIN
167600
167694
  ** 5. The affinities of A and B must be compatible
167601
- ** 6a. Both operands use the same collating sequence OR
167602
- ** 6b. The overall collating sequence is BINARY
167695
+ ** 6. Both operands use the same collating sequence, and they must not
167696
+ ** use explicit COLLATE clauses.
167603
167697
  ** If this routine returns TRUE, that means that the RHS can be substituted
167604
167698
  ** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
167605
167699
  ** This is an optimization. No harm comes from returning 0. But if 1 is
@@ -167607,10 +167701,9 @@ static void exprAnalyzeOrTerm(
167607
167701
  */
167608
167702
  static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
167609
167703
  char aff1, aff2;
167610
- CollSeq *pColl;
167611
167704
  if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
167612
167705
  if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
167613
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
167706
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
167614
167707
  assert( pSrc!=0 );
167615
167708
  if( pExpr->op==TK_IS
167616
167709
  && pSrc->nSrc>=2
@@ -167625,10 +167718,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
167625
167718
  ){
167626
167719
  return 0; /* (5) */
167627
167720
  }
167628
- pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
167629
- if( !sqlite3IsBinary(pColl)
167630
- && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
167631
- ){
167721
+ if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
167632
167722
  return 0; /* (6) */
167633
167723
  }
167634
167724
  return 1;
@@ -167960,7 +168050,7 @@ static void exprAnalyze(
167960
168050
  /* Analyze a term that is composed of two or more subterms connected by
167961
168051
  ** an OR operator.
167962
168052
  */
167963
- else if( pExpr->op==TK_OR ){
168053
+ else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
167964
168054
  assert( pWC->op==TK_AND );
167965
168055
  exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
167966
168056
  pTerm = &pWC->a[idxTerm];
@@ -171778,7 +171868,8 @@ static int whereRangeVectorLen(
171778
171868
  idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
171779
171869
  if( aff!=idxaff ) break;
171780
171870
 
171781
- pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
171871
+ if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
171872
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
171782
171873
  if( pColl==0 ) break;
171783
171874
  if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
171784
171875
  }
@@ -184270,9 +184361,11 @@ static YYACTIONTYPE yy_reduce(
184270
184361
  ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
184271
184362
  yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
184272
184363
  if( yymsp[-4].minor.yy454 ){
184364
+ int i;
184273
184365
  yymsp[-4].minor.yy454->x.pList = pList;
184274
- if( ALWAYS(pList->nExpr) ){
184275
- yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate;
184366
+ for(i=0; i<pList->nExpr; i++){
184367
+ assert( pList->a[i].pExpr!=0 );
184368
+ yymsp[-4].minor.yy454->flags |= pList->a[i].pExpr->flags & EP_Propagate;
184276
184369
  }
184277
184370
  }else{
184278
184371
  sqlite3ExprListDelete(pParse->db, pList);
@@ -184740,15 +184833,13 @@ static YYACTIONTYPE yy_reduce(
184740
184833
  break;
184741
184834
  case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
184742
184835
  {
184743
- sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
184836
+ sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
184744
184837
  }
184745
- yy_destructor(yypParser,219,&yymsp[-2].minor);
184746
184838
  break;
184747
184839
  case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
184748
184840
  {
184749
- sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
184841
+ sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
184750
184842
  }
184751
- yy_destructor(yypParser,219,&yymsp[-2].minor);
184752
184843
  break;
184753
184844
  case 302: /* cmd ::= create_vtab */
184754
184845
  {sqlite3VtabFinishParse(pParse,0);}
@@ -193952,6 +194043,12 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
193952
194043
  SQLITE_EXTENSION_INIT1
193953
194044
  #endif
193954
194045
 
194046
+
194047
+ /*
194048
+ ** Assume any b-tree layer with more levels than this is corrupt.
194049
+ */
194050
+ #define FTS3_MAX_BTREE_HEIGHT 48
194051
+
193955
194052
  typedef struct Fts3HashWrapper Fts3HashWrapper;
193956
194053
  struct Fts3HashWrapper {
193957
194054
  Fts3Hash hash; /* Hash table */
@@ -195668,7 +195765,11 @@ static int fts3SelectLeaf(
195668
195765
  assert( piLeaf || piLeaf2 );
195669
195766
 
195670
195767
  fts3GetVarint32(zNode, &iHeight);
195671
- rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195768
+ if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
195769
+ rc = FTS_CORRUPT_VTAB;
195770
+ }else{
195771
+ rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195772
+ }
195672
195773
  assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
195673
195774
 
195674
195775
  if( rc==SQLITE_OK && iHeight>1 ){
@@ -200197,7 +200298,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
200197
200298
  /* State 3. The integer just read is a column number. */
200198
200299
  default: assert( eState==3 );
200199
200300
  iCol = (int)v;
200200
- if( iCol<1 ){
200301
+ if( iCol<1 || iCol>(pFts3->nColumn+1) ){
200201
200302
  rc = SQLITE_CORRUPT_VTAB;
200202
200303
  break;
200203
200304
  }
@@ -200887,6 +200988,7 @@ static int getNextNode(
200887
200988
  assert( nKey==4 );
200888
200989
  if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
200889
200990
  nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
200991
+ if( nNear>=1000000000 ) nNear = 1000000000;
200890
200992
  }
200891
200993
  }
200892
200994
 
@@ -210750,7 +210852,7 @@ static int fts3ExprLHits(
210750
210852
  if( p->flag==FTS3_MATCHINFO_LHITS ){
210751
210853
  p->aMatchinfo[iStart + iCol] = (u32)nHit;
210752
210854
  }else if( nHit ){
210753
- p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
210855
+ p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
210754
210856
  }
210755
210857
  }
210756
210858
  assert( *pIter==0x00 || *pIter==0x01 );
@@ -213240,7 +213342,7 @@ static void jsonAppendSqlValue(
213240
213342
  break;
213241
213343
  }
213242
213344
  case SQLITE_FLOAT: {
213243
- jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
213345
+ jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
213244
213346
  break;
213245
213347
  }
213246
213348
  case SQLITE_INTEGER: {
@@ -214554,9 +214656,10 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
214554
214656
  u8 x;
214555
214657
  u32 sz;
214556
214658
  u32 n;
214557
- assert( i<=pParse->nBlob );
214558
- x = pParse->aBlob[i]>>4;
214559
- if( x<=11 ){
214659
+ if( i>=pParse->nBlob ){
214660
+ *pSz = 0;
214661
+ return 0;
214662
+ }else if( (x = pParse->aBlob[i]>>4)<=11 ){
214560
214663
  sz = x;
214561
214664
  n = 1;
214562
214665
  }else if( x==12 ){
@@ -217339,11 +217442,9 @@ static void jsonGroupInverse(
217339
217442
  UNUSED_PARAMETER(argc);
217340
217443
  UNUSED_PARAMETER(argv);
217341
217444
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
217342
- #ifdef NEVER
217343
217445
  /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
217344
217446
  ** always have been called to initialize it */
217345
217447
  if( NEVER(!pStr) ) return;
217346
- #endif
217347
217448
  z = pStr->zBuf;
217348
217449
  for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
217349
217450
  if( c=='"' ){
@@ -217372,6 +217473,13 @@ static void jsonGroupInverse(
217372
217473
  ** json_group_obj(NAME,VALUE)
217373
217474
  **
217374
217475
  ** Return a JSON object composed of all names and values in the aggregate.
217476
+ **
217477
+ ** Rows for which NAME is NULL do not result in a new entry. However, we
217478
+ ** do initially insert a "@" entry into the growing string for each null entry
217479
+ ** and change the first character of the string to "@" to signal that the
217480
+ ** string contains null entries. The "@" markers are needed in order to
217481
+ ** correctly process xInverse() requests. The initial "@" is converted
217482
+ ** back into "{" and the "@" null values are removed by jsonObjectCompute().
217375
217483
  */
217376
217484
  static void jsonObjectStep(
217377
217485
  sqlite3_context *ctx,
@@ -217389,7 +217497,7 @@ static void jsonObjectStep(
217389
217497
  if( pStr->zBuf==0 ){
217390
217498
  jsonStringInit(pStr, ctx);
217391
217499
  jsonAppendChar(pStr, '{');
217392
- }else if( pStr->nUsed>1 && z!=0 ){
217500
+ }else if( pStr->nUsed>1 ){
217393
217501
  jsonAppendChar(pStr, ',');
217394
217502
  }
217395
217503
  pStr->pCtx = ctx;
@@ -217397,6 +217505,9 @@ static void jsonObjectStep(
217397
217505
  jsonAppendString(pStr, z, n);
217398
217506
  jsonAppendChar(pStr, ':');
217399
217507
  jsonAppendSqlValue(pStr, argv[1]);
217508
+ }else{
217509
+ pStr->zBuf[0] = '@';
217510
+ jsonAppendRawNZ(pStr, "@", 1);
217400
217511
  }
217401
217512
  }
217402
217513
  }
@@ -217405,20 +217516,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
217405
217516
  int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
217406
217517
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
217407
217518
  if( pStr ){
217408
- jsonAppendRawNZ(pStr, "}", 2);
217409
- jsonStringTrimOneChar(pStr);
217519
+ JsonString *pOgStr = pStr;
217520
+ JsonString tmpStr;
217521
+ jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
217522
+ jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
217410
217523
  pStr->pCtx = ctx;
217411
217524
  if( pStr->eErr ){
217412
217525
  jsonReturnString(pStr, 0, 0);
217413
217526
  return;
217414
- }else if( flags & JSON_BLOB ){
217527
+ }
217528
+ if( pStr->zBuf[0]!='{' ){
217529
+ /* The string contains null entries that need to be removed */
217530
+ u64 i, j;
217531
+ int inStr = 0;
217532
+ if( !isFinal ){
217533
+ /* Work with a temporary copy of the string if this is not the
217534
+ ** final result */
217535
+ jsonStringInit(&tmpStr, ctx);
217536
+ jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
217537
+ pStr = &tmpStr;
217538
+ if( pStr->eErr ){
217539
+ jsonReturnString(pStr, 0, 0);
217540
+ return;
217541
+ }
217542
+ jsonStringTrimOneChar(pStr); /* Remove zero terminator */
217543
+ }
217544
+ /* Fix up the string by changing the initial "@" flag back to
217545
+ ** to "{" and removing all subsequence "@" entries, with their
217546
+ ** associated comma delimeters. */
217547
+ pStr->zBuf[0] = '{';
217548
+ for(i=j=1; i<pStr->nUsed; i++){
217549
+ char c = pStr->zBuf[i];
217550
+ if( c=='"' ){
217551
+ inStr = !inStr;
217552
+ pStr->zBuf[j++] = '"';
217553
+ }else if( c=='\\' ){
217554
+ pStr->zBuf[j++] = '\\';
217555
+ pStr->zBuf[j++] = pStr->zBuf[++i];
217556
+ }else if( c=='@' && !inStr ){
217557
+ assert( i+1<pStr->nUsed );
217558
+ if( pStr->zBuf[i+1]==',' ){
217559
+ i++;
217560
+ }else if( pStr->zBuf[j-1]==',' ){
217561
+ j--;
217562
+ }
217563
+ }else{
217564
+ pStr->zBuf[j++] = c;
217565
+ }
217566
+ }
217567
+ pStr->zBuf[j] = 0; /* Restore zero terminator */
217568
+ pStr->nUsed = j; /* Truncate the string */
217569
+ }
217570
+ if( flags & JSON_BLOB ){
217415
217571
  jsonReturnStringAsBlob(pStr);
217416
217572
  if( isFinal ){
217417
217573
  if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
217418
217574
  }else{
217419
- jsonStringTrimOneChar(pStr);
217575
+ jsonStringTrimOneChar(pOgStr);
217420
217576
  }
217421
- return;
217422
217577
  }else if( isFinal ){
217423
217578
  sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
217424
217579
  pStr->bStatic ? SQLITE_TRANSIENT :
@@ -217426,8 +217581,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
217426
217581
  pStr->bStatic = 1;
217427
217582
  }else{
217428
217583
  sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
217429
- jsonStringTrimOneChar(pStr);
217584
+ jsonStringTrimOneChar(pOgStr);
217430
217585
  }
217586
+ if( pStr!=pOgStr ) jsonStringReset(pStr);
217431
217587
  }else if( flags & JSON_BLOB ){
217432
217588
  static const unsigned char emptyObject = 0x0c;
217433
217589
  sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
@@ -218279,7 +218435,7 @@ struct Rtree {
218279
218435
  u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
218280
218436
  u8 nBytesPerCell; /* Bytes consumed per cell */
218281
218437
  u8 inWrTrans; /* True if inside write transaction */
218282
- u8 nAux; /* # of auxiliary columns in %_rowid */
218438
+ u16 nAux; /* # of auxiliary columns in %_rowid */
218283
218439
  #ifdef SQLITE_ENABLE_GEOPOLY
218284
218440
  u8 nAuxNotNull; /* Number of initial not-null aux columns */
218285
218441
  #endif
@@ -219515,7 +219671,7 @@ static int nodeRowidIndex(
219515
219671
  ){
219516
219672
  int ii;
219517
219673
  int nCell = NCELL(pNode);
219518
- assert( nCell<200 );
219674
+ assert( nCell<65536 && nCell>=0 );
219519
219675
  for(ii=0; ii<nCell; ii++){
219520
219676
  if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
219521
219677
  *piIndex = ii;
@@ -219777,7 +219933,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
219777
219933
  pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
219778
219934
  if( rc ) return rc;
219779
219935
  nCell = NCELL(pNode);
219780
- assert( nCell<200 );
219936
+ if( nCell>RTREE_MAXCELLS ){
219937
+ RTREE_IS_CORRUPT(pRtree);
219938
+ return SQLITE_CORRUPT_VTAB;
219939
+ }
219781
219940
  pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
219782
219941
  while( p->iCell<nCell ){
219783
219942
  sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
@@ -221754,7 +221913,7 @@ static int rtreeInit(
221754
221913
  "Auxiliary rtree columns must be last" /* 4 */
221755
221914
  };
221756
221915
 
221757
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
221916
+ assert( RTREE_MAX_AUX_COLUMN<256 );
221758
221917
  if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
221759
221918
  *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
221760
221919
  return SQLITE_ERROR;
@@ -223673,6 +223832,11 @@ static int geopolyInit(
223673
223832
  int ii;
223674
223833
  (void)pAux;
223675
223834
 
223835
+ if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
223836
+ *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
223837
+ return SQLITE_ERROR;
223838
+ }
223839
+
223676
223840
  sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
223677
223841
  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
223678
223842
 
@@ -224807,7 +224971,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
224807
224971
  const UChar *zInput; /* Pointer to input string */
224808
224972
  UChar *zOutput = 0; /* Pointer to output buffer */
224809
224973
  int nInput; /* Size of utf-16 input string in bytes */
224810
- int nOut; /* Size of output buffer in bytes */
224974
+ sqlite3_int64 nOut; /* Size of output buffer in bytes */
224811
224975
  int cnt;
224812
224976
  int bToUpper; /* True for toupper(), false for tolower() */
224813
224977
  UErrorCode status;
@@ -224830,7 +224994,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
224830
224994
  }
224831
224995
 
224832
224996
  for(cnt=0; cnt<2; cnt++){
224833
- UChar *zNew = sqlite3_realloc(zOutput, nOut);
224997
+ UChar *zNew = sqlite3_realloc64(zOutput, nOut);
224834
224998
  if( zNew==0 ){
224835
224999
  sqlite3_free(zOutput);
224836
225000
  sqlite3_result_error_nomem(p);
@@ -224839,9 +225003,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
224839
225003
  zOutput = zNew;
224840
225004
  status = U_ZERO_ERROR;
224841
225005
  if( bToUpper ){
224842
- nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225006
+ nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
224843
225007
  }else{
224844
- nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225008
+ nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
224845
225009
  }
224846
225010
 
224847
225011
  if( U_SUCCESS(status) ){
@@ -232556,12 +232720,13 @@ static int dbpageFilter(
232556
232720
  pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
232557
232721
  pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
232558
232722
  if( idxNum & 1 ){
232723
+ i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
232559
232724
  assert( argc>(idxNum>>1) );
232560
- pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
232561
- if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
232725
+ if( iPg<1 || iPg>pCsr->mxPgno ){
232562
232726
  pCsr->pgno = 1;
232563
232727
  pCsr->mxPgno = 0;
232564
232728
  }else{
232729
+ pCsr->pgno = (Pgno)iPg;
232565
232730
  pCsr->mxPgno = pCsr->pgno;
232566
232731
  }
232567
232732
  }else{
@@ -234908,6 +235073,16 @@ static int sessionPrepareDfltStmt(
234908
235073
  return rc;
234909
235074
  }
234910
235075
 
235076
+ /*
235077
+ ** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
235078
+ ** called, set it to the results of the sqlite3_finalize() call. Or, if
235079
+ ** it is already set to an error code, leave it as is.
235080
+ */
235081
+ static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
235082
+ int rc = sqlite3_finalize(pStmt);
235083
+ if( *pRc==SQLITE_OK ) *pRc = rc;
235084
+ }
235085
+
234911
235086
  /*
234912
235087
  ** Table pTab has one or more existing change-records with old.* records
234913
235088
  ** with fewer than pTab->nCol columns. This function updates all such
@@ -234930,9 +235105,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
234930
235105
  }
234931
235106
  }
234932
235107
 
235108
+ sessionFinalizeStmt(pStmt, &rc);
234933
235109
  pSession->rc = rc;
234934
- rc = sqlite3_finalize(pStmt);
234935
- if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
234936
235110
  return pSession->rc;
234937
235111
  }
234938
235112
 
@@ -235500,7 +235674,7 @@ static int sessionDiffFindNew(
235500
235674
  rc = SQLITE_NOMEM;
235501
235675
  }else{
235502
235676
  sqlite3_stmt *pStmt;
235503
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235677
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
235504
235678
  if( rc==SQLITE_OK ){
235505
235679
  SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
235506
235680
  pDiffCtx->pStmt = pStmt;
@@ -235563,7 +235737,7 @@ static int sessionDiffFindModified(
235563
235737
  rc = SQLITE_NOMEM;
235564
235738
  }else{
235565
235739
  sqlite3_stmt *pStmt;
235566
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235740
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
235567
235741
 
235568
235742
  if( rc==SQLITE_OK ){
235569
235743
  SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
@@ -236258,11 +236432,11 @@ static int sessionSelectStmt(
236258
236432
  );
236259
236433
  sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
236260
236434
  }else{
236261
- #if 0
236435
+ #if 0
236262
236436
  if( bRowid ){
236263
236437
  sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
236264
236438
  }
236265
- #endif
236439
+ #endif
236266
236440
  for(i=0; i<nCol; i++){
236267
236441
  if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
236268
236442
  sessionAppendIdent(&cols, azCol[i], &rc);
@@ -237516,7 +237690,13 @@ static int sessionChangesetInvert(
237516
237690
 
237517
237691
  /* Test for EOF. */
237518
237692
  if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
237519
- if( pInput->iNext>=pInput->nData ) break;
237693
+ if( pInput->iNext+1>=pInput->nData ){
237694
+ if( pInput->iNext!=pInput->nData ){
237695
+ rc = SQLITE_CORRUPT_BKPT;
237696
+ goto finished_invert;
237697
+ }
237698
+ break;
237699
+ }
237520
237700
  eType = pInput->aData[pInput->iNext];
237521
237701
 
237522
237702
  switch( eType ){
@@ -237712,6 +237892,7 @@ struct SessionApplyCtx {
237712
237892
  u8 bRebaseStarted; /* If table header is already in rebase */
237713
237893
  u8 bRebase; /* True to collect rebase information */
237714
237894
  u8 bIgnoreNoop; /* True to ignore no-op conflicts */
237895
+ u8 bNoUpdateLoop; /* No update-loop processing */
237715
237896
  int bRowid;
237716
237897
  char *zErr; /* Error message, if any */
237717
237898
  };
@@ -238285,7 +238466,7 @@ static int sessionConflictHandler(
238285
238466
  u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
238286
238467
  int nBlob = pIter->in.iNext - pIter->in.iCurrent;
238287
238468
  sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
238288
- return SQLITE_OK;
238469
+ return rc;
238289
238470
  }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
238290
238471
  || eType==SQLITE_CHANGESET_CONFLICT
238291
238472
  ){
@@ -238407,7 +238588,7 @@ static int sessionApplyOneOp(
238407
238588
  for(i=0; rc==SQLITE_OK && i<nCol; i++){
238408
238589
  sqlite3_value *pOld = sessionChangesetOld(pIter, i);
238409
238590
  sqlite3_value *pNew = sessionChangesetNew(pIter, i);
238410
- if( p->abPK[i] || (bPatchset==0 && pOld) ){
238591
+ if( pOld && (p->abPK[i] || bPatchset==0) ){
238411
238592
  rc = sessionBindValue(pUp, i*2+2, pOld);
238412
238593
  }
238413
238594
  if( rc==SQLITE_OK && pNew ){
@@ -238533,7 +238714,264 @@ static int sessionApplyOneWithRetry(
238533
238714
  }
238534
238715
 
238535
238716
  /*
238536
- ** Retry the changes accumulated in the pApply->constraints buffer.
238717
+ ** Create an iterator to iterate through the retry buffer pRetry.
238718
+ */
238719
+ static int sessionRetryIterInit(
238720
+ SessionBuffer *pRetry, /* Buffer to iterate through */
238721
+ int bPatchset, /* True for patchset, false for changeset */
238722
+ const char *zTab, /* Table name */
238723
+ SessionApplyCtx *pApply, /* Session apply context */
238724
+ sqlite3_changeset_iter **ppIter /* OUT: New iterator */
238725
+ ){
238726
+ sqlite3_changeset_iter *pRet = 0;
238727
+ int rc = SQLITE_OK;
238728
+
238729
+ rc = sessionChangesetStart(
238730
+ &pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
238731
+ );
238732
+ if( rc==SQLITE_OK ){
238733
+ size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
238734
+ pRet->bPatchset = bPatchset;
238735
+ pRet->zTab = (char*)zTab;
238736
+ pRet->nCol = pApply->nCol;
238737
+ pRet->abPK = pApply->abPK;
238738
+ sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
238739
+ pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
238740
+ if( rc==SQLITE_OK ){
238741
+ memset(pRet->apValue, 0, nByte);
238742
+ }else{
238743
+ sqlite3changeset_finalize(pRet);
238744
+ pRet = 0;
238745
+ }
238746
+ }
238747
+
238748
+ *ppIter = pRet;
238749
+ return rc;
238750
+ }
238751
+
238752
+ /*
238753
+ ** Attempt to apply all the changes in retry buffer pRetry to the database.
238754
+ ** Except, if parameter iSkip is greater than or equal to 0, skip change
238755
+ ** iSkip.
238756
+ */
238757
+ static int sessionApplyRetryBuffer(
238758
+ SessionBuffer *pRetry, /* Buffer to apply changes from */
238759
+ int iSkip, /* If >=0, index of change to omit */
238760
+ sqlite3 *db, /* Database handle */
238761
+ int bPatchset, /* True for patchset, false for changeset */
238762
+ const char *zTab, /* Name of table to write to */
238763
+ SessionApplyCtx *pApply, /* Apply context */
238764
+ int(*xConflict)(void*, int, sqlite3_changeset_iter*),
238765
+ void *pCtx /* First argument passed to xConflict */
238766
+ ){
238767
+ int rc = SQLITE_OK;
238768
+ int rc2 = SQLITE_OK;
238769
+ int ii = 0;
238770
+ sqlite3_changeset_iter *pIter = 0;
238771
+
238772
+ assert( pApply->constraints.nBuf==0 );
238773
+
238774
+ rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
238775
+
238776
+ for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
238777
+ if( ii!=iSkip ){
238778
+ rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
238779
+ }
238780
+ }
238781
+
238782
+ rc2 = sqlite3changeset_finalize(pIter);
238783
+ if( rc==SQLITE_OK ) rc = rc2;
238784
+ assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
238785
+
238786
+ return rc;
238787
+ }
238788
+
238789
+ /*
238790
+ ** Check if table zTab in the "main" database of db is a WITHOUT ROWID
238791
+ ** table.
238792
+ **
238793
+ ** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
238794
+ ** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
238795
+ ** error does occur, return an SQLite error code. The final value of (*pbWR)
238796
+ ** is undefined in this case.
238797
+ */
238798
+ static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
238799
+ sqlite3_stmt *pList = 0;
238800
+ char *zSql = 0;
238801
+ int rc = SQLITE_OK;
238802
+
238803
+ zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
238804
+ if( zSql==0 ){
238805
+ rc = SQLITE_NOMEM;
238806
+ }else{
238807
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
238808
+ sqlite3_free(zSql);
238809
+ }
238810
+
238811
+ if( rc==SQLITE_OK ){
238812
+ sqlite3_step(pList);
238813
+ *pbWR = sqlite3_column_int(pList, 4);
238814
+ rc = sqlite3_finalize(pList);
238815
+ }
238816
+
238817
+ return rc;
238818
+ }
238819
+
238820
+ /*
238821
+ ** Iterator pUp points to an UPDATE change. This function deletes the
238822
+ ** affected row from the database and creates an INSERT statement that
238823
+ ** may be used to reinsert the row as it is after the UPDATE change
238824
+ ** has been applied.
238825
+ **
238826
+ ** If successful, SQLITE_OK is returned and output variable (*ppInsert)
238827
+ ** is left pointing to a prepared INSERT statement. It is the responsibility
238828
+ ** of the caller to eventually free this statement using sqlite3_finalize().
238829
+ ** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
238830
+ ** set to NULL. pApply->zErr may be set to an error message in this case.
238831
+ */
238832
+ static int sessionUpdateToDeleteInsert(
238833
+ sqlite3 *db, /* Database to write to */
238834
+ const char *zTab, /* Table name */
238835
+ SessionApplyCtx *pApply, /* Apply context */
238836
+ sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
238837
+ sqlite3_stmt **ppInsert /* OUT: INSERT statement */
238838
+ ){
238839
+ sqlite3_stmt *pRet = 0; /* The INSERT statement */
238840
+ sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
238841
+ int rc = SQLITE_OK;
238842
+ int bWR = 0;
238843
+
238844
+ rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
238845
+ if( rc==SQLITE_OK ){
238846
+ char *zSelect = 0;
238847
+ char *zInsert = 0;
238848
+ SessionBuffer cols = {0, 0, 0};
238849
+ SessionBuffer insbind = {0, 0, 0};
238850
+ SessionBuffer pkcols = {0, 0, 0};
238851
+ SessionBuffer selbind = {0, 0, 0};
238852
+
238853
+ const char *zComma = "";
238854
+ const char *zComma2 = "";
238855
+ int ii;
238856
+ for(ii=0; ii<pApply->nCol; ii++){
238857
+ sessionAppendStr(&cols, zComma, &rc);
238858
+ sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
238859
+ sessionAppendStr(&insbind, zComma, &rc);
238860
+ sessionAppendStr(&insbind, "?", &rc);
238861
+ zComma = ", ";
238862
+
238863
+ if( pApply->abPK[ii] ){
238864
+ sessionAppendStr(&pkcols, zComma2, &rc);
238865
+ sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
238866
+ sessionAppendStr(&selbind, zComma2, &rc);
238867
+ sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
238868
+ zComma2 = ", ";
238869
+ }
238870
+ }
238871
+ if( bWR==0 ){
238872
+ sessionAppendStr(&cols, zComma, &rc);
238873
+ sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
238874
+ sessionAppendStr(&insbind, zComma, &rc);
238875
+ sessionAppendStr(&insbind, "?", &rc);
238876
+ }
238877
+
238878
+ if( rc==SQLITE_OK ){
238879
+ zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
238880
+ cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
238881
+ );
238882
+ if( zSelect==0 ) rc = SQLITE_NOMEM;
238883
+ }
238884
+ if( rc==SQLITE_OK ){
238885
+ zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
238886
+ zTab, cols.aBuf, insbind.aBuf
238887
+ );
238888
+ if( zInsert==0 ) rc = SQLITE_NOMEM;
238889
+ }
238890
+
238891
+ if( rc==SQLITE_OK ){
238892
+ rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
238893
+ }
238894
+ if( rc==SQLITE_OK ){
238895
+ rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
238896
+ }
238897
+
238898
+ sqlite3_free(zSelect);
238899
+ sqlite3_free(zInsert);
238900
+ sqlite3_free(cols.aBuf);
238901
+ sqlite3_free(insbind.aBuf);
238902
+ sqlite3_free(pkcols.aBuf);
238903
+ sqlite3_free(selbind.aBuf);
238904
+ }
238905
+
238906
+ if( rc==SQLITE_OK ){
238907
+ rc = sessionBindRow(
238908
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
238909
+ );
238910
+ }
238911
+
238912
+ if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
238913
+ int iCol;
238914
+ for(iCol=0; iCol<pApply->nCol; iCol++){
238915
+ sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
238916
+ if( pVal==0 ){
238917
+ pVal = sqlite3_column_value(pSelect, iCol);
238918
+ }
238919
+ rc = sqlite3_bind_value(pRet, iCol+1, pVal);
238920
+ }
238921
+ if( bWR==0 ){
238922
+ sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
238923
+ }
238924
+ }
238925
+ sessionFinalizeStmt(pSelect, &rc);
238926
+
238927
+ /* Delete the row from the database. */
238928
+ if( rc==SQLITE_OK ){
238929
+ rc = sessionBindRow(
238930
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
238931
+ );
238932
+ sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
238933
+ }
238934
+ if( rc==SQLITE_OK ){
238935
+ sqlite3_step(pApply->pDelete);
238936
+ rc = sqlite3_reset(pApply->pDelete);
238937
+ }
238938
+
238939
+ if( rc!=SQLITE_OK ){
238940
+ sqlite3_finalize(pRet);
238941
+ pRet = 0;
238942
+ }
238943
+
238944
+ *ppInsert = pRet;
238945
+ return rc;
238946
+ }
238947
+
238948
+ /*
238949
+ ** Retry the changes accumulated in the pApply->constraints buffer. The
238950
+ ** pApply->constraints buffer contains all changes to table zTab that
238951
+ ** could not be applied due to SQLITE_CONSTRAINT errors. This function
238952
+ ** attempts to apply them as follows:
238953
+ **
238954
+ ** 1) It runs through the buffer and attempts to retry each change,
238955
+ ** removing any that are successfully applied from the buffer. This
238956
+ ** is repeated until no further progress can be made.
238957
+ **
238958
+ ** 2) For each UPDATE change in the buffer, try the following in a
238959
+ ** savepoint transaction:
238960
+ **
238961
+ ** a) DELETE the affected row,
238962
+ ** b) Attempt step (1) with remaining changes,
238963
+ ** c) Attempt to INSERT a row equivalent to the one that would be
238964
+ ** created by applying this UPDATE change.
238965
+ **
238966
+ ** If the INSERT in (c) succeeds, the savepoint is committed and all
238967
+ ** successfully applied changes are removed from the buffer. Step (2)
238968
+ ** is then repeated.
238969
+ **
238970
+ ** 3) Once step (2) has been attempted for each UPDATE in the change,
238971
+ ** a final attempt is made to apply each remaining change. This time,
238972
+ ** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
238973
+ ** is invoked and the user has to decide whether to omit the change
238974
+ ** or rollback the entire _apply() operation.
238537
238975
  */
238538
238976
  static int sessionRetryConstraints(
238539
238977
  sqlite3 *db,
@@ -238544,41 +238982,101 @@ static int sessionRetryConstraints(
238544
238982
  void *pCtx /* First argument passed to xConflict */
238545
238983
  ){
238546
238984
  int rc = SQLITE_OK;
238985
+ int iUpdate = 0;
238547
238986
 
238987
+ /* Step (1) */
238548
238988
  while( pApply->constraints.nBuf ){
238549
- sqlite3_changeset_iter *pIter2 = 0;
238550
238989
  SessionBuffer cons = pApply->constraints;
238551
238990
  memset(&pApply->constraints, 0, sizeof(SessionBuffer));
238552
238991
 
238553
- rc = sessionChangesetStart(
238554
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
238992
+ rc = sessionApplyRetryBuffer(
238993
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
238994
+ );
238995
+
238996
+ sqlite3_free(cons.aBuf);
238997
+ if( rc!=SQLITE_OK ) break;
238998
+
238999
+ /* If no progress has been made this round, break out of the loop. */
239000
+ if( pApply->constraints.nBuf>=cons.nBuf ) break;
239001
+ }
239002
+
239003
+ /* Step (2) */
239004
+ while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
239005
+ SessionBuffer cons = {0, 0, 0};
239006
+ sqlite3_changeset_iter *pUp = 0;
239007
+ sqlite3_stmt *pInsert = 0;
239008
+ int iSkip = 0;
239009
+
239010
+ rc = sessionRetryIterInit(
239011
+ &pApply->constraints, bPatchset, zTab, pApply, &pUp
238555
239012
  );
238556
239013
  if( rc==SQLITE_OK ){
238557
- size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
238558
- int rc2;
238559
- pIter2->bPatchset = bPatchset;
238560
- pIter2->zTab = (char*)zTab;
238561
- pIter2->nCol = pApply->nCol;
238562
- pIter2->abPK = pApply->abPK;
238563
- sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
238564
- pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
238565
- if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
239014
+ int iThis = -1;
239015
+ while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
239016
+ if( pUp->op==SQLITE_UPDATE ) iThis++;
239017
+ if( iThis==iUpdate ) break;
239018
+ iSkip++;
239019
+ }
239020
+ if( iThis==iUpdate ){
239021
+ rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
239022
+ if( rc==SQLITE_OK ){
239023
+ rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
239024
+ }
239025
+ }
239026
+ sqlite3changeset_finalize(pUp);
239027
+ if( iThis!=iUpdate ) break;
239028
+ }
239029
+
239030
+ if( rc==SQLITE_OK ){
239031
+ cons = pApply->constraints;
238566
239032
 
238567
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
238568
- rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
239033
+ while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
239034
+ SessionBuffer app = pApply->constraints;
239035
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
239036
+ rc = sessionApplyRetryBuffer(
239037
+ &app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
239038
+ );
239039
+ if( app.aBuf!=cons.aBuf ){
239040
+ sqlite3_free(app.aBuf);
239041
+ }
239042
+ if( pApply->constraints.nBuf>=app.nBuf ){
239043
+ break;
239044
+ }
239045
+ iSkip = -1;
238569
239046
  }
239047
+ }
238570
239048
 
238571
- rc2 = sqlite3changeset_finalize(pIter2);
238572
- if( rc==SQLITE_OK ) rc = rc2;
239049
+ iUpdate++;
239050
+ if( rc==SQLITE_OK ){
239051
+ sqlite3_step(pInsert);
239052
+ rc = sqlite3_finalize(pInsert);
239053
+ if( rc==SQLITE_CONSTRAINT ){
239054
+ rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
239055
+ sqlite3_free(pApply->constraints.aBuf);
239056
+ pApply->constraints = cons;
239057
+ memset(&cons, 0, sizeof(cons));
239058
+ }else if( rc==SQLITE_OK ){
239059
+ iUpdate = 0;
239060
+ }
239061
+ if( rc==SQLITE_OK ){
239062
+ rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
239063
+ }
239064
+ }else{
239065
+ sqlite3_finalize(pInsert);
238573
239066
  }
238574
- assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
238575
239067
 
238576
239068
  sqlite3_free(cons.aBuf);
238577
- if( rc!=SQLITE_OK ) break;
238578
- if( pApply->constraints.nBuf>=cons.nBuf ){
238579
- /* No progress was made on the last round. */
238580
- pApply->bDeferConstraints = 0;
238581
- }
239069
+ }
239070
+
239071
+ /* Step (3) */
239072
+ if( rc==SQLITE_OK && pApply->constraints.nBuf ){
239073
+ SessionBuffer cons = pApply->constraints;
239074
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
239075
+ pApply->bDeferConstraints = 0;
239076
+ rc = sessionApplyRetryBuffer(
239077
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
239078
+ );
239079
+ sqlite3_free(cons.aBuf);
238582
239080
  }
238583
239081
 
238584
239082
  return rc;
@@ -238632,6 +239130,7 @@ static int sessionChangesetApply(
238632
239130
  sApply.bRebase = (ppRebase && pnRebase);
238633
239131
  sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
238634
239132
  sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
239133
+ sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
238635
239134
  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
238636
239135
  rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
238637
239136
  }
@@ -240443,7 +240942,7 @@ SQLITE_API int sqlite3changegroup_change_blob(
240443
240942
  const void *pVal,
240444
240943
  int nVal
240445
240944
  ){
240446
- sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + nVal;
240945
+ sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
240447
240946
  int rc = SQLITE_OK;
240448
240947
  SessionBuffer *pBuf = 0;
240449
240948
 
@@ -251027,7 +251526,7 @@ static void fts5DataRelease(Fts5Data *pData){
251027
251526
  static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
251028
251527
  Fts5Data *pRet = fts5DataRead(p, iRowid);
251029
251528
  if( pRet ){
251030
- if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
251529
+ if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
251031
251530
  FTS5_CORRUPT_ROWID(p, iRowid);
251032
251531
  fts5DataRelease(pRet);
251033
251532
  pRet = 0;
@@ -252681,6 +253180,10 @@ static void fts5LeafSeek(
252681
253180
  if( nKeep<nMatch ){
252682
253181
  goto search_failed;
252683
253182
  }
253183
+ if( (iOff+nNew)>n ){
253184
+ FTS5_CORRUPT_ITER(p, pIter);
253185
+ return;
253186
+ }
252684
253187
 
252685
253188
  assert( nKeep>=nMatch );
252686
253189
  if( nKeep==nMatch ){
@@ -253657,8 +254160,7 @@ static void fts5PoslistFilterCallback(
253657
254160
 
253658
254161
  do {
253659
254162
  while( i<nChunk && pChunk[i]!=0x01 ){
253660
- while( pChunk[i] & 0x80 ) i++;
253661
- i++;
254163
+ fts5IndexSkipVarint(pChunk, i);
253662
254164
  }
253663
254165
  if( pCtx->eState ){
253664
254166
  fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
@@ -253807,7 +254309,7 @@ static void fts5IndexExtractColset(
253807
254309
  /* Advance pointer p until it points to pEnd or an 0x01 byte that is
253808
254310
  ** not part of a varint */
253809
254311
  while( p<pEnd && *p!=0x01 ){
253810
- while( *p++ & 0x80 );
254312
+ while( p<pEnd && (*p++ & 0x80) );
253811
254313
  }
253812
254314
 
253813
254315
  if( pColset->aiCol[i]==iCurrent ){
@@ -253904,8 +254406,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
253904
254406
 
253905
254407
  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
253906
254408
  assert( pIter->pColset );
254409
+ assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
253907
254410
 
253908
- if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
254411
+ if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
254412
+ || pSeg->nPos>pIter->pIndex->pConfig->nCol
254413
+ ){
253909
254414
  fts5IterSetOutputs_Col(pIter, pSeg);
253910
254415
  }else{
253911
254416
  u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
@@ -255399,6 +255904,11 @@ static void fts5DoSecureDelete(
255399
255904
  }else{
255400
255905
  iStart = fts5GetU16(&aPg[0]);
255401
255906
  }
255907
+ if( iStart>nPg ){
255908
+ FTS5_CORRUPT_IDX(p);
255909
+ sqlite3_free(aIdx);
255910
+ return;
255911
+ }
255402
255912
 
255403
255913
  iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
255404
255914
  assert_nc( iSOP<=pSeg->iLeafOffset );
@@ -263275,7 +263785,7 @@ static void fts5SourceIdFunc(
263275
263785
  ){
263276
263786
  assert( nArg==0 );
263277
263787
  UNUSED_PARAM2(nArg, apUnused);
263278
- sqlite3_result_text(pCtx, "fts5: 2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9", -1, SQLITE_TRANSIENT);
263788
+ sqlite3_result_text(pCtx, "fts5: 2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24", -1, SQLITE_TRANSIENT);
263279
263789
  }
263280
263790
 
263281
263791
  /*
@@ -265669,8 +266179,14 @@ static int fts5PorterCreate(
265669
266179
  const char *zBase = "unicode61";
265670
266180
  fts5_tokenizer_v2 *pV2 = 0;
265671
266181
 
265672
- if( nArg>0 ){
265673
- zBase = azArg[0];
266182
+ while( nArg>0 ){
266183
+ if( sqlite3_stricmp(azArg[0],"porter")==0 ){
266184
+ nArg--;
266185
+ azArg++;
266186
+ }else{
266187
+ zBase = azArg[0];
266188
+ break;
266189
+ }
265674
266190
  }
265675
266191
 
265676
266192
  pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));