Wapp

Check-in [7225deab5d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update the built-in SQLite implementation to version 3.48.0.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7225deab5dd558d0f3b41afa8cdb31cd61aaa56383c7bd89059eb93b85e62c21
User & Date: drh 2025-01-14 15:27:10.163
Context
2025-02-03
16:57
Update the built-in SQLite to the latest 3.49.0 beta. (check-in: 27f64e15e6 user: drh tags: trunk)
2025-01-14
15:27
Update the built-in SQLite implementation to version 3.48.0. (check-in: 7225deab5d user: drh tags: trunk)
15:26
Fix typos in the header comment of wapptclsh.c.in. (check-in: 7ee6ff55d1 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to tclsqlite3.c.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
** the text of this file.  Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** 2b17bc49655c577029919c2d409de994b0d2 with changes in files:
**
**    
*/
#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
** the text of this file.  Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** d2fe6b05f38d9d7cd78c5d252e99ac59f1ae with changes in files:
**
**    
*/
#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.48.0"
#define SQLITE_VERSION_NUMBER 3048000
#define SQLITE_SOURCE_ID      "2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|







464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.48.0"
#define SQLITE_VERSION_NUMBER 3048000
#define SQLITE_SOURCE_ID      "2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
33051
33052
33053
33054
33055
33056
33057

33058


33059
33060
33061
33062
33063
33064
33065
    if( pItem->fg.jointype & JT_LTORJ ){
      sqlite3_str_appendf(&x, " LTORJ");
    }
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.isCte ){

      sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);


    }
    if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
      sqlite3_str_appendf(&x, " isOn");
    }
    if( pItem->fg.isTabFunc )      sqlite3_str_appendf(&x, " isTabFunc");
    if( pItem->fg.isCorrelated )   sqlite3_str_appendf(&x, " isCorrelated");
    if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");







>
|
>
>







33051
33052
33053
33054
33055
33056
33057
33058
33059
33060
33061
33062
33063
33064
33065
33066
33067
33068
    if( pItem->fg.jointype & JT_LTORJ ){
      sqlite3_str_appendf(&x, " LTORJ");
    }
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.isCte ){
      static const char *aMat[] = {",MAT", "", ",NO-MAT"};
      sqlite3_str_appendf(&x, " CteUse=%d%s",
                          pItem->u2.pCteUse->nUse,
                          aMat[pItem->u2.pCteUse->eM10d]);
    }
    if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
      sqlite3_str_appendf(&x, " isOn");
    }
    if( pItem->fg.isTabFunc )      sqlite3_str_appendf(&x, " isTabFunc");
    if( pItem->fg.isCorrelated )   sqlite3_str_appendf(&x, " isCorrelated");
    if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
33082
33083
33084
33085
33086
33087
33088
33089
33090
33091
33092
33093
33094
33095
33096
33097
33098
    if( pItem->fg.isSubquery ){
      assert( n==1 );
      if( pItem->pSTab ){
        Table *pTab = pItem->pSTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }
      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
      sqlite3TreeViewPush(&pView, 0);
      sqlite3TreeViewLine(pView, "SUBQUERY");
      sqlite3TreeViewPop(&pView);
      sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
    }
    if( pItem->fg.isTabFunc ){
      sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
    }
    sqlite3TreeViewPop(&pView);
  }







<
<
<







33085
33086
33087
33088
33089
33090
33091



33092
33093
33094
33095
33096
33097
33098
    if( pItem->fg.isSubquery ){
      assert( n==1 );
      if( pItem->pSTab ){
        Table *pTab = pItem->pSTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }
      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );



      sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
    }
    if( pItem->fg.isTabFunc ){
      sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
    }
    sqlite3TreeViewPop(&pView);
  }
112712
112713
112714
112715
112716
112717
112718

112719
112720
112721
112722
112723
112724
112725
            if( j==nExpr ) break;
            mCol = MASKBIT(j);
            if( mCol & colUsed ) break; /* Each column used only once */
            colUsed |= mCol;
            if( aiMap ) aiMap[i] = j;
          }


          assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
          if( colUsed==(MASKBIT(nExpr)-1) ){
            /* If we reach this point, that means the index pIdx is usable */
            int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
            ExplainQueryPlan((pParse, 0,
                              "USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
            sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);







>







112712
112713
112714
112715
112716
112717
112718
112719
112720
112721
112722
112723
112724
112725
112726
            if( j==nExpr ) break;
            mCol = MASKBIT(j);
            if( mCol & colUsed ) break; /* Each column used only once */
            colUsed |= mCol;
            if( aiMap ) aiMap[i] = j;
          }

          assert( nExpr>0 && nExpr<BMS );
          assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
          if( colUsed==(MASKBIT(nExpr)-1) ){
            /* If we reach this point, that means the index pIdx is usable */
            int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
            ExplainQueryPlan((pParse, 0,
                              "USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
            sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
164141
164142
164143
164144
164145
164146
164147





164148
164149
164150
164151
164152
164153
164154
**   1.   If iCol is already the left-most column of some other index,
**        then return false.
**
**   2.   If iCol is part of an existing index that has an aiRowLogEst of
**        more than 20, then return false.
**
**   3.   If no disqualifying conditions above are found, return true.





*/
static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
  const Table *pTab,
  int iCol
){
  const Index *pIdx;
  for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){







>
>
>
>
>







164142
164143
164144
164145
164146
164147
164148
164149
164150
164151
164152
164153
164154
164155
164156
164157
164158
164159
164160
**   1.   If iCol is already the left-most column of some other index,
**        then return false.
**
**   2.   If iCol is part of an existing index that has an aiRowLogEst of
**        more than 20, then return false.
**
**   3.   If no disqualifying conditions above are found, return true.
**
** 2025-01-03: I experimented with a new rule that returns false if the
** the datatype of the column is "BOOLEAN". This did not improve
** performance on any queries at hand, but it did burn CPU cycles, so the
** idea was not committed.
*/
static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
  const Table *pTab,
  int iCol
){
  const Index *pIdx;
  for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
226242
226243
226244
226245
226246
226247
226248


















226249
226250
226251
226252
226253
226254
226255
}

static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  *pRowid = pCsr->pgno;
  return SQLITE_OK;
}



















static int dbpageUpdate(
  sqlite3_vtab *pVtab,
  int argc,
  sqlite3_value **argv,
  sqlite_int64 *pRowid
){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







226248
226249
226250
226251
226252
226253
226254
226255
226256
226257
226258
226259
226260
226261
226262
226263
226264
226265
226266
226267
226268
226269
226270
226271
226272
226273
226274
226275
226276
226277
226278
226279
}

static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  *pRowid = pCsr->pgno;
  return SQLITE_OK;
}

/*
** Open write transactions. Since we do not know in advance which database
** files will be written by the sqlite_dbpage virtual table, start a write
** transaction on them all.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
static int dbpageBeginTrans(DbpageTable *pTab){
  sqlite3 *db = pTab->db;
  int rc = SQLITE_OK;
  int i;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
  return rc;
}

static int dbpageUpdate(
  sqlite3_vtab *pVtab,
  int argc,
  sqlite3_value **argv,
  sqlite_int64 *pRowid
){
226310
226311
226312
226313
226314
226315
226316






226317
226318
226319
226320
226321
226322
226323
      pgno--;
      pTab->pgnoTrunc = pgno;
    }else{
      zErr = "bad page value";
      goto update_fail;
    }
  }






  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);
    if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
      unsigned char *aPage = sqlite3PagerGetData(pDbPage);
      memcpy(aPage, pData, szPage);







>
>
>
>
>
>







226334
226335
226336
226337
226338
226339
226340
226341
226342
226343
226344
226345
226346
226347
226348
226349
226350
226351
226352
226353
      pgno--;
      pTab->pgnoTrunc = pgno;
    }else{
      zErr = "bad page value";
      goto update_fail;
    }
  }

  if( dbpageBeginTrans(pTab)!=SQLITE_OK ){
    zErr = "failed to open transaction";
    goto update_fail;
  }

  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);
    if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
      unsigned char *aPage = sqlite3PagerGetData(pDbPage);
      memcpy(aPage, pData, szPage);
226331
226332
226333
226334
226335
226336
226337
226338
226339
226340
226341
226342
226343
226344
226345
226346
226347
226348
226349
226350
226351
226352
226353
226354
226355
226356

update_fail:
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
  return SQLITE_ERROR;
}

/* Since we do not know in advance which database files will be
** written by the sqlite_dbpage virtual table, start a write transaction
** on them all.
*/
static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3 *db = pTab->db;
  int i;
  for(i=0; i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
  pTab->pgnoTrunc = 0;
  return SQLITE_OK;
}

/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
*/
static int dbpageSync(sqlite3_vtab *pVtab){







<
<
<
<


<
<
<
<
<
<







226361
226362
226363
226364
226365
226366
226367




226368
226369






226370
226371
226372
226373
226374
226375
226376

update_fail:
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
  return SQLITE_ERROR;
}





static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;






  pTab->pgnoTrunc = 0;
  return SQLITE_OK;
}

/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
*/
static int dbpageSync(sqlite3_vtab *pVtab){
226378
226379
226380
226381
226382
226383
226384
226385
226386
226387
226388
226389
226390
226391
226392
}

/*
** Invoke this routine to register the "dbpage" virtual table module
*/
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
  static sqlite3_module dbpage_module = {
    0,                            /* iVersion */
    dbpageConnect,                /* xCreate */
    dbpageConnect,                /* xConnect */
    dbpageBestIndex,              /* xBestIndex */
    dbpageDisconnect,             /* xDisconnect */
    dbpageDisconnect,             /* xDestroy */
    dbpageOpen,                   /* xOpen - open a cursor */
    dbpageClose,                  /* xClose - close a cursor */







|







226398
226399
226400
226401
226402
226403
226404
226405
226406
226407
226408
226409
226410
226411
226412
}

/*
** Invoke this routine to register the "dbpage" virtual table module
*/
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
  static sqlite3_module dbpage_module = {
    2,                            /* iVersion */
    dbpageConnect,                /* xCreate */
    dbpageConnect,                /* xConnect */
    dbpageBestIndex,              /* xBestIndex */
    dbpageDisconnect,             /* xDisconnect */
    dbpageDisconnect,             /* xDestroy */
    dbpageOpen,                   /* xOpen - open a cursor */
    dbpageClose,                  /* xClose - close a cursor */
231697
231698
231699
231700
231701
231702
231703
231704
231705
231706
231707
231708
231709


231710
231711
231712
231713
231714
231715
231716
      sIter.nCol = nFk;
      res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter);
      if( res!=SQLITE_CHANGESET_OMIT ){
        rc = SQLITE_CONSTRAINT;
      }
    }
  }
  sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);

  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
    }else{


      sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
      sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
    }
  }

  assert( sApply.bRebase || sApply.rebase.nBuf==0 );
  if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){







<




<
>
>







231717
231718
231719
231720
231721
231722
231723

231724
231725
231726
231727

231728
231729
231730
231731
231732
231733
231734
231735
231736
      sIter.nCol = nFk;
      res = xConflict(pCtx, SQLITE_CHANGESET_FOREIGN_KEY, &sIter);
      if( res!=SQLITE_CHANGESET_OMIT ){
        rc = SQLITE_CONSTRAINT;
      }
    }
  }


  if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);

    }
    if( rc!=SQLITE_OK ){
      sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
      sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
    }
  }

  assert( sApply.bRebase || sApply.rebase.nBuf==0 );
  if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
243322
243323
243324
243325
243326
243327
243328
243329
243330
243331




243332
243333
243334
243335
243336
243337
243338
static int fts5IndexPrepareStmt(
  Fts5Index *p,
  sqlite3_stmt **ppStmt,
  char *zSql
){
  if( p->rc==SQLITE_OK ){
    if( zSql ){
      p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
          SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
          ppStmt, 0);




    }else{
      p->rc = SQLITE_NOMEM;
    }
  }
  sqlite3_free(zSql);
  return p->rc;
}







|


>
>
>
>







243342
243343
243344
243345
243346
243347
243348
243349
243350
243351
243352
243353
243354
243355
243356
243357
243358
243359
243360
243361
243362
static int fts5IndexPrepareStmt(
  Fts5Index *p,
  sqlite3_stmt **ppStmt,
  char *zSql
){
  if( p->rc==SQLITE_OK ){
    if( zSql ){
      int rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
          SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
          ppStmt, 0);
      /* If this prepare() call fails with SQLITE_ERROR, then one of the
      ** %_idx or %_data tables has been removed or modified. Call this
      ** corruption.  */
      p->rc = (rc==SQLITE_ERROR ? SQLITE_CORRUPT : rc);
    }else{
      p->rc = SQLITE_NOMEM;
    }
  }
  sqlite3_free(zSql);
  return p->rc;
}
247903
247904
247905
247906
247907
247908
247909


















247910
247911
247912
247913
247914
247915
247916
  Fts5Structure *pStruct,
  const char *zTerm,
  int nTerm,
  i64 iRowid
){
  const int f = FTS5INDEX_QUERY_SKIPHASH;
  Fts5Iter *pIter = 0;            /* Used to find term instance */



















  fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
  if( fts5MultiIterEof(p, pIter)==0 ){
    i64 iThis = fts5MultiIterRowid(pIter);
    if( iThis<iRowid ){
      fts5MultiIterNextFrom(p, pIter, iRowid);
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







247927
247928
247929
247930
247931
247932
247933
247934
247935
247936
247937
247938
247939
247940
247941
247942
247943
247944
247945
247946
247947
247948
247949
247950
247951
247952
247953
247954
247955
247956
247957
247958
  Fts5Structure *pStruct,
  const char *zTerm,
  int nTerm,
  i64 iRowid
){
  const int f = FTS5INDEX_QUERY_SKIPHASH;
  Fts5Iter *pIter = 0;            /* Used to find term instance */

  /* If the version number has not been set to SECUREDELETE, do so now. */
  if( p->pConfig->iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE ){
    Fts5Config *pConfig = p->pConfig;
    sqlite3_stmt *pStmt = 0;
    fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
          "REPLACE INTO %Q.'%q_config' VALUES ('version', %d)",
          pConfig->zDb, pConfig->zName, FTS5_CURRENT_VERSION_SECUREDELETE
    ));
    if( p->rc==SQLITE_OK ){
      int rc;
      sqlite3_step(pStmt);
      rc = sqlite3_finalize(pStmt);
      if( p->rc==SQLITE_OK ) p->rc = rc;
      pConfig->iCookie++;
      pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
    }
  }

  fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
  if( fts5MultiIterEof(p, pIter)==0 ){
    i64 iThis = fts5MultiIterRowid(pIter);
    if( iThis<iRowid ){
      fts5MultiIterNextFrom(p, pIter, iRowid);
    }
253744
253745
253746
253747
253748
253749
253750
253751
253752
253753
253754
253755
253756
253757
253758
253759
253760
253761
253762
253763
253764
253765
253766
253767
253768
253769
253770
  sqlite3_value **apVal,          /* Array of arguments */
  sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  Fts5Config *pConfig = pTab->p.pConfig;
  int eType0;                     /* value_type() of apVal[0] */
  int rc = SQLITE_OK;             /* Return code */
  int bUpdateOrDelete = 0;

  /* A transaction must be open when this is called. */
  assert( pTab->ts.eState==1 || pTab->ts.eState==2 );

  assert( pVtab->zErrMsg==0 );
  assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
  assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
       || sqlite3_value_type(apVal[0])==SQLITE_NULL
  );
  assert( pTab->p.pConfig->pzErrmsg==0 );
  if( pConfig->pgsz==0 ){
    rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
    if( rc!=SQLITE_OK ) return rc;
  }

  pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;

  /* Put any active cursors into REQUIRE_SEEK state. */
  fts5TripCursors(pTab);







<











|







253786
253787
253788
253789
253790
253791
253792

253793
253794
253795
253796
253797
253798
253799
253800
253801
253802
253803
253804
253805
253806
253807
253808
253809
253810
253811
  sqlite3_value **apVal,          /* Array of arguments */
  sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  Fts5Config *pConfig = pTab->p.pConfig;
  int eType0;                     /* value_type() of apVal[0] */
  int rc = SQLITE_OK;             /* Return code */


  /* A transaction must be open when this is called. */
  assert( pTab->ts.eState==1 || pTab->ts.eState==2 );

  assert( pVtab->zErrMsg==0 );
  assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
  assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
       || sqlite3_value_type(apVal[0])==SQLITE_NULL
  );
  assert( pTab->p.pConfig->pzErrmsg==0 );
  if( pConfig->pgsz==0 ){
    rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie);
    if( rc!=SQLITE_OK ) return rc;
  }

  pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;

  /* Put any active cursors into REQUIRE_SEEK state. */
  fts5TripCursors(pTab);
253781
253782
253783
253784
253785
253786
253787
253788
253789
253790
253791
253792
253793
253794
253795
      if( pConfig->bContentlessDelete ){
        fts5SetVtabError(pTab,
            "'delete' may not be used with a contentless_delete=1 table"
        );
        rc = SQLITE_ERROR;
      }else{
        rc = fts5SpecialDelete(pTab, apVal);
        bUpdateOrDelete = 1;
      }
    }else{
      rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
    }
  }else{
    /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
    ** any conflict on the rowid value must be detected before any







<







253822
253823
253824
253825
253826
253827
253828

253829
253830
253831
253832
253833
253834
253835
      if( pConfig->bContentlessDelete ){
        fts5SetVtabError(pTab,
            "'delete' may not be used with a contentless_delete=1 table"
        );
        rc = SQLITE_ERROR;
      }else{
        rc = fts5SpecialDelete(pTab, apVal);

      }
    }else{
      rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
    }
  }else{
    /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
    ** any conflict on the rowid value must be detected before any
253818
253819
253820
253821
253822
253823
253824
253825
253826
253827
253828
253829
253830
253831
253832
        fts5SetVtabError(pTab,
            "cannot DELETE from contentless fts5 table: %s", pConfig->zName
        );
        rc = SQLITE_ERROR;
      }else{
        i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
        bUpdateOrDelete = 1;
      }
    }

    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);








<







253858
253859
253860
253861
253862
253863
253864

253865
253866
253867
253868
253869
253870
253871
        fts5SetVtabError(pTab,
            "cannot DELETE from contentless fts5 table: %s", pConfig->zName
        );
        rc = SQLITE_ERROR;
      }else{
        i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);

      }
    }

    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);

253846
253847
253848
253849
253850
253851
253852
253853
253854
253855
253856
253857
253858
253859
253860

      if( eType0!=SQLITE_INTEGER ){
        /* An INSERT statement. If the conflict-mode is REPLACE, first remove
        ** the current entry (if any). */
        if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
          bUpdateOrDelete = 1;
        }
        fts5StorageInsert(&rc, pTab, apVal, pRowid);
      }

      /* UPDATE */
      else{
        Fts5Storage *pStorage = pTab->pStorage;







<







253885
253886
253887
253888
253889
253890
253891

253892
253893
253894
253895
253896
253897
253898

      if( eType0!=SQLITE_INTEGER ){
        /* An INSERT statement. If the conflict-mode is REPLACE, first remove
        ** the current entry (if any). */
        if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);

        }
        fts5StorageInsert(&rc, pTab, apVal, pRowid);
      }

      /* UPDATE */
      else{
        Fts5Storage *pStorage = pTab->pStorage;
253900
253901
253902
253903
253904
253905
253906
253907
253908
253909
253910
253911
253912
253913
253914
253915
253916
253917
253918
253919
253920
253921
253922
253923
253924
253925
253926
253927
253928
253929
253930
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid);
          }
        }else{
          rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
          fts5StorageInsert(&rc, pTab, apVal, pRowid);
        }
        bUpdateOrDelete = 1;
        sqlite3Fts5StorageReleaseDeleteRow(pStorage);
      }

    }
  }

  if( rc==SQLITE_OK
   && bUpdateOrDelete
   && pConfig->bSecureDelete
   && pConfig->iVersion==FTS5_CURRENT_VERSION
  ){
    rc = sqlite3Fts5StorageConfigValue(
        pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE
    );
    if( rc==SQLITE_OK ){
      pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
    }
  }

 update_out:
  pTab->p.pConfig->pzErrmsg = 0;
  return rc;
}







<


<
<
<
<
<
<
<
<
<
<
<
<
<
<







253938
253939
253940
253941
253942
253943
253944

253945
253946














253947
253948
253949
253950
253951
253952
253953
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5StorageContentInsert(pStorage, 1, apVal, pRowid);
          }
        }else{
          rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
          fts5StorageInsert(&rc, pTab, apVal, pRowid);
        }

        sqlite3Fts5StorageReleaseDeleteRow(pStorage);
      }














    }
  }

 update_out:
  pTab->p.pConfig->pzErrmsg = 0;
  return rc;
}
253969
253970
253971
253972
253973
253974
253975

253976
253977
253978
253979
253980
253981
253982
** hash-table. Any changes made to the database are reverted by SQLite.
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
  int rc;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
  rc = sqlite3Fts5StorageRollback(pTab->pStorage);

  return rc;
}

static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);

static void *fts5ApiUserData(Fts5Context *pCtx){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;







>







253992
253993
253994
253995
253996
253997
253998
253999
254000
254001
254002
254003
254004
254005
254006
** hash-table. Any changes made to the database are reverted by SQLite.
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
  int rc;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
  rc = sqlite3Fts5StorageRollback(pTab->pStorage);
  pTab->p.pConfig->pgsz = 0;
  return rc;
}

static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);

static void *fts5ApiUserData(Fts5Context *pCtx){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
255437
255438
255439
255440
255441
255442
255443
255444
255445
255446
255447
255448
255449
255450
255451
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552", -1, SQLITE_TRANSIENT);
}

/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as







|







255461
255462
255463
255464
255465
255466
255467
255468
255469
255470
255471
255472
255473
255474
255475
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2025-01-14 11:05:00 d2fe6b05f38d9d7cd78c5d252e99ac59f1aea071d669830c1ffe4e8966e84010", -1, SQLITE_TRANSIENT);
}

/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
255917
255918
255919
255920
255921
255922
255923





255924
255925
255926
255927
255928
255929
255930
      if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
      p->pConfig->bLock++;
      rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
      p->pConfig->bLock--;
      sqlite3_free(zSql);
      if( rc!=SQLITE_OK && pzErrMsg ){
        *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));





      }
    }
  }

  *ppStmt = p->aStmt[eStmt];
  sqlite3_reset(*ppStmt);
  return rc;







>
>
>
>
>







255941
255942
255943
255944
255945
255946
255947
255948
255949
255950
255951
255952
255953
255954
255955
255956
255957
255958
255959
      if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
      p->pConfig->bLock++;
      rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
      p->pConfig->bLock--;
      sqlite3_free(zSql);
      if( rc!=SQLITE_OK && pzErrMsg ){
        *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
      }
      if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){
        /* One of the internal tables - not the %_content table - is missing.
        ** This counts as a corrupted table.  */
       rc = SQLITE_CORRUPT;
      }
    }
  }

  *ppStmt = p->aStmt[eStmt];
  sqlite3_reset(*ppStmt);
  return rc;
261354
261355
261356
261357
261358
261359
261360
261361
261362
261363
261364
261365
261366
261367
261368
}

/*
** Write data to an incremental blob channel.
*/
static int SQLITE_TCLAPI incrblobOutput(
  ClientData instanceData,
  CONST char *buf,
  int toWrite,
  int *errorCodePtr
){
  IncrblobChannel *p = (IncrblobChannel *)instanceData;
  sqlite3_int64 nWrite = toWrite;   /* Number of bytes to write */
  sqlite3_int64 nBlob;              /* Total size of the blob */
  int rc;                           /* sqlite error code */







|







261383
261384
261385
261386
261387
261388
261389
261390
261391
261392
261393
261394
261395
261396
261397
}

/*
** Write data to an incremental blob channel.
*/
static int SQLITE_TCLAPI incrblobOutput(
  ClientData instanceData,
  const char *buf,
  int toWrite,
  int *errorCodePtr
){
  IncrblobChannel *p = (IncrblobChannel *)instanceData;
  sqlite3_int64 nWrite = toWrite;   /* Number of bytes to write */
  sqlite3_int64 nBlob;              /* Total size of the blob */
  int rc;                           /* sqlite error code */
262110
262111
262112
262113
262114
262115
262116
262117

262118
262119
262120
262121
262122
262123
262124
    int eType = p->eType;

    if( eType==SQLITE_NULL ){
      if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
        /* Only return a BLOB type if the Tcl variable is a bytearray and
        ** has no string representation. */
        eType = SQLITE_BLOB;
      }else if( (c=='b' && strcmp(zType,"boolean")==0)

             || (c=='w' && strcmp(zType,"wideInt")==0)
             || (c=='i' && strcmp(zType,"int")==0) 
      ){
        eType = SQLITE_INTEGER;
      }else if( c=='d' && strcmp(zType,"double")==0 ){
        eType = SQLITE_FLOAT;
      }else{







|
>







262139
262140
262141
262142
262143
262144
262145
262146
262147
262148
262149
262150
262151
262152
262153
262154
    int eType = p->eType;

    if( eType==SQLITE_NULL ){
      if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
        /* Only return a BLOB type if the Tcl variable is a bytearray and
        ** has no string representation. */
        eType = SQLITE_BLOB;
      }else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 )
             || (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 )
             || (c=='w' && strcmp(zType,"wideInt")==0)
             || (c=='i' && strcmp(zType,"int")==0) 
      ){
        eType = SQLITE_INTEGER;
      }else if( c=='d' && strcmp(zType,"double")==0 ){
        eType = SQLITE_FLOAT;
      }else{
262518
262519
262520
262521
262522
262523
262524
262525



262526
262527
262528
262529
262530
262531
262532
262533
262534
          /* Load a BLOB type if the Tcl variable is a bytearray and
          ** it has no string representation or the host
          ** parameter name begins with "@". */
          data = Tcl_GetByteArrayFromObj(pVar, &n);
          sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }else if( c=='b' && strcmp(zType,"boolean")==0 ){



          int nn;
          Tcl_GetIntFromObj(interp, pVar, &nn);
          sqlite3_bind_int(pStmt, i, nn);
        }else if( c=='d' && strcmp(zType,"double")==0 ){
          double r;
          Tcl_GetDoubleFromObj(interp, pVar, &r);
          sqlite3_bind_double(pStmt, i, r);
        }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
              (c=='i' && strcmp(zType,"int")==0) ){







|
>
>
>

|







262548
262549
262550
262551
262552
262553
262554
262555
262556
262557
262558
262559
262560
262561
262562
262563
262564
262565
262566
262567
          /* Load a BLOB type if the Tcl variable is a bytearray and
          ** it has no string representation or the host
          ** parameter name begins with "@". */
          data = Tcl_GetByteArrayFromObj(pVar, &n);
          sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }else if( c=='b' && pVar->bytes==0 
               && (strcmp(zType,"booleanString")==0
                   || strcmp(zType,"boolean")==0)
        ){
          int nn;
          Tcl_GetBooleanFromObj(interp, pVar, &nn);
          sqlite3_bind_int(pStmt, i, nn);
        }else if( c=='d' && strcmp(zType,"double")==0 ){
          double r;
          Tcl_GetDoubleFromObj(interp, pVar, &r);
          sqlite3_bind_double(pStmt, i, r);
        }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
              (c=='i' && strcmp(zType,"int")==0) ){
262856
262857
262858
262859
262860
262861
262862

262863
262864
262865
262866
262867
262868
262869
262870
/*
** If using Tcl version 8.6 or greater, use the NR functions to avoid
** recursive evaluation of scripts by the [db eval] and [db trans]
** commands. Even if the headers used while compiling the extension
** are 8.6 or newer, the code still tests the Tcl version at runtime.
** This allows stubs-enabled builds to be used with older Tcl libraries.
*/

#if TCL_MAJOR_VERSION>8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>=6)
# define SQLITE_TCL_NRE 1
static int DbUseNre(void){
  int major, minor;
  Tcl_GetVersion(&major, &minor, 0, 0);
  return( (major==8 && minor>=6) || major>8 );
}
#else







>
|







262889
262890
262891
262892
262893
262894
262895
262896
262897
262898
262899
262900
262901
262902
262903
262904
/*
** If using Tcl version 8.6 or greater, use the NR functions to avoid
** recursive evaluation of scripts by the [db eval] and [db trans]
** commands. Even if the headers used while compiling the extension
** are 8.6 or newer, the code still tests the Tcl version at runtime.
** This allows stubs-enabled builds to be used with older Tcl libraries.
*/
#if TCL_MAJOR_VERSION>8 || !defined(TCL_MINOR_VERSION) \
                        || TCL_MINOR_VERSION>=6
# define SQLITE_TCL_NRE 1
static int DbUseNre(void){
  int major, minor;
  Tcl_GetVersion(&major, &minor, 0, 0);
  return( (major==8 && minor>=6) || major>8 );
}
#else