SQLite

Check-in [02b77a582c]
Login

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

Overview
Comment:Fix a memory leak that occurs when an out-of-memory error occurs while preparing a statement that has multiple virtual table updates within triggers. Other virtual table changes to support full-coverage testing. (CVS 6661)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 02b77a582c65e0eb45eb1a9abbdeef11f52d7ce6
User & Date: drh 2009-05-20 20:10:47.000
Context
2009-05-21
04:42
Add conditional 'extern "C"' block to sqlite3async.h. Ticket #3866. (CVS 6662) (check-in: e4d1b117c9 user: danielk1977 tags: trunk)
2009-05-20
20:10
Fix a memory leak that occurs when an out-of-memory error occurs while preparing a statement that has multiple virtual table updates within triggers. Other virtual table changes to support full-coverage testing. (CVS 6661) (check-in: 02b77a582c user: drh tags: trunk)
16:22
Remove unused, undocumented, and untested error reporting logic from the xFindFunction interface in virtual tables. (CVS 6660) (check-in: 55d6ced262 user: drh tags: trunk)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to src/vtab.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2006 June 10
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.88 2009/05/20 16:22:02 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2006 June 10
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.89 2009/05/20 20:10:47 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
103
104
105
106
107
108
109

110
111
112
113
114


115
116
117
118
119
120
121
*/
void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
  assert( pVtab->nRef>0 );
  pVtab->nRef--;
  assert(db);
  assert( sqlite3SafetyCheckOk(db) );
  if( pVtab->nRef==0 ){

    if( db->magic==SQLITE_MAGIC_BUSY ){
      (void)sqlite3SafetyOff(db);
      pVtab->pModule->xDisconnect(pVtab);
      (void)sqlite3SafetyOn(db);
    } else {


      pVtab->pModule->xDisconnect(pVtab);
    }
  }
}

/*
** Clear any and all virtual-table information from the Table record.







>




|
>
>







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
*/
void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
  assert( pVtab->nRef>0 );
  pVtab->nRef--;
  assert(db);
  assert( sqlite3SafetyCheckOk(db) );
  if( pVtab->nRef==0 ){
#ifdef SQLITE_DEBUG
    if( db->magic==SQLITE_MAGIC_BUSY ){
      (void)sqlite3SafetyOff(db);
      pVtab->pModule->xDisconnect(pVtab);
      (void)sqlite3SafetyOn(db);
    } else 
#endif
    {
      pVtab->pModule->xDisconnect(pVtab);
    }
  }
}

/*
** Clear any and all virtual-table information from the Table record.
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  if( pParse->db->flags & SQLITE_SharedCache ){
    sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
    return;
  }

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
  pTable = pParse->pNewTable;
  if( pTable==0 || pParse->nErr ) return;
  assert( 0==pTable->pIndex );

  db = pParse->db;
  iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
  assert( iDb>=0 );

  pTable->tabFlags |= TF_Virtual;







|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  if( pParse->db->flags & SQLITE_SharedCache ){
    sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
    return;
  }

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
  pTable = pParse->pNewTable;
  if( pTable==0 ) return;
  assert( 0==pTable->pIndex );

  db = pParse->db;
  iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
  assert( iDb>=0 );

  pTable->tabFlags |= TF_Virtual;
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
  if( pParse->sArg.z && pParse->pNewTable ){
    const char *z = (const char*)pParse->sArg.z;
    int n = pParse->sArg.n;
    sqlite3 *db = pParse->db;
    addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
  }
}








|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
  if( pParse->sArg.z && ALWAYS(pParse->pNewTable) ){
    const char *z = (const char*)pParse->sArg.z;
    int n = pParse->sArg.n;
    sqlite3 *db = pParse->db;
    addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n));
  }
}

374
375
376
377
378
379
380


381
382
383
384
385
386
387
388

  db->pVTab = pTab;
  rc = sqlite3SafetyOff(db);
  assert( rc==SQLITE_OK );
  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr);
  rc2 = sqlite3SafetyOn(db);
  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;


  if( rc==SQLITE_OK && pVtab ){
    pVtab->pModule = pMod->pModule;
    pVtab->nRef = 1;
    pTab->pVtab = pVtab;
  }

  if( SQLITE_OK!=rc ){
    if( zErr==0 ){







>
>
|







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

  db->pVTab = pTab;
  rc = sqlite3SafetyOff(db);
  assert( rc==SQLITE_OK );
  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr);
  rc2 = sqlite3SafetyOn(db);
  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
  /* Justification of ALWAYS():  A correct vtab constructor must allocate
  ** the sqlite3_vtab object if successful. */
  if( rc==SQLITE_OK && ALWAYS(pVtab) ){
    pVtab->pModule = pMod->pModule;
    pVtab->nRef = 1;
    pTab->pVtab = pVtab;
  }

  if( SQLITE_OK!=rc ){
    if( zErr==0 ){
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
**
** This call is a no-op if table pTab is not a virtual table.
*/
int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
  Module *pMod;
  int rc = SQLITE_OK;


  if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
    return SQLITE_OK;
  }

  pMod = pTab->pMod;
  if( !pMod ){
    const char *zModule = pTab->azModuleArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);







>
|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
**
** This call is a no-op if table pTab is not a virtual table.
*/
int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
  Module *pMod;
  int rc = SQLITE_OK;

  assert( pTab );
  if( (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
    return SQLITE_OK;
  }

  pMod = pTab->pMod;
  if( !pMod ){
    const char *zModule = pTab->azModuleArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
525
526
527
528
529
530
531


532
533
534
535
536
537
538
539
  if( !pMod ){
    *pzErr = sqlite3MPrintf(db, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
  }



  if( rc==SQLITE_OK && pTab->pVtab ){
      rc = addToVTrans(db, pTab->pVtab);
  }

  return rc;
}

/*







>
>
|







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  if( !pMod ){
    *pzErr = sqlite3MPrintf(db, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
  }

  /* Justification of ALWAYS():  The xConstructor method is required to
  ** create a valid sqlite3_vtab if it returns SQLITE_OK. */
  if( rc==SQLITE_OK && ALWAYS(pTab->pVtab) ){
      rc = addToVTrans(db, pTab->pVtab);
  }

  return rc;
}

/*
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.
**
** This call is a no-op if zTab is not a virtual table.
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
{
  int rc = SQLITE_OK;
  Table *pTab;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
  assert(pTab);
  if( pTab->pVtab ){
    int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
    rc = sqlite3SafetyOff(db);
    assert( rc==SQLITE_OK );
    if( xDestroy ){
      rc = xDestroy(pTab->pVtab);
    }
    (void)sqlite3SafetyOn(db);
    if( rc==SQLITE_OK ){
      int i;
      for(i=0; i<db->nVTrans; i++){
        if( db->aVTrans[i]==pTab->pVtab ){
          db->aVTrans[i] = db->aVTrans[--db->nVTrans];
          break;







|
<




<
|



<

<







602
603
604
605
606
607
608
609

610
611
612
613

614
615
616
617

618

619
620
621
622
623
624
625
/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.
**
** This call is a no-op if zTab is not a virtual table.
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){

  int rc = SQLITE_OK;
  Table *pTab;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);

  if( ALWAYS(pTab!=0 && pTab->pVtab!=0) ){
    int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
    rc = sqlite3SafetyOff(db);
    assert( rc==SQLITE_OK );

      rc = xDestroy(pTab->pVtab);

    (void)sqlite3SafetyOn(db);
    if( rc==SQLITE_OK ){
      int i;
      for(i=0; i<db->nVTrans; i++){
        if( db->aVTrans[i]==pTab->pVtab ){
          db->aVTrans[i] = db->aVTrans[--db->nVTrans];
          break;
635
636
637
638
639
640
641
642
643
644


645
646
647
648
649
650
651
** the offset of the method to call in the sqlite3_module structure.
**
** The array is cleared after invoking the callbacks. 
*/
static void callFinaliser(sqlite3 *db, int offset){
  int i;
  if( db->aVTrans ){
    for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){
      sqlite3_vtab *pVtab = db->aVTrans[i];
      int (*x)(sqlite3_vtab *);


      x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
      if( x ) x(pVtab);
      sqlite3VtabUnlock(db, pVtab);
    }
    sqlite3DbFree(db, db->aVTrans);
    db->nVTrans = 0;
    db->aVTrans = 0;







|


>
>







639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
** the offset of the method to call in the sqlite3_module structure.
**
** The array is cleared after invoking the callbacks. 
*/
static void callFinaliser(sqlite3 *db, int offset){
  int i;
  if( db->aVTrans ){
    for(i=0; i<db->nVTrans; i++){
      sqlite3_vtab *pVtab = db->aVTrans[i];
      int (*x)(sqlite3_vtab *);

      assert( pVtab!=0 );
      x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
      if( x ) x(pVtab);
      sqlite3VtabUnlock(db, pVtab);
    }
    sqlite3DbFree(db, db->aVTrans);
    db->nVTrans = 0;
    db->aVTrans = 0;
664
665
666
667
668
669
670
671
672
673

674
675
676
677
678
679
680
  int i;
  int rc = SQLITE_OK;
  int rcsafety;
  sqlite3_vtab **aVTrans = db->aVTrans;

  rc = sqlite3SafetyOff(db);
  db->aVTrans = 0;
  for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
    sqlite3_vtab *pVtab = aVTrans[i];
    int (*x)(sqlite3_vtab *);

    x = pVtab->pModule->xSync;
    if( x ){
      rc = x(pVtab);
      sqlite3DbFree(db, *pzErrmsg);
      *pzErrmsg = pVtab->zErrMsg;
      pVtab->zErrMsg = 0;
    }







|


>







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  int i;
  int rc = SQLITE_OK;
  int rcsafety;
  sqlite3_vtab **aVTrans = db->aVTrans;

  rc = sqlite3SafetyOff(db);
  db->aVTrans = 0;
  for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
    sqlite3_vtab *pVtab = aVTrans[i];
    int (*x)(sqlite3_vtab *);
    assert( pVtab!=0 );
    x = pVtab->pModule->xSync;
    if( x ){
      rc = x(pVtab);
      sqlite3DbFree(db, *pzErrmsg);
      *pzErrmsg = pVtab->zErrMsg;
      pVtab->zErrMsg = 0;
    }
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
  int rc = SQLITE_OK;
  const sqlite3_module *pModule;

  /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
  ** than zero, then this function is being called from within a
  ** virtual module xSync() callback. It is illegal to write to 
  ** virtual module tables in this case, so return SQLITE_MISUSE.
  */
  if( sqlite3VtabInSync(db) ){
    return SQLITE_LOCKED;
  }
  if( !pVtab ){
    return SQLITE_OK;
  } 
  pModule = pVtab->pModule;

  if( pModule->xBegin ){
    int i;


    /* If pVtab is already in the aVTrans array, return early */
    for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){
      if( db->aVTrans[i]==pVtab ){
        return SQLITE_OK;
      }
    }

    /* Invoke the xBegin method */
    rc = pModule->xBegin(pVtab);







|














|







724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
  int rc = SQLITE_OK;
  const sqlite3_module *pModule;

  /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
  ** than zero, then this function is being called from within a
  ** virtual module xSync() callback. It is illegal to write to 
  ** virtual module tables in this case, so return SQLITE_LOCKED.
  */
  if( sqlite3VtabInSync(db) ){
    return SQLITE_LOCKED;
  }
  if( !pVtab ){
    return SQLITE_OK;
  } 
  pModule = pVtab->pModule;

  if( pModule->xBegin ){
    int i;


    /* If pVtab is already in the aVTrans array, return early */
    for(i=0; i<db->nVTrans; i++){
      if( db->aVTrans[i]==pVtab ){
        return SQLITE_OK;
      }
    }

    /* Invoke the xBegin method */
    rc = pModule->xBegin(pVtab);
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  FuncDef *pNew;
  int rc = 0;
  char *zLowerName;
  unsigned char *z;


  /* Check to see the left operand is a column in a virtual table */
  if( pExpr==0 ) return pDef;
  if( pExpr->op!=TK_COLUMN ) return pDef;
  pTab = pExpr->pTab;
  if( pTab==0 ) return pDef;
  if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
  pVtab = pTab->pVtab;
  assert( pVtab!=0 );
  assert( pVtab->pModule!=0 );
  pMod = (sqlite3_module *)pVtab->pModule;
  if( pMod->xFindFunction==0 ) return pDef;
 







|


|







785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  FuncDef *pNew;
  int rc = 0;
  char *zLowerName;
  unsigned char *z;


  /* Check to see the left operand is a column in a virtual table */
  if( NEVER(pExpr==0) ) return pDef;
  if( pExpr->op!=TK_COLUMN ) return pDef;
  pTab = pExpr->pTab;
  if( NEVER(pTab==0) ) return pDef;
  if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
  pVtab = pTab->pVtab;
  assert( pVtab!=0 );
  assert( pVtab->pModule!=0 );
  pMod = (sqlite3_module *)pVtab->pModule;
  if( pMod->xFindFunction==0 ) return pDef;
 
828
829
830
831
832
833
834


835
836
837
838
839
840

841
842
843
844
845
846
847
848
** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]
** array so that an OP_VBegin will get generated for it.  Add pTab to the
** array if it is missing.  If pTab is already in the array, this routine
** is a no-op.
*/
void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
  int i, n;


  assert( IsVirtual(pTab) );
  for(i=0; i<pParse->nVtabLock; i++){
    if( pTab==pParse->apVtabLock[i] ) return;
  }
  n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]);
  pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n);

  if( pParse->apVtabLock ){
    pParse->apVtabLock[pParse->nVtabLock++] = pTab;
  }else{
    pParse->db->mallocFailed = 1;
  }
}

#endif /* SQLITE_OMIT_VIRTUALTABLE */







>
>





|
>
|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]
** array so that an OP_VBegin will get generated for it.  Add pTab to the
** array if it is missing.  If pTab is already in the array, this routine
** is a no-op.
*/
void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
  int i, n;
  Table **apVtabLock;

  assert( IsVirtual(pTab) );
  for(i=0; i<pParse->nVtabLock; i++){
    if( pTab==pParse->apVtabLock[i] ) return;
  }
  n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]);
  apVtabLock = sqlite3_realloc(pParse->apVtabLock, n);
  if( apVtabLock ){
    pParse->apVtabLock = apVtabLock;
    pParse->apVtabLock[pParse->nVtabLock++] = pTab;
  }else{
    pParse->db->mallocFailed = 1;
  }
}

#endif /* SQLITE_OMIT_VIRTUALTABLE */