SQLite

Check-in [67da596d]
Login

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

Overview
Comment:Different fix for the fts5 COMMIT-following-OOM problem first fixed by [fba3129d]. This one does not cause problems if an fts5 table is renamed and then dropped within the same transaction.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.44
Files: files | file ages | folders
SHA3-256: 67da596d82ec0ed3c679da3be9d7379c557cd2fb83d7d833556107caf31327f6
User & Date: dan 2023-12-11 13:48:30
Context
2023-12-12
17:55
Worker1 Promiser API: when multiple db connections are active then use the requested connection instead of always the first-opened connection. Bug reported in forum post 894c330e7f23b177. (check-in: 3874e5a3 user: stephan tags: branch-3.44)
2023-12-11
13:48
Different fix for the fts5 COMMIT-following-OOM problem first fixed by [fba3129d]. This one does not cause problems if an fts5 table is renamed and then dropped within the same transaction. (check-in: 67da596d user: dan tags: branch-3.44)
2023-12-07
14:41
Different fix for the fts5 COMMIT-following-OOM problem first fixed by [fba3129d]. This one does not cause problems if an fts5 table is renamed and then dropped within the same transaction. (check-in: d8c6b246 user: dan tags: trunk)
2023-11-29
02:53
Increase the patch level to 3.44.3. (check-in: bb4d35e2 user: drh tags: branch-3.44)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_index.c.

353
354
355
356
357
358
359

360
361
362
363
364
365
366
  i64 iWriteRowid;                /* Rowid for current doc being written */
  int bDelete;                    /* Current write is a delete */
  int nContentlessDelete;         /* Number of contentless delete ops */
  int nPendingRow;                /* Number of INSERT in hash table */

  /* Error state. */
  int rc;                         /* Current error code */


  /* State used by the fts5DataXXX() functions. */
  sqlite3_blob *pReader;          /* RO incr-blob open on %_data table */
  sqlite3_stmt *pWriter;          /* "INSERT ... %_data VALUES(?,?)" */
  sqlite3_stmt *pDeleter;         /* "DELETE FROM %_data ... id>=? AND id<=?" */
  sqlite3_stmt *pIdxWriter;       /* "INSERT ... %_idx VALUES(?,?,?,?)" */
  sqlite3_stmt *pIdxDeleter;      /* "DELETE FROM %_idx WHERE segid=?" */







>







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  i64 iWriteRowid;                /* Rowid for current doc being written */
  int bDelete;                    /* Current write is a delete */
  int nContentlessDelete;         /* Number of contentless delete ops */
  int nPendingRow;                /* Number of INSERT in hash table */

  /* Error state. */
  int rc;                         /* Current error code */
  int flushRc;

  /* State used by the fts5DataXXX() functions. */
  sqlite3_blob *pReader;          /* RO incr-blob open on %_data table */
  sqlite3_stmt *pWriter;          /* "INSERT ... %_data VALUES(?,?)" */
  sqlite3_stmt *pDeleter;         /* "DELETE FROM %_data ... id>=? AND id<=?" */
  sqlite3_stmt *pIdxWriter;       /* "INSERT ... %_idx VALUES(?,?,?,?)" */
  sqlite3_stmt *pIdxDeleter;      /* "DELETE FROM %_idx WHERE segid=?" */
3998
3999
4000
4001
4002
4003
4004

4005
4006
4007
4008
4009
4010
4011
*/
static void fts5IndexDiscardData(Fts5Index *p){
  assert( p->pHash || p->nPendingData==0 );
  if( p->pHash ){
    sqlite3Fts5HashClear(p->pHash);
    p->nPendingData = 0;
    p->nPendingRow = 0;

  }
  p->nContentlessDelete = 0;
}

/*
** Return the size of the prefix, in bytes, that buffer 
** (pNew/<length-unknown>) shares with buffer (pOld/nOld).







>







3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
*/
static void fts5IndexDiscardData(Fts5Index *p){
  assert( p->pHash || p->nPendingData==0 );
  if( p->pHash ){
    sqlite3Fts5HashClear(p->pHash);
    p->nPendingData = 0;
    p->nPendingRow = 0;
    p->flushRc = SQLITE_OK;
  }
  p->nContentlessDelete = 0;
}

/*
** Return the size of the prefix, in bytes, that buffer 
** (pNew/<length-unknown>) shares with buffer (pOld/nOld).
5580
5581
5582
5583
5584
5585
5586




5587
5588
5589
5590
5591
5592
5593
5594


5595
5596
5597
5598
5599
5600
5601
}

/*
** Flush any data stored in the in-memory hash tables to the database.
*/
static void fts5IndexFlush(Fts5Index *p){
  /* Unless it is empty, flush the hash table to disk */




  if( p->nPendingData || p->nContentlessDelete ){
    assert( p->pHash );
    fts5FlushOneHash(p);
    if( p->rc==SQLITE_OK ){
      sqlite3Fts5HashClear(p->pHash);
      p->nPendingData = 0;
      p->nPendingRow = 0;
      p->nContentlessDelete = 0;


    }
  }
}

static Fts5Structure *fts5IndexOptimizeStruct(
  Fts5Index *p, 
  Fts5Structure *pStruct







>
>
>
>








>
>







5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
}

/*
** Flush any data stored in the in-memory hash tables to the database.
*/
static void fts5IndexFlush(Fts5Index *p){
  /* Unless it is empty, flush the hash table to disk */
  if( p->flushRc ){
    p->rc = p->flushRc;
    return;
  }
  if( p->nPendingData || p->nContentlessDelete ){
    assert( p->pHash );
    fts5FlushOneHash(p);
    if( p->rc==SQLITE_OK ){
      sqlite3Fts5HashClear(p->pHash);
      p->nPendingData = 0;
      p->nPendingRow = 0;
      p->nContentlessDelete = 0;
    }else if( p->nPendingData || p->nContentlessDelete ){
      p->flushRc = p->rc;
    }
  }
}

static Fts5Structure *fts5IndexOptimizeStruct(
  Fts5Index *p, 
  Fts5Structure *pStruct

Changes to ext/fts5/fts5_main.c.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

struct Fts5FullTable {
  Fts5Table p;                    /* Public class members from fts5Int.h */
  Fts5Storage *pStorage;          /* Document store */
  Fts5Global *pGlobal;            /* Global (connection wide) data */
  Fts5Cursor *pSortCsr;           /* Sort data from this cursor */
  int iSavepoint;                 /* Successful xSavepoint()+1 */
  int bInSavepoint;
#ifdef SQLITE_DEBUG
  struct Fts5TransactionState ts;
#endif
};

struct Fts5MatchPhrase {
  Fts5Buffer *pPoslist;           /* Pointer to current poslist */







|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

struct Fts5FullTable {
  Fts5Table p;                    /* Public class members from fts5Int.h */
  Fts5Storage *pStorage;          /* Document store */
  Fts5Global *pGlobal;            /* Global (connection wide) data */
  Fts5Cursor *pSortCsr;           /* Sort data from this cursor */
  int iSavepoint;                 /* Successful xSavepoint()+1 */
  
#ifdef SQLITE_DEBUG
  struct Fts5TransactionState ts;
#endif
};

struct Fts5MatchPhrase {
  Fts5Buffer *pPoslist;           /* Pointer to current poslist */
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
*/
static int fts5RenameMethod(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  const char *zName               /* New name of table */
){
  int rc;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  pTab->bInSavepoint = 1;
  rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);
  pTab->bInSavepoint = 0;
  return rc;
}

int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
  fts5TripCursors((Fts5FullTable*)pTab);
  return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
}

/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  int rc = SQLITE_OK;
  char *zSql = 0;
  fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);

  if( pTab->bInSavepoint==0 ){
    zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')",
        pTab->p.pConfig->zDb, pTab->p.pConfig->zName, pTab->p.pConfig->zName
    );
    if( zSql ){
      pTab->bInSavepoint = 1;
      rc = sqlite3_exec(pTab->p.pConfig->db, zSql, 0, 0, 0);
      pTab->bInSavepoint = 0;
      sqlite3_free(zSql);
    }else{
      rc = SQLITE_NOMEM;
    }
    if( rc==SQLITE_OK ){
      pTab->iSavepoint = iSavepoint+1;
    }
  }

  return rc;
}

/*
** The xRelease() method.
**
** This is a no-op.







<

<
















|

|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
<







2611
2612
2613
2614
2615
2616
2617

2618

2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637












2638
2639
2640


2641
2642
2643
2644
2645
2646
2647
*/
static int fts5RenameMethod(
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  const char *zName               /* New name of table */
){
  int rc;
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;

  rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);

  return rc;
}

int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
  fts5TripCursors((Fts5FullTable*)pTab);
  return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
}

/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
  int rc = SQLITE_OK;

  fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
  rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);












  if( rc==SQLITE_OK ){
    pTab->iSavepoint = iSavepoint+1;
  }


  return rc;
}

/*
** The xRelease() method.
**
** This is a no-op.
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
}

/*
** Run an integrity check on the FTS5 data structures.  Return a string
** if anything is found amiss.  Return a NULL pointer if everything is
** OK.
*/
static int fts5Integrity(
  sqlite3_vtab *pVtab,    /* the FTS5 virtual table to check */
  const char *zSchema,    /* Name of schema in which this table lives */
  const char *zTabname,   /* Name of the table itself */
  int isQuick,            /* True if this is a quick-check */
  char **pzErr            /* Write error message here */
){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;







|







2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
}

/*
** Run an integrity check on the FTS5 data structures.  Return a string
** if anything is found amiss.  Return a NULL pointer if everything is
** OK.
*/
static int fts5IntegrityMethod(
  sqlite3_vtab *pVtab,    /* the FTS5 virtual table to check */
  const char *zSchema,    /* Name of schema in which this table lives */
  const char *zTabname,   /* Name of the table itself */
  int isQuick,            /* True if this is a quick-check */
  char **pzErr            /* Write error message here */
){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
    /* xRollback     */ fts5RollbackMethod,
    /* xFindFunction */ fts5FindFunctionMethod,
    /* xRename       */ fts5RenameMethod,
    /* xSavepoint    */ fts5SavepointMethod,
    /* xRelease      */ fts5ReleaseMethod,
    /* xRollbackTo   */ fts5RollbackToMethod,
    /* xShadowName   */ fts5ShadowName,
    /* xIntegrity    */ fts5Integrity
  };

  int rc;
  Fts5Global *pGlobal = 0;

  pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
  if( pGlobal==0 ){







|







2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
    /* xRollback     */ fts5RollbackMethod,
    /* xFindFunction */ fts5FindFunctionMethod,
    /* xRename       */ fts5RenameMethod,
    /* xSavepoint    */ fts5SavepointMethod,
    /* xRelease      */ fts5ReleaseMethod,
    /* xRollbackTo   */ fts5RollbackToMethod,
    /* xShadowName   */ fts5ShadowName,
    /* xIntegrity    */ fts5IntegrityMethod
  };

  int rc;
  Fts5Global *pGlobal = 0;

  pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
  if( pGlobal==0 ){

Changes to ext/fts5/test/fts5misc.test.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
do_execsql_test 2.2.1 {
  CREATE TABLE t0(c0);
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  BEGIN TRANSACTION;
  INSERT INTO vt0(c0) VALUES ('xyz');
}

breakpoint
do_execsql_test 2.2.2 {
  ALTER TABLE t0 RENAME TO t1;
}
do_execsql_test 2.2.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.2.4 {







<







87
88
89
90
91
92
93

94
95
96
97
98
99
100
do_execsql_test 2.2.1 {
  CREATE TABLE t0(c0);
  CREATE VIRTUAL TABLE vt0 USING fts5(c0);
  BEGIN TRANSACTION;
  INSERT INTO vt0(c0) VALUES ('xyz');
}


do_execsql_test 2.2.2 {
  ALTER TABLE t0 RENAME TO t1;
}
do_execsql_test 2.2.3 {
  INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.2.4 {
496
497
498
499
500
501
502















503
504
505
do_execsql_test 17.5 {
  SELECT c0 FROM t0 WHERE c0 GLOB '*f*';
} {assertionfaultproblem}
do_execsql_test 17.5 {
  SELECT c0 FROM t0 WHERE c0 GLOB '*faul*';
} {assertionfaultproblem}

















finish_test








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



495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
do_execsql_test 17.5 {
  SELECT c0 FROM t0 WHERE c0 GLOB '*f*';
} {assertionfaultproblem}
do_execsql_test 17.5 {
  SELECT c0 FROM t0 WHERE c0 GLOB '*faul*';
} {assertionfaultproblem}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 18.0 {
  BEGIN;
    CREATE VIRTUAL TABLE t1 USING fts5(text);
    ALTER TABLE t1 RENAME TO t2;
}

do_execsql_test 18.1 {
    DROP TABLE t2;
}

do_execsql_test 18.2 {
  COMMIT;
}

finish_test