better-sqlite3-multiple-ciphers 12.10.0 → 12.11.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.
@@ -123,7 +123,7 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
123
123
  /*** Begin of #include "sqlite3patched.c" ***/
124
124
  /******************************************************************************
125
125
  ** This file is an amalgamation of many separate C source files from SQLite
126
- ** version 3.53.1. By combining all the individual C code files into this
126
+ ** version 3.53.2. By combining all the individual C code files into this
127
127
  ** single large file, the entire code can be compiled as a single translation
128
128
  ** unit. This allows many compilers to do optimizations that would not be
129
129
  ** possible if the files were compiled separately. Performance improvements
@@ -141,7 +141,7 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
141
141
  ** separate file. This file contains only code for the core SQLite library.
142
142
  **
143
143
  ** The content in this amalgamation comes from Fossil check-in
144
- ** c88b22011a54b4f6fbd149e9f8e4de77658c with changes in files:
144
+ ** d6e03d8c777cfa2d35e3b60d8ec3e0187f3e with changes in files:
145
145
  **
146
146
  **
147
147
  */
@@ -591,12 +591,12 @@ extern "C" {
591
591
  ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
592
592
  ** [sqlite_version()] and [sqlite_source_id()].
593
593
  */
594
- #define SQLITE_VERSION "3.53.1"
595
- #define SQLITE_VERSION_NUMBER 3053001
596
- #define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9"
594
+ #define SQLITE_VERSION "3.53.2"
595
+ #define SQLITE_VERSION_NUMBER 3053002
596
+ #define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
597
597
  #define SQLITE_SCM_BRANCH "branch-3.53"
598
- #define SQLITE_SCM_TAGS "release version-3.53.1"
599
- #define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z"
598
+ #define SQLITE_SCM_TAGS "release version-3.53.2"
599
+ #define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
600
600
 
601
601
  /*
602
602
  ** CAPI3REF: Run-Time Library Version Numbers
@@ -13298,11 +13298,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
13298
13298
  ** database behave as if they were declared with "ON UPDATE NO ACTION ON
13299
13299
  ** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
13300
13300
  ** or SET DEFAULT.
13301
+ **
13302
+ ** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
13303
+ ** Sometimes, a changeset contains two or more update statements such that
13304
+ ** although after applying all updates the database will contain no
13305
+ ** constraint violations, no single update can be applied before the others.
13306
+ ** The simplest example of this is a pair of UPDATEs that have "swapped"
13307
+ ** two column values with a UNIQUE constraint.
13308
+ ** <p>
13309
+ ** Usually, sqlite3changeset_apply() and similar functions work hard to try
13310
+ ** to find a way to apply such a changeset. However, if this flag is set,
13311
+ ** then all such updates are considered CONSTRAINT conflicts.
13301
13312
  */
13302
13313
  #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
13303
13314
  #define SQLITE_CHANGESETAPPLY_INVERT 0x0002
13304
13315
  #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
13305
13316
  #define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
13317
+ #define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
13306
13318
 
13307
13319
  /*
13308
13320
  ** CAPI3REF: Constants Passed To The Conflict Handler
@@ -22586,7 +22598,15 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void);
22586
22598
  SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
22587
22599
  SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
22588
22600
  SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
22589
- SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
22601
+ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
22602
+ Parse *pParse, /* Parse context */
22603
+ SrcList *pSrc, /* Table to add constraint to */
22604
+ Token *pFirst, /* First token of new constraint */
22605
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
22606
+ const char *zExpr, /* Text of CHECK expression */
22607
+ int nExpr, /* Size of pExpr in bytes */
22608
+ Expr *pExpr /* The parsed CHECK expression */
22609
+ );
22590
22610
  SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
22591
22611
  SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
22592
22612
  SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
@@ -33401,8 +33421,8 @@ SQLITE_API void sqlite3_str_vappendf(
33401
33421
  ** all control characters, and for backslash itself.
33402
33422
  ** For %#Q, do the same but only if there is at least
33403
33423
  ** one control character. */
33404
- u32 nBack = 0;
33405
- u32 nCtrl = 0;
33424
+ i64 nBack = 0;
33425
+ i64 nCtrl = 0;
33406
33426
  for(k=0; k<i; k++){
33407
33427
  if( escarg[k]=='\\' ){
33408
33428
  nBack++;
@@ -45455,9 +45475,9 @@ static int unixShmMap(
45455
45475
  nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
45456
45476
 
45457
45477
  if( pShmNode->nRegion<nReqRegion ){
45458
- char **apNew; /* New apRegion[] array */
45459
- int nByte = nReqRegion*szRegion; /* Minimum required file size */
45460
- struct stat sStat; /* Used by fstat() */
45478
+ char **apNew; /* New apRegion[] array */
45479
+ i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
45480
+ struct stat sStat; /* Used by fstat() */
45461
45481
 
45462
45482
  pShmNode->szRegion = szRegion;
45463
45483
 
@@ -45488,7 +45508,7 @@ static int unixShmMap(
45488
45508
  */
45489
45509
  else{
45490
45510
  static const int pgsz = 4096;
45491
- int iPg;
45511
+ i64 iPg;
45492
45512
 
45493
45513
  /* Write to the last byte of each newly allocated or extended page */
45494
45514
  assert( (nByte % pgsz)==0 );
@@ -45514,8 +45534,8 @@ static int unixShmMap(
45514
45534
  }
45515
45535
  pShmNode->apRegion = apNew;
45516
45536
  while( pShmNode->nRegion<nReqRegion ){
45517
- int nMap = szRegion*nShmPerMap;
45518
- int i;
45537
+ i64 nMap = (i64)szRegion*(i64)nShmPerMap;
45538
+ i64 i;
45519
45539
  void *pMem;
45520
45540
  if( pShmNode->hShm>=0 ){
45521
45541
  pMem = osMmap(0, nMap,
@@ -53489,7 +53509,7 @@ static int winShmMap(
53489
53509
  if( pShmNode->nRegion<=iRegion ){
53490
53510
  HANDLE hShared = pShmNode->hSharedShm;
53491
53511
  struct ShmRegion *apNew; /* New aRegion[] array */
53492
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
53512
+ i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
53493
53513
  sqlite3_int64 sz; /* Current size of wal-index file */
53494
53514
 
53495
53515
  pShmNode->szRegion = szRegion;
@@ -53520,7 +53540,7 @@ static int winShmMap(
53520
53540
 
53521
53541
  /* Map the requested memory region into this processes address space. */
53522
53542
  apNew = (struct ShmRegion*)sqlite3_realloc64(
53523
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
53543
+ pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
53524
53544
  );
53525
53545
  if( !apNew ){
53526
53546
  rc = SQLITE_IOERR_NOMEM_BKPT;
@@ -53542,15 +53562,14 @@ static int winShmMap(
53542
53562
  #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
53543
53563
  hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
53544
53564
  #endif
53545
-
53546
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
53565
+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
53547
53566
  osGetCurrentProcessId(), pShmNode->nRegion, nByte,
53548
53567
  hMap ? "ok" : "failed"));
53549
53568
  if( hMap ){
53550
- int iOffset = pShmNode->nRegion*szRegion;
53569
+ i64 iOffset = pShmNode->nRegion*szRegion;
53551
53570
  int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
53552
53571
  pMap = osMapViewOfFile(hMap, flags,
53553
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
53572
+ 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
53554
53573
  );
53555
53574
  OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
53556
53575
  osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
@@ -53572,7 +53591,7 @@ static int winShmMap(
53572
53591
 
53573
53592
  shmpage_out:
53574
53593
  if( pShmNode->nRegion>iRegion ){
53575
- int iOffset = iRegion*szRegion;
53594
+ i64 iOffset = (i64)iRegion*(i64)szRegion;
53576
53595
  int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
53577
53596
  char *p = (char *)pShmNode->aRegion[iRegion].pMap;
53578
53597
  *pp = (void *)&p[iOffsetShift];
@@ -62301,7 +62320,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
62301
62320
  if( rc!=SQLITE_OK ) goto delsuper_out;
62302
62321
  nSuperPtr = 1 + (i64)pVfs->mxPathname;
62303
62322
  assert( nSuperJournal>=0 && nSuperPtr>0 );
62304
- zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
62323
+ zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
62305
62324
  if( !zFree ){
62306
62325
  rc = SQLITE_NOMEM_BKPT;
62307
62326
  goto delsuper_out;
@@ -62562,10 +62581,10 @@ static int pager_playback(Pager *pPager, int isHot){
62562
62581
  **
62563
62582
  ** TODO: Technically the following is an error because it assumes that
62564
62583
  ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
62565
- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
62584
+ ** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
62566
62585
  ** mxPathname is 512, which is the same as the minimum allowable value
62567
- ** for pageSize.
62568
- */
62586
+ ** for pageSize, and so this assumption holds. But it might not for some
62587
+ ** custom VFS. */
62569
62588
  zSuper = pPager->pTmpSpace;
62570
62589
  rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
62571
62590
  if( rc==SQLITE_OK && zSuper[0] ){
@@ -78455,7 +78474,9 @@ static int accessPayload(
78455
78474
  ** means "not yet known" (the cache is lazily populated).
78456
78475
  */
78457
78476
  if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
78458
- int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
78477
+ i64 nOvfl = pCur->info.nPayload;
78478
+ testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
78479
+ nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
78459
78480
  if( pCur->aOverflow==0
78460
78481
  || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
78461
78482
  ){
@@ -78560,6 +78581,12 @@ static int accessPayload(
78560
78581
  (eOp==0 ? PAGER_GET_READONLY : 0)
78561
78582
  );
78562
78583
  if( rc==SQLITE_OK ){
78584
+ if( eOp!=0
78585
+ && (sqlite3PagerPageRefcount(pDbPage)!=1
78586
+ || NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit)) ){
78587
+ sqlite3PagerUnref(pDbPage);
78588
+ return SQLITE_CORRUPT_PAGE(pPage);
78589
+ }
78563
78590
  aPayload = sqlite3PagerGetData(pDbPage);
78564
78591
  nextPage = get4byte(aPayload);
78565
78592
  rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
@@ -111254,6 +111281,7 @@ static int lookupName(
111254
111281
  pExpr->op = TK_FUNCTION;
111255
111282
  pExpr->u.zToken = "coalesce";
111256
111283
  pExpr->x.pList = pFJMatch;
111284
+ pExpr->affExpr = SQLITE_AFF_DEFER;
111257
111285
  cnt = 1;
111258
111286
  goto lookupname_end;
111259
111287
  }else{
@@ -111422,6 +111450,26 @@ static int exprProbability(Expr *p){
111422
111450
  return (int)(r*134217728.0);
111423
111451
  }
111424
111452
 
111453
+ /*
111454
+ ** Set the EP_SubtArg property on every expression inside of
111455
+ ** pList. If any subexpression is actually a subquery, then
111456
+ ** also set the EP_SubtArg property on the first result-set
111457
+ ** column of that subquery.
111458
+ */
111459
+ static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
111460
+ int nn, ii;
111461
+ nn = pList ? pList->nExpr : 0;
111462
+ for(ii=0; ii<nn; ii++){
111463
+ Expr *pExpr = pList->a[ii].pExpr;
111464
+ ExprSetProperty(pExpr, EP_SubtArg);
111465
+ if( pExpr->op==TK_SELECT ){
111466
+ assert( ExprUseXSelect(pExpr) );
111467
+ assert( pExpr->x.pSelect!=0 );
111468
+ resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
111469
+ }
111470
+ }
111471
+ }
111472
+
111425
111473
  /*
111426
111474
  ** This routine is callback for sqlite3WalkExpr().
111427
111475
  **
@@ -111666,10 +111714,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
111666
111714
  if( (pDef->funcFlags & SQLITE_SUBTYPE)
111667
111715
  || ExprHasProperty(pExpr, EP_SubtArg)
111668
111716
  ){
111669
- int ii;
111670
- for(ii=0; ii<n; ii++){
111671
- ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
111672
- }
111717
+ resolveSetExprSubtypeArg(pList);
111673
111718
  }
111674
111719
 
111675
111720
  if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
@@ -117064,7 +117109,16 @@ static void sqlite3ExprCodeIN(
117064
117109
  CollSeq *pColl;
117065
117110
  int r3 = sqlite3GetTempReg(pParse);
117066
117111
  p = sqlite3VectorFieldSubexpr(pLeft, i);
117067
- pColl = sqlite3ExprCollSeq(pParse, p);
117112
+ if( ExprUseXSelect(pExpr) ){
117113
+ Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
117114
+ pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
117115
+ }else{
117116
+ /* If the RHS of the IN(...) expression are scalar expressions, do
117117
+ ** not consider their collation sequences. The documentation says
117118
+ ** "The collating sequence used for expressions of the form "x IN (y, z,
117119
+ ** ...)" is the collating sequence of x.". */
117120
+ pColl = sqlite3ExprCollSeq(pParse, p);
117121
+ }
117068
117122
  sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
117069
117123
  sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
117070
117124
  (void*)pColl, P4_COLLSEQ);
@@ -117487,26 +117541,37 @@ static int exprCodeInlineFunction(
117487
117541
  }
117488
117542
 
117489
117543
  /*
117490
- ** Expression Node callback for sqlite3ExprCanReturnSubtype().
117544
+ ** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
117545
+ ** pExpr is able to return a subtype, set pWalker->eCode and abort
117546
+ ** the search. If pExpr can never return a subtype, prune search.
117547
+ **
117548
+ ** The only expressions that can return a subtype are:
117491
117549
  **
117492
- ** Only a function call is able to return a subtype. So if the node
117493
- ** is not a function call, return WRC_Prune immediately.
117550
+ ** 1. A function
117551
+ ** 2. The no-op "+" operator
117552
+ ** 3. A CASE...END expression
117553
+ ** 4. A CAST() expression
117554
+ ** 5. A "expr COLLATE colseq" expression.
117494
117555
  **
117495
- ** A function call is able to return a subtype if it has the
117496
- ** SQLITE_RESULT_SUBTYPE property.
117556
+ ** For any other kind of expression, prune the search.
117497
117557
  **
117498
- ** Assume that every function is able to pass-through a subtype from
117499
- ** one of its argument (using sqlite3_result_value()). Most functions
117500
- ** are not this way, but we don't have a mechanism to distinguish those
117501
- ** that are from those that are not, so assume they all work this way.
117502
- ** That means that if one of its arguments is another function and that
117503
- ** other function is able to return a subtype, then this function is
117504
- ** able to return a subtype.
117558
+ ** For case 1, the expression can yield a subtype if the function has
117559
+ ** the SQLITE_RESULT_SUBTYPE property. Functions can also return
117560
+ ** a subtype (via sqlite3_result_value()) if any of the arguments can
117561
+ ** return a subtype.
117562
+ **
117563
+ ** In all cases 1 through 5, the expression might also return a subtype
117564
+ ** if any operand can return a subtype.
117505
117565
  */
117506
117566
  static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
117507
117567
  int n;
117508
117568
  FuncDef *pDef;
117509
117569
  sqlite3 *db;
117570
+ if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
117571
+ || pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
117572
+ ){
117573
+ return WRC_Continue;
117574
+ }
117510
117575
  if( pExpr->op!=TK_FUNCTION ){
117511
117576
  return WRC_Prune;
117512
117577
  }
@@ -117516,7 +117581,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
117516
117581
  pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
117517
117582
  if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
117518
117583
  pWalker->eCode = 1;
117519
- return WRC_Prune;
117584
+ return WRC_Abort;
117520
117585
  }
117521
117586
  return WRC_Continue;
117522
117587
  }
@@ -123494,19 +123559,31 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
123494
123559
  SrcList *pSrc, /* Table to add constraint to */
123495
123560
  Token *pFirst, /* First token of new constraint */
123496
123561
  Token *pName, /* Name of new constraint. NULL if name omitted. */
123497
- const char *pExpr, /* Text of CHECK expression */
123498
- int nExpr /* Size of pExpr in bytes */
123562
+ const char *zExpr, /* Text of CHECK expression */
123563
+ int nExpr, /* Size of pExpr in bytes */
123564
+ Expr *pExpr /* The parsed CHECK expression */
123499
123565
  ){
123500
123566
  Table *pTab = 0; /* Table identified by pSrc */
123501
123567
  int iDb = 0; /* Which schema does pTab live in */
123502
123568
  const char *zDb = 0; /* Name of the schema in which pTab lives */
123503
123569
  const char *pCons = 0; /* Text of the constraint */
123504
123570
  int nCons; /* Bytes of text to use from pCons[] */
123571
+ int rc; /* Result from error checking pExpr */
123505
123572
 
123506
123573
  /* Look up the table being altered. */
123507
123574
  assert( pSrc->nSrc==1 );
123508
123575
  pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
123509
- if( !pTab ) return;
123576
+ if( !pTab ){
123577
+ sqlite3ExprDelete(pParse->db, pExpr);
123578
+ return;
123579
+ }
123580
+
123581
+ /* Verify that the new CHECK constraint does not contain any
123582
+ ** internal-use-only function. Forum post 2026-05-10T01:11:28Z
123583
+ */
123584
+ rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
123585
+ sqlite3ExprDelete(pParse->db, pExpr);
123586
+ if( rc ) return;
123510
123587
 
123511
123588
  /* If this new constraint has a name, check that it is not a duplicate of
123512
123589
  ** an existing constraint. It is an error if it is. */
@@ -123527,7 +123604,7 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
123527
123604
  sqlite3NestedParse(pParse,
123528
123605
  "SELECT sqlite_fail('constraint failed', %d) "
123529
123606
  "FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
123530
- SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr
123607
+ SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
123531
123608
  );
123532
123609
 
123533
123610
  /* Edit the SQL for the named table. */
@@ -134209,9 +134286,18 @@ static void printfFunc(
134209
134286
  sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
134210
134287
  str.printfFlags = SQLITE_PRINTF_SQLFUNC;
134211
134288
  sqlite3_str_appendf(&str, zFormat, &x);
134212
- n = str.nChar;
134213
- sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
134214
- SQLITE_DYNAMIC);
134289
+ if( str.accError==SQLITE_OK ){
134290
+ n = str.nChar;
134291
+ sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
134292
+ SQLITE_DYNAMIC);
134293
+ }else{
134294
+ if( str.accError==SQLITE_NOMEM ){
134295
+ sqlite3_result_error_nomem(context);
134296
+ }else{
134297
+ sqlite3_result_error_toobig(context);
134298
+ }
134299
+ sqlite3_str_reset(&str);
134300
+ }
134215
134301
  }
134216
134302
  }
134217
134303
 
@@ -135849,11 +135935,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
135849
135935
  assert( p->cnt>0 );
135850
135936
  p->cnt--;
135851
135937
  if( !p->approx ){
135852
- if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
135853
- p->ovrfl = 1;
135854
- p->approx = 1;
135938
+ i64 x = p->iSum;
135939
+ if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
135940
+ p->iSum = x;
135941
+ return;
135855
135942
  }
135856
- }else if( type==SQLITE_INTEGER ){
135943
+ p->ovrfl = 1;
135944
+ p->approx = 1;
135945
+ kahanBabuskaNeumaierInit(p, p->iSum);
135946
+ }
135947
+ if( type==SQLITE_INTEGER ){
135857
135948
  i64 iVal = sqlite3_value_int64(argv[0]);
135858
135949
  if( iVal!=SMALLEST_INT64 ){
135859
135950
  kahanBabuskaNeumaierStepInt64(p, -iVal);
@@ -136826,47 +136917,46 @@ static void percentSort(double *a, unsigned int n){
136826
136917
  int i; /* Loop counter */
136827
136918
  double rPivot; /* The pivot value */
136828
136919
 
136829
- assert( n>=2 );
136830
- if( a[0]>a[n-1] ){
136831
- SWAP_DOUBLE(a[0],a[n-1])
136832
- }
136833
- if( n==2 ) return;
136834
- iGt = n-1;
136835
- i = n/2;
136836
- if( a[0]>a[i] ){
136837
- SWAP_DOUBLE(a[0],a[i])
136838
- }else if( a[i]>a[iGt] ){
136839
- SWAP_DOUBLE(a[i],a[iGt])
136840
- }
136841
- if( n==3 ) return;
136842
- rPivot = a[i];
136843
- iLt = i = 1;
136844
- do{
136845
- if( a[i]<rPivot ){
136846
- if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
136847
- iLt++;
136848
- i++;
136849
- }else if( a[i]>rPivot ){
136850
- do{
136851
- iGt--;
136852
- }while( iGt>i && a[iGt]>rPivot );
136920
+ while( n>=2 ){
136921
+ if( a[0]>a[n-1] ){
136922
+ SWAP_DOUBLE(a[0],a[n-1])
136923
+ }
136924
+ if( n==2 ) return;
136925
+ iGt = n-1;
136926
+ i = n/2;
136927
+ if( a[0]>a[i] ){
136928
+ SWAP_DOUBLE(a[0],a[i])
136929
+ }else if( a[i]>a[iGt] ){
136853
136930
  SWAP_DOUBLE(a[i],a[iGt])
136931
+ }
136932
+ if( n==3 ) return;
136933
+ rPivot = a[i];
136934
+ iLt = i = 1;
136935
+ do{
136936
+ if( a[i]<rPivot ){
136937
+ if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
136938
+ iLt++;
136939
+ i++;
136940
+ }else if( a[i]>rPivot ){
136941
+ do{
136942
+ iGt--;
136943
+ }while( iGt>i && a[iGt]>rPivot );
136944
+ SWAP_DOUBLE(a[i],a[iGt])
136945
+ }else{
136946
+ i++;
136947
+ }
136948
+ }while( i<iGt );
136949
+ if( iLt>n/2 ){
136950
+ if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
136951
+ n = iLt;
136854
136952
  }else{
136855
- i++;
136953
+ if( iLt>=2 ) percentSort(a, iLt);
136954
+ a += iGt;
136955
+ n -= iGt;
136856
136956
  }
136857
- }while( i<iGt );
136858
- if( iLt>=2 ) percentSort(a, iLt);
136859
- if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
136860
-
136861
- /* Uncomment for testing */
136862
- #if 0
136863
- for(i=0; i<n-1; i++){
136864
- assert( a[i]<=a[i+1] );
136865
136957
  }
136866
- #endif
136867
136958
  }
136868
136959
 
136869
-
136870
136960
  /*
136871
136961
  ** The "inverse" function for percentile(Y,P) is called to remove a
136872
136962
  ** row that was previously inserted by "step".
@@ -156364,8 +156454,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
156364
156454
  ** does not refer to a table to the right of CheckOnCtx.iJoin. */
156365
156455
  do {
156366
156456
  SrcList *pSrc = pCtx->pSrc;
156457
+ int nSrc = pSrc->nSrc;
156367
156458
  int iTab = pExpr->iTable;
156368
- if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
156459
+ int ii;
156460
+ for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
156461
+ if( ii<nSrc ){
156369
156462
  if( pCtx->iJoin && iTab>pCtx->iJoin ){
156370
156463
  sqlite3ErrorMsg(pWalker->pParse,
156371
156464
  "%s references tables to its right",
@@ -166574,6 +166667,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
166574
166667
  WO_EQ|WO_IN|WO_IS, 0);
166575
166668
  if( pAlt==0 ) continue;
166576
166669
  if( pAlt->wtFlags & (TERM_CODED) ) continue;
166670
+ if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
166577
166671
  if( (pAlt->eOperator & WO_IN)
166578
166672
  && ExprUseXSelect(pAlt->pExpr)
166579
166673
  && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
@@ -167766,8 +167860,8 @@ static void exprAnalyzeOrTerm(
167766
167860
  ** 3. Not originating in the ON clause of an OUTER JOIN
167767
167861
  ** 4. The operator is not IS or else the query does not contain RIGHT JOIN
167768
167862
  ** 5. The affinities of A and B must be compatible
167769
- ** 6a. Both operands use the same collating sequence OR
167770
- ** 6b. The overall collating sequence is BINARY
167863
+ ** 6. Both operands use the same collating sequence, and they must not
167864
+ ** use explicit COLLATE clauses.
167771
167865
  ** If this routine returns TRUE, that means that the RHS can be substituted
167772
167866
  ** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
167773
167867
  ** This is an optimization. No harm comes from returning 0. But if 1 is
@@ -167775,10 +167869,9 @@ static void exprAnalyzeOrTerm(
167775
167869
  */
167776
167870
  static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
167777
167871
  char aff1, aff2;
167778
- CollSeq *pColl;
167779
167872
  if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
167780
167873
  if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
167781
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
167874
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
167782
167875
  assert( pSrc!=0 );
167783
167876
  if( pExpr->op==TK_IS
167784
167877
  && pSrc->nSrc>=2
@@ -167793,10 +167886,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
167793
167886
  ){
167794
167887
  return 0; /* (5) */
167795
167888
  }
167796
- pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
167797
- if( !sqlite3IsBinary(pColl)
167798
- && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
167799
- ){
167889
+ if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
167800
167890
  return 0; /* (6) */
167801
167891
  }
167802
167892
  return 1;
@@ -168128,7 +168218,7 @@ static void exprAnalyze(
168128
168218
  /* Analyze a term that is composed of two or more subterms connected by
168129
168219
  ** an OR operator.
168130
168220
  */
168131
- else if( pExpr->op==TK_OR ){
168221
+ else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
168132
168222
  assert( pWC->op==TK_AND );
168133
168223
  exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
168134
168224
  pTerm = &pWC->a[idxTerm];
@@ -171946,7 +172036,8 @@ static int whereRangeVectorLen(
171946
172036
  idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
171947
172037
  if( aff!=idxaff ) break;
171948
172038
 
171949
- pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
172039
+ if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
172040
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
171950
172041
  if( pColl==0 ) break;
171951
172042
  if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
171952
172043
  }
@@ -184438,9 +184529,11 @@ static YYACTIONTYPE yy_reduce(
184438
184529
  ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
184439
184530
  yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
184440
184531
  if( yymsp[-4].minor.yy454 ){
184532
+ int i;
184441
184533
  yymsp[-4].minor.yy454->x.pList = pList;
184442
- if( ALWAYS(pList->nExpr) ){
184443
- yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate;
184534
+ for(i=0; i<pList->nExpr; i++){
184535
+ assert( pList->a[i].pExpr!=0 );
184536
+ yymsp[-4].minor.yy454->flags |= pList->a[i].pExpr->flags & EP_Propagate;
184444
184537
  }
184445
184538
  }else{
184446
184539
  sqlite3ExprListDelete(pParse->db, pList);
@@ -184908,15 +185001,13 @@ static YYACTIONTYPE yy_reduce(
184908
185001
  break;
184909
185002
  case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
184910
185003
  {
184911
- 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));
185004
+ 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);
184912
185005
  }
184913
- yy_destructor(yypParser,219,&yymsp[-2].minor);
184914
185006
  break;
184915
185007
  case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
184916
185008
  {
184917
- 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));
185009
+ 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);
184918
185010
  }
184919
- yy_destructor(yypParser,219,&yymsp[-2].minor);
184920
185011
  break;
184921
185012
  case 302: /* cmd ::= create_vtab */
184922
185013
  {sqlite3VtabFinishParse(pParse,0);}
@@ -194133,6 +194224,12 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
194133
194224
  SQLITE_EXTENSION_INIT1
194134
194225
  #endif
194135
194226
 
194227
+
194228
+ /*
194229
+ ** Assume any b-tree layer with more levels than this is corrupt.
194230
+ */
194231
+ #define FTS3_MAX_BTREE_HEIGHT 48
194232
+
194136
194233
  typedef struct Fts3HashWrapper Fts3HashWrapper;
194137
194234
  struct Fts3HashWrapper {
194138
194235
  Fts3Hash hash; /* Hash table */
@@ -195849,7 +195946,11 @@ static int fts3SelectLeaf(
195849
195946
  assert( piLeaf || piLeaf2 );
195850
195947
 
195851
195948
  fts3GetVarint32(zNode, &iHeight);
195852
- rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195949
+ if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
195950
+ rc = FTS_CORRUPT_VTAB;
195951
+ }else{
195952
+ rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
195953
+ }
195853
195954
  assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
195854
195955
 
195855
195956
  if( rc==SQLITE_OK && iHeight>1 ){
@@ -200378,7 +200479,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
200378
200479
  /* State 3. The integer just read is a column number. */
200379
200480
  default: assert( eState==3 );
200380
200481
  iCol = (int)v;
200381
- if( iCol<1 ){
200482
+ if( iCol<1 || iCol>(pFts3->nColumn+1) ){
200382
200483
  rc = SQLITE_CORRUPT_VTAB;
200383
200484
  break;
200384
200485
  }
@@ -201068,6 +201169,7 @@ static int getNextNode(
201068
201169
  assert( nKey==4 );
201069
201170
  if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
201070
201171
  nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
201172
+ if( nNear>=1000000000 ) nNear = 1000000000;
201071
201173
  }
201072
201174
  }
201073
201175
 
@@ -210931,7 +211033,7 @@ static int fts3ExprLHits(
210931
211033
  if( p->flag==FTS3_MATCHINFO_LHITS ){
210932
211034
  p->aMatchinfo[iStart + iCol] = (u32)nHit;
210933
211035
  }else if( nHit ){
210934
- p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
211036
+ p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
210935
211037
  }
210936
211038
  }
210937
211039
  assert( *pIter==0x00 || *pIter==0x01 );
@@ -213421,7 +213523,7 @@ static void jsonAppendSqlValue(
213421
213523
  break;
213422
213524
  }
213423
213525
  case SQLITE_FLOAT: {
213424
- jsonPrintf(100, p, "%!0.15g", sqlite3_value_double(pValue));
213526
+ jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
213425
213527
  break;
213426
213528
  }
213427
213529
  case SQLITE_INTEGER: {
@@ -214735,9 +214837,10 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
214735
214837
  u8 x;
214736
214838
  u32 sz;
214737
214839
  u32 n;
214738
- assert( i<=pParse->nBlob );
214739
- x = pParse->aBlob[i]>>4;
214740
- if( x<=11 ){
214840
+ if( i>=pParse->nBlob ){
214841
+ *pSz = 0;
214842
+ return 0;
214843
+ }else if( (x = pParse->aBlob[i]>>4)<=11 ){
214741
214844
  sz = x;
214742
214845
  n = 1;
214743
214846
  }else if( x==12 ){
@@ -217520,11 +217623,9 @@ static void jsonGroupInverse(
217520
217623
  UNUSED_PARAMETER(argc);
217521
217624
  UNUSED_PARAMETER(argv);
217522
217625
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
217523
- #ifdef NEVER
217524
217626
  /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
217525
217627
  ** always have been called to initialize it */
217526
217628
  if( NEVER(!pStr) ) return;
217527
- #endif
217528
217629
  z = pStr->zBuf;
217529
217630
  for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
217530
217631
  if( c=='"' ){
@@ -217553,6 +217654,13 @@ static void jsonGroupInverse(
217553
217654
  ** json_group_obj(NAME,VALUE)
217554
217655
  **
217555
217656
  ** Return a JSON object composed of all names and values in the aggregate.
217657
+ **
217658
+ ** Rows for which NAME is NULL do not result in a new entry. However, we
217659
+ ** do initially insert a "@" entry into the growing string for each null entry
217660
+ ** and change the first character of the string to "@" to signal that the
217661
+ ** string contains null entries. The "@" markers are needed in order to
217662
+ ** correctly process xInverse() requests. The initial "@" is converted
217663
+ ** back into "{" and the "@" null values are removed by jsonObjectCompute().
217556
217664
  */
217557
217665
  static void jsonObjectStep(
217558
217666
  sqlite3_context *ctx,
@@ -217570,7 +217678,7 @@ static void jsonObjectStep(
217570
217678
  if( pStr->zBuf==0 ){
217571
217679
  jsonStringInit(pStr, ctx);
217572
217680
  jsonAppendChar(pStr, '{');
217573
- }else if( pStr->nUsed>1 && z!=0 ){
217681
+ }else if( pStr->nUsed>1 ){
217574
217682
  jsonAppendChar(pStr, ',');
217575
217683
  }
217576
217684
  pStr->pCtx = ctx;
@@ -217578,6 +217686,9 @@ static void jsonObjectStep(
217578
217686
  jsonAppendString(pStr, z, n);
217579
217687
  jsonAppendChar(pStr, ':');
217580
217688
  jsonAppendSqlValue(pStr, argv[1]);
217689
+ }else{
217690
+ pStr->zBuf[0] = '@';
217691
+ jsonAppendRawNZ(pStr, "@", 1);
217581
217692
  }
217582
217693
  }
217583
217694
  }
@@ -217586,20 +217697,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
217586
217697
  int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
217587
217698
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
217588
217699
  if( pStr ){
217589
- jsonAppendRawNZ(pStr, "}", 2);
217590
- jsonStringTrimOneChar(pStr);
217700
+ JsonString *pOgStr = pStr;
217701
+ JsonString tmpStr;
217702
+ jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
217703
+ jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
217591
217704
  pStr->pCtx = ctx;
217592
217705
  if( pStr->eErr ){
217593
217706
  jsonReturnString(pStr, 0, 0);
217594
217707
  return;
217595
- }else if( flags & JSON_BLOB ){
217708
+ }
217709
+ if( pStr->zBuf[0]!='{' ){
217710
+ /* The string contains null entries that need to be removed */
217711
+ u64 i, j;
217712
+ int inStr = 0;
217713
+ if( !isFinal ){
217714
+ /* Work with a temporary copy of the string if this is not the
217715
+ ** final result */
217716
+ jsonStringInit(&tmpStr, ctx);
217717
+ jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
217718
+ pStr = &tmpStr;
217719
+ if( pStr->eErr ){
217720
+ jsonReturnString(pStr, 0, 0);
217721
+ return;
217722
+ }
217723
+ jsonStringTrimOneChar(pStr); /* Remove zero terminator */
217724
+ }
217725
+ /* Fix up the string by changing the initial "@" flag back to
217726
+ ** to "{" and removing all subsequence "@" entries, with their
217727
+ ** associated comma delimeters. */
217728
+ pStr->zBuf[0] = '{';
217729
+ for(i=j=1; i<pStr->nUsed; i++){
217730
+ char c = pStr->zBuf[i];
217731
+ if( c=='"' ){
217732
+ inStr = !inStr;
217733
+ pStr->zBuf[j++] = '"';
217734
+ }else if( c=='\\' ){
217735
+ pStr->zBuf[j++] = '\\';
217736
+ pStr->zBuf[j++] = pStr->zBuf[++i];
217737
+ }else if( c=='@' && !inStr ){
217738
+ assert( i+1<pStr->nUsed );
217739
+ if( pStr->zBuf[i+1]==',' ){
217740
+ i++;
217741
+ }else if( pStr->zBuf[j-1]==',' ){
217742
+ j--;
217743
+ }
217744
+ }else{
217745
+ pStr->zBuf[j++] = c;
217746
+ }
217747
+ }
217748
+ pStr->zBuf[j] = 0; /* Restore zero terminator */
217749
+ pStr->nUsed = j; /* Truncate the string */
217750
+ }
217751
+ if( flags & JSON_BLOB ){
217596
217752
  jsonReturnStringAsBlob(pStr);
217597
217753
  if( isFinal ){
217598
217754
  if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
217599
217755
  }else{
217600
- jsonStringTrimOneChar(pStr);
217756
+ jsonStringTrimOneChar(pOgStr);
217601
217757
  }
217602
- return;
217603
217758
  }else if( isFinal ){
217604
217759
  sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
217605
217760
  pStr->bStatic ? SQLITE_TRANSIENT :
@@ -217607,8 +217762,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
217607
217762
  pStr->bStatic = 1;
217608
217763
  }else{
217609
217764
  sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
217610
- jsonStringTrimOneChar(pStr);
217765
+ jsonStringTrimOneChar(pOgStr);
217611
217766
  }
217767
+ if( pStr!=pOgStr ) jsonStringReset(pStr);
217612
217768
  }else if( flags & JSON_BLOB ){
217613
217769
  static const unsigned char emptyObject = 0x0c;
217614
217770
  sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
@@ -218460,7 +218616,7 @@ struct Rtree {
218460
218616
  u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
218461
218617
  u8 nBytesPerCell; /* Bytes consumed per cell */
218462
218618
  u8 inWrTrans; /* True if inside write transaction */
218463
- u8 nAux; /* # of auxiliary columns in %_rowid */
218619
+ u16 nAux; /* # of auxiliary columns in %_rowid */
218464
218620
  #ifdef SQLITE_ENABLE_GEOPOLY
218465
218621
  u8 nAuxNotNull; /* Number of initial not-null aux columns */
218466
218622
  #endif
@@ -219696,7 +219852,7 @@ static int nodeRowidIndex(
219696
219852
  ){
219697
219853
  int ii;
219698
219854
  int nCell = NCELL(pNode);
219699
- assert( nCell<200 );
219855
+ assert( nCell<65536 && nCell>=0 );
219700
219856
  for(ii=0; ii<nCell; ii++){
219701
219857
  if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
219702
219858
  *piIndex = ii;
@@ -219958,7 +220114,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
219958
220114
  pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
219959
220115
  if( rc ) return rc;
219960
220116
  nCell = NCELL(pNode);
219961
- assert( nCell<200 );
220117
+ if( nCell>RTREE_MAXCELLS ){
220118
+ RTREE_IS_CORRUPT(pRtree);
220119
+ return SQLITE_CORRUPT_VTAB;
220120
+ }
219962
220121
  pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
219963
220122
  while( p->iCell<nCell ){
219964
220123
  sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
@@ -221935,7 +222094,7 @@ static int rtreeInit(
221935
222094
  "Auxiliary rtree columns must be last" /* 4 */
221936
222095
  };
221937
222096
 
221938
- assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
222097
+ assert( RTREE_MAX_AUX_COLUMN<256 );
221939
222098
  if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
221940
222099
  *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
221941
222100
  return SQLITE_ERROR;
@@ -223854,6 +224013,11 @@ static int geopolyInit(
223854
224013
  int ii;
223855
224014
  (void)pAux;
223856
224015
 
224016
+ if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
224017
+ *pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
224018
+ return SQLITE_ERROR;
224019
+ }
224020
+
223857
224021
  sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
223858
224022
  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
223859
224023
 
@@ -224988,7 +225152,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
224988
225152
  const UChar *zInput; /* Pointer to input string */
224989
225153
  UChar *zOutput = 0; /* Pointer to output buffer */
224990
225154
  int nInput; /* Size of utf-16 input string in bytes */
224991
- int nOut; /* Size of output buffer in bytes */
225155
+ sqlite3_int64 nOut; /* Size of output buffer in bytes */
224992
225156
  int cnt;
224993
225157
  int bToUpper; /* True for toupper(), false for tolower() */
224994
225158
  UErrorCode status;
@@ -225011,7 +225175,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
225011
225175
  }
225012
225176
 
225013
225177
  for(cnt=0; cnt<2; cnt++){
225014
- UChar *zNew = sqlite3_realloc(zOutput, nOut);
225178
+ UChar *zNew = sqlite3_realloc64(zOutput, nOut);
225015
225179
  if( zNew==0 ){
225016
225180
  sqlite3_free(zOutput);
225017
225181
  sqlite3_result_error_nomem(p);
@@ -225020,9 +225184,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
225020
225184
  zOutput = zNew;
225021
225185
  status = U_ZERO_ERROR;
225022
225186
  if( bToUpper ){
225023
- nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225187
+ nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225024
225188
  }else{
225025
- nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225189
+ nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
225026
225190
  }
225027
225191
 
225028
225192
  if( U_SUCCESS(status) ){
@@ -232737,12 +232901,13 @@ static int dbpageFilter(
232737
232901
  pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
232738
232902
  pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
232739
232903
  if( idxNum & 1 ){
232904
+ i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
232740
232905
  assert( argc>(idxNum>>1) );
232741
- pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
232742
- if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
232906
+ if( iPg<1 || iPg>pCsr->mxPgno ){
232743
232907
  pCsr->pgno = 1;
232744
232908
  pCsr->mxPgno = 0;
232745
232909
  }else{
232910
+ pCsr->pgno = (Pgno)iPg;
232746
232911
  pCsr->mxPgno = pCsr->pgno;
232747
232912
  }
232748
232913
  }else{
@@ -235089,6 +235254,16 @@ static int sessionPrepareDfltStmt(
235089
235254
  return rc;
235090
235255
  }
235091
235256
 
235257
+ /*
235258
+ ** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
235259
+ ** called, set it to the results of the sqlite3_finalize() call. Or, if
235260
+ ** it is already set to an error code, leave it as is.
235261
+ */
235262
+ static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
235263
+ int rc = sqlite3_finalize(pStmt);
235264
+ if( *pRc==SQLITE_OK ) *pRc = rc;
235265
+ }
235266
+
235092
235267
  /*
235093
235268
  ** Table pTab has one or more existing change-records with old.* records
235094
235269
  ** with fewer than pTab->nCol columns. This function updates all such
@@ -235111,9 +235286,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
235111
235286
  }
235112
235287
  }
235113
235288
 
235289
+ sessionFinalizeStmt(pStmt, &rc);
235114
235290
  pSession->rc = rc;
235115
- rc = sqlite3_finalize(pStmt);
235116
- if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
235117
235291
  return pSession->rc;
235118
235292
  }
235119
235293
 
@@ -235681,7 +235855,7 @@ static int sessionDiffFindNew(
235681
235855
  rc = SQLITE_NOMEM;
235682
235856
  }else{
235683
235857
  sqlite3_stmt *pStmt;
235684
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235858
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
235685
235859
  if( rc==SQLITE_OK ){
235686
235860
  SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
235687
235861
  pDiffCtx->pStmt = pStmt;
@@ -235744,7 +235918,7 @@ static int sessionDiffFindModified(
235744
235918
  rc = SQLITE_NOMEM;
235745
235919
  }else{
235746
235920
  sqlite3_stmt *pStmt;
235747
- rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0);
235921
+ rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
235748
235922
 
235749
235923
  if( rc==SQLITE_OK ){
235750
235924
  SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
@@ -236439,11 +236613,11 @@ static int sessionSelectStmt(
236439
236613
  );
236440
236614
  sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
236441
236615
  }else{
236442
- #if 0
236616
+ #if 0
236443
236617
  if( bRowid ){
236444
236618
  sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
236445
236619
  }
236446
- #endif
236620
+ #endif
236447
236621
  for(i=0; i<nCol; i++){
236448
236622
  if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
236449
236623
  sessionAppendIdent(&cols, azCol[i], &rc);
@@ -237697,7 +237871,13 @@ static int sessionChangesetInvert(
237697
237871
 
237698
237872
  /* Test for EOF. */
237699
237873
  if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
237700
- if( pInput->iNext>=pInput->nData ) break;
237874
+ if( pInput->iNext+1>=pInput->nData ){
237875
+ if( pInput->iNext!=pInput->nData ){
237876
+ rc = SQLITE_CORRUPT_BKPT;
237877
+ goto finished_invert;
237878
+ }
237879
+ break;
237880
+ }
237701
237881
  eType = pInput->aData[pInput->iNext];
237702
237882
 
237703
237883
  switch( eType ){
@@ -237893,6 +238073,7 @@ struct SessionApplyCtx {
237893
238073
  u8 bRebaseStarted; /* If table header is already in rebase */
237894
238074
  u8 bRebase; /* True to collect rebase information */
237895
238075
  u8 bIgnoreNoop; /* True to ignore no-op conflicts */
238076
+ u8 bNoUpdateLoop; /* No update-loop processing */
237896
238077
  int bRowid;
237897
238078
  char *zErr; /* Error message, if any */
237898
238079
  };
@@ -238466,7 +238647,7 @@ static int sessionConflictHandler(
238466
238647
  u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
238467
238648
  int nBlob = pIter->in.iNext - pIter->in.iCurrent;
238468
238649
  sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
238469
- return SQLITE_OK;
238650
+ return rc;
238470
238651
  }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
238471
238652
  || eType==SQLITE_CHANGESET_CONFLICT
238472
238653
  ){
@@ -238588,7 +238769,7 @@ static int sessionApplyOneOp(
238588
238769
  for(i=0; rc==SQLITE_OK && i<nCol; i++){
238589
238770
  sqlite3_value *pOld = sessionChangesetOld(pIter, i);
238590
238771
  sqlite3_value *pNew = sessionChangesetNew(pIter, i);
238591
- if( p->abPK[i] || (bPatchset==0 && pOld) ){
238772
+ if( pOld && (p->abPK[i] || bPatchset==0) ){
238592
238773
  rc = sessionBindValue(pUp, i*2+2, pOld);
238593
238774
  }
238594
238775
  if( rc==SQLITE_OK && pNew ){
@@ -238714,7 +238895,264 @@ static int sessionApplyOneWithRetry(
238714
238895
  }
238715
238896
 
238716
238897
  /*
238717
- ** Retry the changes accumulated in the pApply->constraints buffer.
238898
+ ** Create an iterator to iterate through the retry buffer pRetry.
238899
+ */
238900
+ static int sessionRetryIterInit(
238901
+ SessionBuffer *pRetry, /* Buffer to iterate through */
238902
+ int bPatchset, /* True for patchset, false for changeset */
238903
+ const char *zTab, /* Table name */
238904
+ SessionApplyCtx *pApply, /* Session apply context */
238905
+ sqlite3_changeset_iter **ppIter /* OUT: New iterator */
238906
+ ){
238907
+ sqlite3_changeset_iter *pRet = 0;
238908
+ int rc = SQLITE_OK;
238909
+
238910
+ rc = sessionChangesetStart(
238911
+ &pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
238912
+ );
238913
+ if( rc==SQLITE_OK ){
238914
+ size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
238915
+ pRet->bPatchset = bPatchset;
238916
+ pRet->zTab = (char*)zTab;
238917
+ pRet->nCol = pApply->nCol;
238918
+ pRet->abPK = pApply->abPK;
238919
+ sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
238920
+ pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
238921
+ if( rc==SQLITE_OK ){
238922
+ memset(pRet->apValue, 0, nByte);
238923
+ }else{
238924
+ sqlite3changeset_finalize(pRet);
238925
+ pRet = 0;
238926
+ }
238927
+ }
238928
+
238929
+ *ppIter = pRet;
238930
+ return rc;
238931
+ }
238932
+
238933
+ /*
238934
+ ** Attempt to apply all the changes in retry buffer pRetry to the database.
238935
+ ** Except, if parameter iSkip is greater than or equal to 0, skip change
238936
+ ** iSkip.
238937
+ */
238938
+ static int sessionApplyRetryBuffer(
238939
+ SessionBuffer *pRetry, /* Buffer to apply changes from */
238940
+ int iSkip, /* If >=0, index of change to omit */
238941
+ sqlite3 *db, /* Database handle */
238942
+ int bPatchset, /* True for patchset, false for changeset */
238943
+ const char *zTab, /* Name of table to write to */
238944
+ SessionApplyCtx *pApply, /* Apply context */
238945
+ int(*xConflict)(void*, int, sqlite3_changeset_iter*),
238946
+ void *pCtx /* First argument passed to xConflict */
238947
+ ){
238948
+ int rc = SQLITE_OK;
238949
+ int rc2 = SQLITE_OK;
238950
+ int ii = 0;
238951
+ sqlite3_changeset_iter *pIter = 0;
238952
+
238953
+ assert( pApply->constraints.nBuf==0 );
238954
+
238955
+ rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
238956
+
238957
+ for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
238958
+ if( ii!=iSkip ){
238959
+ rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
238960
+ }
238961
+ }
238962
+
238963
+ rc2 = sqlite3changeset_finalize(pIter);
238964
+ if( rc==SQLITE_OK ) rc = rc2;
238965
+ assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
238966
+
238967
+ return rc;
238968
+ }
238969
+
238970
+ /*
238971
+ ** Check if table zTab in the "main" database of db is a WITHOUT ROWID
238972
+ ** table.
238973
+ **
238974
+ ** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
238975
+ ** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
238976
+ ** error does occur, return an SQLite error code. The final value of (*pbWR)
238977
+ ** is undefined in this case.
238978
+ */
238979
+ static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
238980
+ sqlite3_stmt *pList = 0;
238981
+ char *zSql = 0;
238982
+ int rc = SQLITE_OK;
238983
+
238984
+ zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
238985
+ if( zSql==0 ){
238986
+ rc = SQLITE_NOMEM;
238987
+ }else{
238988
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
238989
+ sqlite3_free(zSql);
238990
+ }
238991
+
238992
+ if( rc==SQLITE_OK ){
238993
+ sqlite3_step(pList);
238994
+ *pbWR = sqlite3_column_int(pList, 4);
238995
+ rc = sqlite3_finalize(pList);
238996
+ }
238997
+
238998
+ return rc;
238999
+ }
239000
+
239001
+ /*
239002
+ ** Iterator pUp points to an UPDATE change. This function deletes the
239003
+ ** affected row from the database and creates an INSERT statement that
239004
+ ** may be used to reinsert the row as it is after the UPDATE change
239005
+ ** has been applied.
239006
+ **
239007
+ ** If successful, SQLITE_OK is returned and output variable (*ppInsert)
239008
+ ** is left pointing to a prepared INSERT statement. It is the responsibility
239009
+ ** of the caller to eventually free this statement using sqlite3_finalize().
239010
+ ** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
239011
+ ** set to NULL. pApply->zErr may be set to an error message in this case.
239012
+ */
239013
+ static int sessionUpdateToDeleteInsert(
239014
+ sqlite3 *db, /* Database to write to */
239015
+ const char *zTab, /* Table name */
239016
+ SessionApplyCtx *pApply, /* Apply context */
239017
+ sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
239018
+ sqlite3_stmt **ppInsert /* OUT: INSERT statement */
239019
+ ){
239020
+ sqlite3_stmt *pRet = 0; /* The INSERT statement */
239021
+ sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
239022
+ int rc = SQLITE_OK;
239023
+ int bWR = 0;
239024
+
239025
+ rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
239026
+ if( rc==SQLITE_OK ){
239027
+ char *zSelect = 0;
239028
+ char *zInsert = 0;
239029
+ SessionBuffer cols = {0, 0, 0};
239030
+ SessionBuffer insbind = {0, 0, 0};
239031
+ SessionBuffer pkcols = {0, 0, 0};
239032
+ SessionBuffer selbind = {0, 0, 0};
239033
+
239034
+ const char *zComma = "";
239035
+ const char *zComma2 = "";
239036
+ int ii;
239037
+ for(ii=0; ii<pApply->nCol; ii++){
239038
+ sessionAppendStr(&cols, zComma, &rc);
239039
+ sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
239040
+ sessionAppendStr(&insbind, zComma, &rc);
239041
+ sessionAppendStr(&insbind, "?", &rc);
239042
+ zComma = ", ";
239043
+
239044
+ if( pApply->abPK[ii] ){
239045
+ sessionAppendStr(&pkcols, zComma2, &rc);
239046
+ sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
239047
+ sessionAppendStr(&selbind, zComma2, &rc);
239048
+ sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
239049
+ zComma2 = ", ";
239050
+ }
239051
+ }
239052
+ if( bWR==0 ){
239053
+ sessionAppendStr(&cols, zComma, &rc);
239054
+ sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
239055
+ sessionAppendStr(&insbind, zComma, &rc);
239056
+ sessionAppendStr(&insbind, "?", &rc);
239057
+ }
239058
+
239059
+ if( rc==SQLITE_OK ){
239060
+ zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
239061
+ cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
239062
+ );
239063
+ if( zSelect==0 ) rc = SQLITE_NOMEM;
239064
+ }
239065
+ if( rc==SQLITE_OK ){
239066
+ zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
239067
+ zTab, cols.aBuf, insbind.aBuf
239068
+ );
239069
+ if( zInsert==0 ) rc = SQLITE_NOMEM;
239070
+ }
239071
+
239072
+ if( rc==SQLITE_OK ){
239073
+ rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
239074
+ }
239075
+ if( rc==SQLITE_OK ){
239076
+ rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
239077
+ }
239078
+
239079
+ sqlite3_free(zSelect);
239080
+ sqlite3_free(zInsert);
239081
+ sqlite3_free(cols.aBuf);
239082
+ sqlite3_free(insbind.aBuf);
239083
+ sqlite3_free(pkcols.aBuf);
239084
+ sqlite3_free(selbind.aBuf);
239085
+ }
239086
+
239087
+ if( rc==SQLITE_OK ){
239088
+ rc = sessionBindRow(
239089
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
239090
+ );
239091
+ }
239092
+
239093
+ if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
239094
+ int iCol;
239095
+ for(iCol=0; iCol<pApply->nCol; iCol++){
239096
+ sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
239097
+ if( pVal==0 ){
239098
+ pVal = sqlite3_column_value(pSelect, iCol);
239099
+ }
239100
+ rc = sqlite3_bind_value(pRet, iCol+1, pVal);
239101
+ }
239102
+ if( bWR==0 ){
239103
+ sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
239104
+ }
239105
+ }
239106
+ sessionFinalizeStmt(pSelect, &rc);
239107
+
239108
+ /* Delete the row from the database. */
239109
+ if( rc==SQLITE_OK ){
239110
+ rc = sessionBindRow(
239111
+ pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
239112
+ );
239113
+ sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
239114
+ }
239115
+ if( rc==SQLITE_OK ){
239116
+ sqlite3_step(pApply->pDelete);
239117
+ rc = sqlite3_reset(pApply->pDelete);
239118
+ }
239119
+
239120
+ if( rc!=SQLITE_OK ){
239121
+ sqlite3_finalize(pRet);
239122
+ pRet = 0;
239123
+ }
239124
+
239125
+ *ppInsert = pRet;
239126
+ return rc;
239127
+ }
239128
+
239129
+ /*
239130
+ ** Retry the changes accumulated in the pApply->constraints buffer. The
239131
+ ** pApply->constraints buffer contains all changes to table zTab that
239132
+ ** could not be applied due to SQLITE_CONSTRAINT errors. This function
239133
+ ** attempts to apply them as follows:
239134
+ **
239135
+ ** 1) It runs through the buffer and attempts to retry each change,
239136
+ ** removing any that are successfully applied from the buffer. This
239137
+ ** is repeated until no further progress can be made.
239138
+ **
239139
+ ** 2) For each UPDATE change in the buffer, try the following in a
239140
+ ** savepoint transaction:
239141
+ **
239142
+ ** a) DELETE the affected row,
239143
+ ** b) Attempt step (1) with remaining changes,
239144
+ ** c) Attempt to INSERT a row equivalent to the one that would be
239145
+ ** created by applying this UPDATE change.
239146
+ **
239147
+ ** If the INSERT in (c) succeeds, the savepoint is committed and all
239148
+ ** successfully applied changes are removed from the buffer. Step (2)
239149
+ ** is then repeated.
239150
+ **
239151
+ ** 3) Once step (2) has been attempted for each UPDATE in the change,
239152
+ ** a final attempt is made to apply each remaining change. This time,
239153
+ ** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
239154
+ ** is invoked and the user has to decide whether to omit the change
239155
+ ** or rollback the entire _apply() operation.
238718
239156
  */
238719
239157
  static int sessionRetryConstraints(
238720
239158
  sqlite3 *db,
@@ -238725,41 +239163,101 @@ static int sessionRetryConstraints(
238725
239163
  void *pCtx /* First argument passed to xConflict */
238726
239164
  ){
238727
239165
  int rc = SQLITE_OK;
239166
+ int iUpdate = 0;
238728
239167
 
239168
+ /* Step (1) */
238729
239169
  while( pApply->constraints.nBuf ){
238730
- sqlite3_changeset_iter *pIter2 = 0;
238731
239170
  SessionBuffer cons = pApply->constraints;
238732
239171
  memset(&pApply->constraints, 0, sizeof(SessionBuffer));
238733
239172
 
238734
- rc = sessionChangesetStart(
238735
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
239173
+ rc = sessionApplyRetryBuffer(
239174
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
239175
+ );
239176
+
239177
+ sqlite3_free(cons.aBuf);
239178
+ if( rc!=SQLITE_OK ) break;
239179
+
239180
+ /* If no progress has been made this round, break out of the loop. */
239181
+ if( pApply->constraints.nBuf>=cons.nBuf ) break;
239182
+ }
239183
+
239184
+ /* Step (2) */
239185
+ while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
239186
+ SessionBuffer cons = {0, 0, 0};
239187
+ sqlite3_changeset_iter *pUp = 0;
239188
+ sqlite3_stmt *pInsert = 0;
239189
+ int iSkip = 0;
239190
+
239191
+ rc = sessionRetryIterInit(
239192
+ &pApply->constraints, bPatchset, zTab, pApply, &pUp
238736
239193
  );
238737
239194
  if( rc==SQLITE_OK ){
238738
- size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
238739
- int rc2;
238740
- pIter2->bPatchset = bPatchset;
238741
- pIter2->zTab = (char*)zTab;
238742
- pIter2->nCol = pApply->nCol;
238743
- pIter2->abPK = pApply->abPK;
238744
- sessionBufferGrow(&pIter2->tblhdr, nByte, &rc);
238745
- pIter2->apValue = (sqlite3_value**)pIter2->tblhdr.aBuf;
238746
- if( rc==SQLITE_OK ) memset(pIter2->apValue, 0, nByte);
239195
+ int iThis = -1;
239196
+ while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
239197
+ if( pUp->op==SQLITE_UPDATE ) iThis++;
239198
+ if( iThis==iUpdate ) break;
239199
+ iSkip++;
239200
+ }
239201
+ if( iThis==iUpdate ){
239202
+ rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
239203
+ if( rc==SQLITE_OK ){
239204
+ rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
239205
+ }
239206
+ }
239207
+ sqlite3changeset_finalize(pUp);
239208
+ if( iThis!=iUpdate ) break;
239209
+ }
239210
+
239211
+ if( rc==SQLITE_OK ){
239212
+ cons = pApply->constraints;
238747
239213
 
238748
- while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter2) ){
238749
- rc = sessionApplyOneWithRetry(db, pIter2, pApply, xConflict, pCtx);
239214
+ while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
239215
+ SessionBuffer app = pApply->constraints;
239216
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
239217
+ rc = sessionApplyRetryBuffer(
239218
+ &app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
239219
+ );
239220
+ if( app.aBuf!=cons.aBuf ){
239221
+ sqlite3_free(app.aBuf);
239222
+ }
239223
+ if( pApply->constraints.nBuf>=app.nBuf ){
239224
+ break;
239225
+ }
239226
+ iSkip = -1;
238750
239227
  }
239228
+ }
238751
239229
 
238752
- rc2 = sqlite3changeset_finalize(pIter2);
238753
- if( rc==SQLITE_OK ) rc = rc2;
239230
+ iUpdate++;
239231
+ if( rc==SQLITE_OK ){
239232
+ sqlite3_step(pInsert);
239233
+ rc = sqlite3_finalize(pInsert);
239234
+ if( rc==SQLITE_CONSTRAINT ){
239235
+ rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
239236
+ sqlite3_free(pApply->constraints.aBuf);
239237
+ pApply->constraints = cons;
239238
+ memset(&cons, 0, sizeof(cons));
239239
+ }else if( rc==SQLITE_OK ){
239240
+ iUpdate = 0;
239241
+ }
239242
+ if( rc==SQLITE_OK ){
239243
+ rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
239244
+ }
239245
+ }else{
239246
+ sqlite3_finalize(pInsert);
238754
239247
  }
238755
- assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
238756
239248
 
238757
239249
  sqlite3_free(cons.aBuf);
238758
- if( rc!=SQLITE_OK ) break;
238759
- if( pApply->constraints.nBuf>=cons.nBuf ){
238760
- /* No progress was made on the last round. */
238761
- pApply->bDeferConstraints = 0;
238762
- }
239250
+ }
239251
+
239252
+ /* Step (3) */
239253
+ if( rc==SQLITE_OK && pApply->constraints.nBuf ){
239254
+ SessionBuffer cons = pApply->constraints;
239255
+ memset(&pApply->constraints, 0, sizeof(SessionBuffer));
239256
+ pApply->bDeferConstraints = 0;
239257
+ rc = sessionApplyRetryBuffer(
239258
+ &cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
239259
+ );
239260
+ sqlite3_free(cons.aBuf);
238763
239261
  }
238764
239262
 
238765
239263
  return rc;
@@ -238813,6 +239311,7 @@ static int sessionChangesetApply(
238813
239311
  sApply.bRebase = (ppRebase && pnRebase);
238814
239312
  sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
238815
239313
  sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
239314
+ sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
238816
239315
  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
238817
239316
  rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
238818
239317
  }
@@ -240624,7 +241123,7 @@ SQLITE_API int sqlite3changegroup_change_blob(
240624
241123
  const void *pVal,
240625
241124
  int nVal
240626
241125
  ){
240627
- sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + nVal;
241126
+ sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
240628
241127
  int rc = SQLITE_OK;
240629
241128
  SessionBuffer *pBuf = 0;
240630
241129
 
@@ -251208,7 +251707,7 @@ static void fts5DataRelease(Fts5Data *pData){
251208
251707
  static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
251209
251708
  Fts5Data *pRet = fts5DataRead(p, iRowid);
251210
251709
  if( pRet ){
251211
- if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
251710
+ if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
251212
251711
  FTS5_CORRUPT_ROWID(p, iRowid);
251213
251712
  fts5DataRelease(pRet);
251214
251713
  pRet = 0;
@@ -252862,6 +253361,10 @@ static void fts5LeafSeek(
252862
253361
  if( nKeep<nMatch ){
252863
253362
  goto search_failed;
252864
253363
  }
253364
+ if( (iOff+nNew)>n ){
253365
+ FTS5_CORRUPT_ITER(p, pIter);
253366
+ return;
253367
+ }
252865
253368
 
252866
253369
  assert( nKeep>=nMatch );
252867
253370
  if( nKeep==nMatch ){
@@ -253838,8 +254341,7 @@ static void fts5PoslistFilterCallback(
253838
254341
 
253839
254342
  do {
253840
254343
  while( i<nChunk && pChunk[i]!=0x01 ){
253841
- while( pChunk[i] & 0x80 ) i++;
253842
- i++;
254344
+ fts5IndexSkipVarint(pChunk, i);
253843
254345
  }
253844
254346
  if( pCtx->eState ){
253845
254347
  fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
@@ -253988,7 +254490,7 @@ static void fts5IndexExtractColset(
253988
254490
  /* Advance pointer p until it points to pEnd or an 0x01 byte that is
253989
254491
  ** not part of a varint */
253990
254492
  while( p<pEnd && *p!=0x01 ){
253991
- while( *p++ & 0x80 );
254493
+ while( p<pEnd && (*p++ & 0x80) );
253992
254494
  }
253993
254495
 
253994
254496
  if( pColset->aiCol[i]==iCurrent ){
@@ -254085,8 +254587,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
254085
254587
 
254086
254588
  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
254087
254589
  assert( pIter->pColset );
254590
+ assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
254088
254591
 
254089
- if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
254592
+ if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
254593
+ || pSeg->nPos>pIter->pIndex->pConfig->nCol
254594
+ ){
254090
254595
  fts5IterSetOutputs_Col(pIter, pSeg);
254091
254596
  }else{
254092
254597
  u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
@@ -255580,6 +256085,11 @@ static void fts5DoSecureDelete(
255580
256085
  }else{
255581
256086
  iStart = fts5GetU16(&aPg[0]);
255582
256087
  }
256088
+ if( iStart>nPg ){
256089
+ FTS5_CORRUPT_IDX(p);
256090
+ sqlite3_free(aIdx);
256091
+ return;
256092
+ }
255583
256093
 
255584
256094
  iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
255585
256095
  assert_nc( iSOP<=pSeg->iLeafOffset );
@@ -263456,7 +263966,7 @@ static void fts5SourceIdFunc(
263456
263966
  ){
263457
263967
  assert( nArg==0 );
263458
263968
  UNUSED_PARAM2(nArg, apUnused);
263459
- sqlite3_result_text(pCtx, "fts5: 2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9", -1, SQLITE_TRANSIENT);
263969
+ sqlite3_result_text(pCtx, "fts5: 2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24", -1, SQLITE_TRANSIENT);
263460
263970
  }
263461
263971
 
263462
263972
  /*
@@ -265850,8 +266360,14 @@ static int fts5PorterCreate(
265850
266360
  const char *zBase = "unicode61";
265851
266361
  fts5_tokenizer_v2 *pV2 = 0;
265852
266362
 
265853
- if( nArg>0 ){
265854
- zBase = azArg[0];
266363
+ while( nArg>0 ){
266364
+ if( sqlite3_stricmp(azArg[0],"porter")==0 ){
266365
+ nArg--;
266366
+ azArg++;
266367
+ }else{
266368
+ zBase = azArg[0];
266369
+ break;
266370
+ }
265855
266371
  }
265856
266372
 
265857
266373
  pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
@@ -269307,9 +269823,9 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
269307
269823
 
269308
269824
  #define SQLITE3MC_VERSION_MAJOR 2
269309
269825
  #define SQLITE3MC_VERSION_MINOR 3
269310
- #define SQLITE3MC_VERSION_RELEASE 4
269826
+ #define SQLITE3MC_VERSION_RELEASE 5
269311
269827
  #define SQLITE3MC_VERSION_SUBRELEASE 0
269312
- #define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 2.3.4"
269828
+ #define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 2.3.5"
269313
269829
 
269314
269830
  #endif /* SQLITE3MC_VERSION_H_ */
269315
269831
  /*** End of #include "sqlite3mc_version.h" ***/
@@ -269468,12 +269984,12 @@ extern "C" {
269468
269984
  ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
269469
269985
  ** [sqlite_version()] and [sqlite_source_id()].
269470
269986
  */
269471
- #define SQLITE_VERSION "3.53.1"
269472
- #define SQLITE_VERSION_NUMBER 3053001
269473
- #define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9"
269987
+ #define SQLITE_VERSION "3.53.2"
269988
+ #define SQLITE_VERSION_NUMBER 3053002
269989
+ #define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
269474
269990
  #define SQLITE_SCM_BRANCH "branch-3.53"
269475
- #define SQLITE_SCM_TAGS "release version-3.53.1"
269476
- #define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z"
269991
+ #define SQLITE_SCM_TAGS "release version-3.53.2"
269992
+ #define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
269477
269993
 
269478
269994
  /*
269479
269995
  ** CAPI3REF: Run-Time Library Version Numbers
@@ -282175,11 +282691,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
282175
282691
  ** database behave as if they were declared with "ON UPDATE NO ACTION ON
282176
282692
  ** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
282177
282693
  ** or SET DEFAULT.
282694
+ **
282695
+ ** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
282696
+ ** Sometimes, a changeset contains two or more update statements such that
282697
+ ** although after applying all updates the database will contain no
282698
+ ** constraint violations, no single update can be applied before the others.
282699
+ ** The simplest example of this is a pair of UPDATEs that have "swapped"
282700
+ ** two column values with a UNIQUE constraint.
282701
+ ** <p>
282702
+ ** Usually, sqlite3changeset_apply() and similar functions work hard to try
282703
+ ** to find a way to apply such a changeset. However, if this flag is set,
282704
+ ** then all such updates are considered CONSTRAINT conflicts.
282178
282705
  */
282179
282706
  #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
282180
282707
  #define SQLITE_CHANGESETAPPLY_INVERT 0x0002
282181
282708
  #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
282182
282709
  #define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
282710
+ #define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
282183
282711
 
282184
282712
  /*
282185
282713
  ** CAPI3REF: Constants Passed To The Conflict Handler
@@ -338118,7 +338646,7 @@ sqlite3mcBtreeSetPageSize(Btree* p, int pageSize, int nReserve, int iFix)
338118
338646
  ** Change 4: Call sqlite3mcBtreeSetPageSize instead of sqlite3BtreeSetPageSize for main database
338119
338647
  ** (sqlite3mcBtreeSetPageSize allows to reduce the number of reserved bytes)
338120
338648
  **
338121
- ** This code is generated by the script rekeyvacuum.sh from SQLite version 3.53.1 amalgamation.
338649
+ ** This code is generated by the script rekeyvacuum.sh from SQLite version 3.53.2 amalgamation.
338122
338650
  */
338123
338651
  SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey(
338124
338652
  char **pzErrMsg, /* Write error message here */
@@ -347868,7 +348396,7 @@ static int seriesFilter(
347868
348396
  if( r<(double)SMALLEST_INT64 ){
347869
348397
  iMin = SMALLEST_INT64;
347870
348398
  }else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
347871
- iMin = (sqlite3_int64)seriesCeil(r+1.0);
348399
+ iMin = (sqlite3_int64)seriesCeil(r)+1;
347872
348400
  }else{
347873
348401
  iMin = (sqlite3_int64)seriesCeil(r);
347874
348402
  }
@@ -347889,7 +348417,7 @@ static int seriesFilter(
347889
348417
  if( r>(double)LARGEST_INT64 ){
347890
348418
  iMax = LARGEST_INT64;
347891
348419
  }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
347892
- iMax = (sqlite3_int64)(r-1.0);
348420
+ iMax = ((sqlite3_int64)r)-1;
347893
348421
  }else{
347894
348422
  iMax = (sqlite3_int64)seriesFloor(r);
347895
348423
  }
@@ -358655,6 +359183,10 @@ static void compressFunc(
358655
359183
  nIn = sqlite3_value_bytes(argv[0]);
358656
359184
  nOut = 13 + nIn + (nIn+999)/1000;
358657
359185
  pOut = sqlite3_malloc64( nOut+5 );
359186
+ if( pOut==0 ){
359187
+ sqlite3_result_error_nomem(context);
359188
+ return;
359189
+ }
358658
359190
  for(i=4; i>=0; i--){
358659
359191
  x[i] = (nIn >> (7*(4-i)))&0x7f;
358660
359192
  }
@@ -358694,6 +359226,10 @@ static void uncompressFunc(
358694
359226
  if( (pIn[i]&0x80)!=0 ){ i++; break; }
358695
359227
  }
358696
359228
  pOut = sqlite3_malloc64( nOut+1 );
359229
+ if( pOut==0 ){
359230
+ sqlite3_result_error_nomem(context);
359231
+ return;
359232
+ }
358697
359233
  rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
358698
359234
  if( rc==Z_OK ){
358699
359235
  sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
@@ -359369,6 +359905,7 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){
359369
359905
  pNext = p->pNext;
359370
359906
  zipfileEntryFree(p);
359371
359907
  }
359908
+ pCsr->pFreeEntry = 0;
359372
359909
  }
359373
359910
 
359374
359911
  /*
@@ -359771,7 +360308,13 @@ static int zipfileGetEntry(
359771
360308
 
359772
360309
  if( rc==SQLITE_OK ){
359773
360310
  u32 *pt = &pNew->mUnixTime;
359774
- pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
360311
+ /* aRead[0..nFile-1] might contain embedded \000 characters
360312
+ ** See Bug 2026-05-31T11:43:05Z */
360313
+ pNew->cds.zFile = sqlite3_malloc64(nFile+1);
360314
+ if( pNew->cds.zFile!=0 ){
360315
+ memcpy(pNew->cds.zFile, aRead, nFile);
360316
+ pNew->cds.zFile[nFile] = 0;
360317
+ }
359775
360318
  pNew->aExtra = (u8*)&pNew[1];
359776
360319
  memcpy(pNew->aExtra, &aRead[nFile], nExtra);
359777
360320
  if( pNew->cds.zFile==0 ){
@@ -360875,10 +361418,10 @@ struct ZipfileCtx {
360875
361418
  };
360876
361419
 
360877
361420
  static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
360878
- if( pBuf->n+nByte>pBuf->nAlloc ){
361421
+ if( (pBuf->nAlloc-pBuf->n)<nByte ){
360879
361422
  u8 *aNew;
360880
- sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
360881
- int nReq = pBuf->n + nByte;
361423
+ i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
361424
+ i64 nReq = pBuf->n + nByte;
360882
361425
 
360883
361426
  while( nNew<nReq ) nNew = nNew*2;
360884
361427
  aNew = sqlite3_realloc64(pBuf->a, nNew);
@@ -363297,6 +363840,15 @@ sqlite3mc_shutdown(void)
363297
363840
  /* Forward declaration */
363298
363841
  typedef struct SqliteDb SqliteDb;
363299
363842
 
363843
+ /* Add -DSQLITE_ENABLE_QRF_IN_TCL to add the Query Result Formatter (QRF)
363844
+ ** into the build of the TCL extension, when building using separate
363845
+ ** source files. The QRF is included automatically when building from
363846
+ ** the tclsqlite3.c amalgamation.
363847
+ */
363848
+ #if defined(SQLITE_ENABLE_QRF_IN_TCL)
363849
+ #include "qrf.h"
363850
+ #endif
363851
+
363300
363852
  /*
363301
363853
  ** New SQL functions can be created as TCL scripts. Each such function
363302
363854
  ** is described by an instance of the following structure.
@@ -365208,6 +365760,376 @@ static void DbHookCmd(
365208
365760
  sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb);
365209
365761
  }
365210
365762
 
365763
+ /*
365764
+ ** Implementation of the "db format" command.
365765
+ **
365766
+ ** Based on provided options, format the results of the SQL statement(s)
365767
+ ** provided into human-readable form using the Query Result Formatter (QRF)
365768
+ ** and return the resuling text.
365769
+ **
365770
+ ** Syntax: db format OPTIONS SQL
365771
+ **
365772
+ ** OPTIONS may be:
365773
+ **
365774
+ ** -style ("auto"|"box"|"column"|...) Output style
365775
+ ** -esc ("auto"|"off"|"ascii"|"symbol") How to deal with ctrl chars
365776
+ ** -text ("auto"|"off"|"sql"|"csv"|...) How to escape TEXT values
365777
+ ** -title ("auto"|"off"|"sql"|...|"off") How to escape column names
365778
+ ** -blob ("auto"|"text"|"sql"|...) How to escape BLOB values
365779
+ ** -wordwrap ("auto"|"off"|"on") Try to wrap at word boundry?
365780
+ ** -textjsonb ("auto"|"off"|"on") Auto-convert JSONB to text?
365781
+ ** -splitcolumn ("auto"|"off"|"on") Enable split-column mode
365782
+ ** -defaultalign ("auto"|"left"|...) Default alignment
365783
+ ** -titalalign ("auto"|"left"|"right"|...) Default column name alignment
365784
+ ** -border ("auto"|"off"|"on") Border for box and table styles
365785
+ ** -wrap NUMBER Max width of any single column
365786
+ ** -screenwidth NUMBER Width of the display TTY
365787
+ ** -linelimit NUMBER Max lines for any cell
365788
+ ** -charlimit NUMBER Content truncated to this size
365789
+ ** -titlelimit NUMBER Max width of column titles
365790
+ ** -multiinsert NUMBER Multi-row INSERT byte size
365791
+ ** -align LIST-OF-ALIGNMENT Alignment of columns
365792
+ ** -widths LIST-OF-NUMBERS Widths for individual columns
365793
+ ** -columnsep TEXT Column separator text
365794
+ ** -rowsep TEXT Row separator text
365795
+ ** -tablename TEXT Table name for style "insert"
365796
+ ** -null TEXT Text for NULL values
365797
+ **
365798
+ ** A mapping from TCL "format" command options to sqlite3_qrf_spec fields
365799
+ ** is below. Use this to reference the QRF documentation:
365800
+ **
365801
+ ** TCL Option spec field
365802
+ ** ---------- ----------
365803
+ ** -style eStyle
365804
+ ** -esc eEsc
365805
+ ** -text eText
365806
+ ** -title eTitle, bTitle
365807
+ ** -blob eBlob
365808
+ ** -wordwrap bWordWrap
365809
+ ** -textjsonb bTextJsonb
365810
+ ** -splitcolumn bSplitColumn
365811
+ ** -defaultalign eDfltAlign
365812
+ ** -titlealign eTitleAlign
365813
+ ** -border bBorder
365814
+ ** -wrap nWrap
365815
+ ** -screenwidth nScreenWidth
365816
+ ** -linelimit nLineLimit
365817
+ ** -charlimit nCharLimit
365818
+ ** -titlelimit nTitleLimit
365819
+ ** -multiinsert nMultiInsert
365820
+ ** -align nAlign, aAlign
365821
+ ** -widths nWidth, aWidth
365822
+ ** -columnsep zColumnSep
365823
+ ** -rowsep zRowSep
365824
+ ** -tablename zTableName
365825
+ ** -null zNull
365826
+ */
365827
+ static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
365828
+ #ifndef SQLITE_QRF_H
365829
+ Tcl_SetResult(pDb->interp, "QRF not available in this build", TCL_VOLATILE);
365830
+ return TCL_ERROR;
365831
+ #else
365832
+ char *zResult = 0; /* Result to be returned */
365833
+ const char *zSql = 0; /* SQL to run */
365834
+ int i; /* Loop counter */
365835
+ int rc; /* Result code */
365836
+ sqlite3_qrf_spec qrf; /* Formatting spec */
365837
+ static const char *azAlign[] = {
365838
+ "auto", "bottom", "c",
365839
+ "center", "e", "left",
365840
+ "middle", "n", "ne",
365841
+ "nw", "right", "s",
365842
+ "se", "sw", "top",
365843
+ "w", 0
365844
+ };
365845
+ static const unsigned char aAlignMap[] = {
365846
+ QRF_ALIGN_Auto, QRF_ALIGN_Bottom, QRF_ALIGN_C,
365847
+ QRF_ALIGN_Center, QRF_ALIGN_E, QRF_ALIGN_Left,
365848
+ QRF_ALIGN_Middle, QRF_ALIGN_N, QRF_ALIGN_NE,
365849
+ QRF_ALIGN_NW, QRF_ALIGN_Right, QRF_ALIGN_S,
365850
+ QRF_ALIGN_SE, QRF_ALIGN_SW, QRF_ALIGN_Top,
365851
+ QRF_ALIGN_W
365852
+ };
365853
+
365854
+ memset(&qrf, 0, sizeof(qrf));
365855
+ qrf.iVersion = 1;
365856
+ qrf.pzOutput = &zResult;
365857
+ for(i=2; i<objc; i++){
365858
+ const char *zArg = Tcl_GetString(objv[i]);
365859
+ const char *azBool[] = { "auto", "yes", "no", "on", "off", 0 };
365860
+ const unsigned char aBoolMap[] = { 0, 2, 1, 2, 1 };
365861
+ if( zArg[0]!='-' ){
365862
+ if( zSql ){
365863
+ Tcl_AppendResult(pDb->interp, "unknown argument: ", zArg, (char*)0);
365864
+ rc = TCL_ERROR;
365865
+ goto format_failed;
365866
+ }
365867
+ zSql = zArg;
365868
+ }else if( i==objc-1 ){
365869
+ Tcl_AppendResult(pDb->interp, "option has no argument: ", zArg, (char*)0);
365870
+ rc = TCL_ERROR;
365871
+ goto format_failed;
365872
+ }else if( strcmp(zArg,"-style")==0 ){
365873
+ static const char *azStyles[] = {
365874
+ "auto", "box", "column",
365875
+ "count", "csv", "eqp",
365876
+ "explain", "html", "insert",
365877
+ "jobject", "json", "line",
365878
+ "list", "markdown", "quote",
365879
+ "stats", "stats-est", "stats-vm",
365880
+ "table", 0
365881
+ };
365882
+ static unsigned char aStyleMap[] = {
365883
+ QRF_STYLE_Auto, QRF_STYLE_Box, QRF_STYLE_Column,
365884
+ QRF_STYLE_Count, QRF_STYLE_Csv, QRF_STYLE_Eqp,
365885
+ QRF_STYLE_Explain, QRF_STYLE_Html, QRF_STYLE_Insert,
365886
+ QRF_STYLE_JObject, QRF_STYLE_Json, QRF_STYLE_Line,
365887
+ QRF_STYLE_List, QRF_STYLE_Markdown, QRF_STYLE_Quote,
365888
+ QRF_STYLE_Stats, QRF_STYLE_StatsEst, QRF_STYLE_StatsVm,
365889
+ QRF_STYLE_Table
365890
+ };
365891
+ int style;
365892
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azStyles,
365893
+ "format style (-style)", 0, &style);
365894
+ if( rc ) goto format_failed;
365895
+ qrf.eStyle = aStyleMap[style];
365896
+ i++;
365897
+ }else if( strcmp(zArg,"-esc")==0 ){
365898
+ static const char *azEsc[] = {
365899
+ "ascii", "auto", "off", "symbol", 0
365900
+ };
365901
+ static unsigned char aEscMap[] = {
365902
+ QRF_ESC_Ascii, QRF_ESC_Auto, QRF_ESC_Off, QRF_ESC_Symbol
365903
+ };
365904
+ int esc;
365905
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azEsc,
365906
+ "control character escape (-esc)", 0, &esc);
365907
+ if( rc ) goto format_failed;
365908
+ qrf.eEsc = aEscMap[esc];
365909
+ i++;
365910
+ }else if( strcmp(zArg,"-text")==0 || strcmp(zArg, "-title")==0 ){
365911
+ /* NB: --title can be "off" or "on but --text may not be. Thus we put
365912
+ ** the "off" and "on" choices first and start the search on the
365913
+ ** thrid element of the array when processing --text */
365914
+ static const char *azText[] = { "off", "on",
365915
+ "auto", "csv", "html",
365916
+ "json", "plain", "relaxed",
365917
+ "sql", "tcl", 0
365918
+ };
365919
+ static unsigned char aTextMap[] = {
365920
+ QRF_TEXT_Auto, QRF_TEXT_Csv, QRF_TEXT_Html,
365921
+ QRF_TEXT_Json, QRF_TEXT_Plain, QRF_TEXT_Relaxed,
365922
+ QRF_TEXT_Sql, QRF_TEXT_Tcl
365923
+ };
365924
+ int txt;
365925
+ int k = zArg[2]=='e';
365926
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], &azText[k*2], zArg,
365927
+ 0, &txt);
365928
+ if( rc ) goto format_failed;
365929
+ if( k ){
365930
+ qrf.eText = aTextMap[txt];
365931
+ }else if( txt<=1 ){
365932
+ qrf.bTitles = txt ? QRF_Yes : QRF_No;
365933
+ qrf.eTitle = QRF_TEXT_Auto;
365934
+ }else{
365935
+ qrf.bTitles = QRF_Yes;
365936
+ qrf.eTitle = aTextMap[txt-2];
365937
+ }
365938
+ i++;
365939
+ }else if( strcmp(zArg,"-blob")==0 ){
365940
+ static const char *azBlob[] = {
365941
+ "auto", "hex", "json",
365942
+ "tcl", "text", "sql",
365943
+ "size", 0
365944
+ };
365945
+ static unsigned char aBlobMap[] = {
365946
+ QRF_BLOB_Auto, QRF_BLOB_Hex, QRF_BLOB_Json,
365947
+ QRF_BLOB_Tcl, QRF_BLOB_Text, QRF_BLOB_Sql,
365948
+ QRF_BLOB_Size
365949
+ };
365950
+ int blob;
365951
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBlob,
365952
+ "BLOB encoding (-blob)", 0, &blob);
365953
+ if( rc ) goto format_failed;
365954
+ qrf.eBlob = aBlobMap[blob];
365955
+ i++;
365956
+ }else if( strcmp(zArg,"-wordwrap")==0 ){
365957
+ int v = 0;
365958
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
365959
+ "-wordwrap", 0, &v);
365960
+ if( rc ) goto format_failed;
365961
+ qrf.bWordWrap = aBoolMap[v];
365962
+ i++;
365963
+ }else if( strcmp(zArg,"-textjsonb")==0
365964
+ || strcmp(zArg,"-splitcolumn")==0
365965
+ || strcmp(zArg,"-border")==0
365966
+ ){
365967
+ int v = 0;
365968
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
365969
+ zArg, 0, &v);
365970
+ if( rc ) goto format_failed;
365971
+ if( zArg[1]=='t' ){
365972
+ qrf.bTextJsonb = aBoolMap[v];
365973
+ }else if( zArg[1]=='b' ){
365974
+ qrf.bBorder = aBoolMap[v];
365975
+ }else{
365976
+ qrf.bSplitColumn = aBoolMap[v];
365977
+ }
365978
+ i++;
365979
+ }else if( strcmp(zArg,"-defaultalign")==0 || strcmp(zArg,"-titlealign")==0){
365980
+ int ax = 0;
365981
+ rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azAlign,
365982
+ zArg[1]=='d' ? "default alignment (-defaultalign)" :
365983
+ "title alignment (-titlealign)",
365984
+ 0, &ax);
365985
+ if( rc ) goto format_failed;
365986
+ if( zArg[1]=='d' ){
365987
+ qrf.eDfltAlign = aAlignMap[ax];
365988
+ }else{
365989
+ qrf.eTitleAlign = aAlignMap[ax];
365990
+ }
365991
+ i++;
365992
+ }else if( strcmp(zArg,"-wrap")==0
365993
+ || strcmp(zArg,"-screenwidth")==0
365994
+ || strcmp(zArg,"-linelimit")==0
365995
+ || strcmp(zArg,"-titlelimit")==0
365996
+ ){
365997
+ int v = 0;
365998
+ rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
365999
+ if( rc ) goto format_failed;
366000
+ if( v<QRF_MIN_WIDTH ){
366001
+ v = QRF_MIN_WIDTH;
366002
+ }else if( v>QRF_MAX_WIDTH ){
366003
+ v = QRF_MAX_WIDTH;
366004
+ }
366005
+ if( zArg[1]=='w' ){
366006
+ qrf.nWrap = v;
366007
+ }else if( zArg[1]=='s' ){
366008
+ qrf.nScreenWidth = v;
366009
+ }else if( zArg[1]=='t' ){
366010
+ qrf.nTitleLimit = v;
366011
+ }else{
366012
+ qrf.nLineLimit = v;
366013
+ }
366014
+ i++;
366015
+ }else if( strcmp(zArg,"-charlimit")==0 ){
366016
+ int v = 0;
366017
+ rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
366018
+ if( rc ) goto format_failed;
366019
+ if( v<0 ) v = 0;
366020
+ qrf.nCharLimit = v;
366021
+ i++;
366022
+ }else if( strcmp(zArg,"-multiinsert")==0 ){
366023
+ int v = 0;
366024
+ rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
366025
+ if( rc ) goto format_failed;
366026
+ if( v<0 ) v = 0;
366027
+ qrf.nMultiInsert = v;
366028
+ i++;
366029
+ }else if( strcmp(zArg,"-align")==0 ){
366030
+ Tcl_Size n = 0;
366031
+ int jj;
366032
+ rc = Tcl_ListObjLength(pDb->interp, objv[i+1], &n);
366033
+ if( rc ) goto format_failed;
366034
+ sqlite3_free(qrf.aAlign);
366035
+ qrf.aAlign = sqlite3_malloc64( (n+1)*sizeof(qrf.aAlign[0]) );
366036
+ if( qrf.aAlign==0 ){
366037
+ Tcl_AppendResult(pDb->interp, "out of memory", (char*)0);
366038
+ rc = TCL_ERROR;
366039
+ goto format_failed;
366040
+ }
366041
+ memset(qrf.aAlign, 0, (n+1)*sizeof(qrf.aAlign[0]));
366042
+ qrf.nAlign = n;
366043
+ for(jj=0; jj<n; jj++){
366044
+ int x;
366045
+ Tcl_Obj *pTerm;
366046
+ rc = Tcl_ListObjIndex(pDb->interp, objv[i+1], jj, &pTerm);
366047
+ if( rc ) goto format_failed;
366048
+ rc = Tcl_GetIndexFromObj(pDb->interp, pTerm, azAlign,
366049
+ "column alignment (-align)", 0, &x);
366050
+ if( rc ) goto format_failed;
366051
+ qrf.aAlign[jj] = aAlignMap[x];
366052
+ }
366053
+ i++;
366054
+ }else if( strcmp(zArg,"-widths")==0 ){
366055
+ Tcl_Size n = 0;
366056
+ int jj;
366057
+ rc = Tcl_ListObjLength(pDb->interp, objv[i+1], &n);
366058
+ if( rc ) goto format_failed;
366059
+ sqlite3_free(qrf.aWidth);
366060
+ qrf.aWidth = sqlite3_malloc64( (n+1)*sizeof(qrf.aWidth[0]) );
366061
+ if( qrf.aWidth==0 ){
366062
+ Tcl_AppendResult(pDb->interp, "out of memory", (char*)0);
366063
+ rc = TCL_ERROR;
366064
+ goto format_failed;
366065
+ }
366066
+ memset(qrf.aWidth, 0, (n+1)*sizeof(qrf.aWidth[0]));
366067
+ qrf.nWidth = n;
366068
+ for(jj=0; jj<n; jj++){
366069
+ Tcl_Obj *pTerm;
366070
+ int v;
366071
+ rc = Tcl_ListObjIndex(pDb->interp, objv[i+1], jj, &pTerm);
366072
+ if( rc ) goto format_failed;
366073
+ rc = Tcl_GetIntFromObj(pDb->interp, pTerm, &v);
366074
+ if( v<(-QRF_MAX_WIDTH) ){
366075
+ v = -QRF_MAX_WIDTH;
366076
+ }else if( v>QRF_MAX_WIDTH ){
366077
+ v = QRF_MAX_WIDTH;
366078
+ }
366079
+ qrf.aWidth[jj] = (short int)v;
366080
+ }
366081
+ i++;
366082
+ }else if( strcmp(zArg,"-columnsep")==0 ){
366083
+ qrf.zColumnSep = Tcl_GetString(objv[i+1]);
366084
+ i++;
366085
+ }else if( strcmp(zArg,"-rowsep")==0 ){
366086
+ qrf.zRowSep = Tcl_GetString(objv[i+1]);
366087
+ i++;
366088
+ }else if( strcmp(zArg,"-tablename")==0 ){
366089
+ qrf.zTableName = Tcl_GetString(objv[i+1]);
366090
+ i++;
366091
+ }else if( strcmp(zArg,"-null")==0 ){
366092
+ qrf.zNull = Tcl_GetString(objv[i+1]);
366093
+ i++;
366094
+ }else if( strcmp(zArg,"-version")==0 ){
366095
+ /* Undocumented. Testing use only */
366096
+ qrf.iVersion = atoi(Tcl_GetString(objv[i+1]));
366097
+ i++;
366098
+ }else{
366099
+ Tcl_AppendResult(pDb->interp, "unknown option: ", zArg, (char*)0);
366100
+ rc = TCL_ERROR;
366101
+ goto format_failed;
366102
+ }
366103
+ }
366104
+ while( zSql && zSql[0] ){
366105
+ SqlPreparedStmt *pStmt = 0; /* Next statement to run */
366106
+ char *zErr = 0; /* Error message from QRF */
366107
+
366108
+ rc = dbPrepareAndBind(pDb, zSql, &zSql, &pStmt);
366109
+ if( rc ) goto format_failed;
366110
+ if( pStmt==0 ) continue;
366111
+ rc = sqlite3_format_query_result(pStmt->pStmt, &qrf, &zErr);
366112
+ dbReleaseStmt(pDb, pStmt, 0);
366113
+ if( rc ){
366114
+ Tcl_SetResult(pDb->interp, zErr, TCL_VOLATILE);
366115
+ sqlite3_free(zErr);
366116
+ rc = TCL_ERROR;
366117
+ goto format_failed;
366118
+ }
366119
+ }
366120
+ Tcl_SetResult(pDb->interp, zResult, TCL_VOLATILE);
366121
+ rc = TCL_OK;
366122
+ /* Fall through...*/
366123
+
366124
+ format_failed:
366125
+ sqlite3_free(qrf.aWidth);
366126
+ sqlite3_free(qrf.aAlign);
366127
+ sqlite3_free(zResult);
366128
+ return rc;
366129
+
366130
+ #endif
366131
+ }
366132
+
365211
366133
  /*
365212
366134
  ** The "sqlite" command below creates a new Tcl command for each
365213
366135
  ** connection it opens to an SQLite database. This routine is invoked
@@ -365237,15 +366159,15 @@ static int SQLITE_TCLAPI DbObjCmd(
365237
366159
  "commit_hook", "complete", "config",
365238
366160
  "copy", "deserialize", "enable_load_extension",
365239
366161
  "errorcode", "erroroffset", "eval",
365240
- "exists", "function", "incrblob",
365241
- "interrupt", "last_insert_rowid", "nullvalue",
365242
- "onecolumn", "preupdate", "profile",
365243
- "progress", "rekey", "restore",
365244
- "rollback_hook", "serialize", "status",
365245
- "timeout", "total_changes", "trace",
365246
- "trace_v2", "transaction", "unlock_notify",
365247
- "update_hook", "version", "wal_hook",
365248
- 0
366162
+ "exists", "format", "function",
366163
+ "incrblob", "interrupt", "last_insert_rowid",
366164
+ "nullvalue", "onecolumn", "preupdate",
366165
+ "profile", "progress", "rekey",
366166
+ "restore", "rollback_hook", "serialize",
366167
+ "status", "timeout", "total_changes",
366168
+ "trace", "trace_v2", "transaction",
366169
+ "unlock_notify", "update_hook", "version",
366170
+ "wal_hook", 0
365249
366171
  };
365250
366172
  enum DB_enum {
365251
366173
  DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
@@ -365254,14 +366176,15 @@ static int SQLITE_TCLAPI DbObjCmd(
365254
366176
  DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
365255
366177
  DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
365256
366178
  DB_ERRORCODE, DB_ERROROFFSET, DB_EVAL,
365257
- DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
365258
- DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
365259
- DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
365260
- DB_PROGRESS, DB_REKEY, DB_RESTORE,
365261
- DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
365262
- DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
365263
- DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
365264
- DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK,
366179
+ DB_EXISTS, DB_FORMAT, DB_FUNCTION,
366180
+ DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID,
366181
+ DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE,
366182
+ DB_PROFILE, DB_PROGRESS, DB_REKEY,
366183
+ DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE,
366184
+ DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
366185
+ DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
366186
+ DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
366187
+ DB_WAL_HOOK
365265
366188
  };
365266
366189
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
365267
366190
 
@@ -366151,6 +367074,18 @@ deserialize_error:
366151
367074
  break;
366152
367075
  }
366153
367076
 
367077
+ /*
367078
+ ** $db format [OPTIONS] SQL
367079
+ **
367080
+ ** Run the SQL statement(s) given as the final argument. Use the
367081
+ ** Query Result Formatter extension of SQLite to format the output as
367082
+ ** text and return that text.
367083
+ */
367084
+ case DB_FORMAT: {
367085
+ rc = dbQrf(pDb, objc, objv);
367086
+ break;
367087
+ }
367088
+
366154
367089
  /*
366155
367090
  ** $db function NAME [OPTIONS] SCRIPT
366156
367091
  **