SQLite

Check-in [854ba30490]
Login

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

Overview
Comment:If a virtual table xSync() returns an error message, copy it into a buffer allocated by sqlite3DbMalloc() before transfering it to Vdbe.zErrMsg.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 854ba3049005adf033e07e6740a36e63f2a56758
User & Date: dan 2013-08-21 17:35:48.189
Context
2013-08-21
19:13
Update sqlite3MemCompare() to try common cases first, for a modest speed improvement. (check-in: b25bac7919 user: drh tags: trunk)
17:35
If a virtual table xSync() returns an error message, copy it into a buffer allocated by sqlite3DbMalloc() before transfering it to Vdbe.zErrMsg. (check-in: 854ba30490 user: dan tags: trunk)
15:52
Performance enhancement in btreeParseCellPtr(). (check-in: a17190a229 user: drh tags: trunk)
Changes
Side-by-Side Diff Show Whitespace Changes Patch
Changes to src/sqliteInt.h.
3149
3150
3151
3152
3153
3154
3155
3156

3157
3158
3159
3160
3161
3162

3163
3164
3165
3166
3167
3168
3169
3149
3150
3151
3152
3153
3154
3155

3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170







-
+






+







#  define sqlite3VtabUnlock(X)
#  define sqlite3VtabUnlockList(X)
#  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
#  define sqlite3GetVTable(X,Y)  ((VTable*)0)
#else
   void sqlite3VtabClear(sqlite3 *db, Table*);
   void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
   int sqlite3VtabSync(sqlite3 *db, char **);
   int sqlite3VtabSync(sqlite3 *db, Vdbe*);
   int sqlite3VtabRollback(sqlite3 *db);
   int sqlite3VtabCommit(sqlite3 *db);
   void sqlite3VtabLock(VTable *);
   void sqlite3VtabUnlock(VTable *);
   void sqlite3VtabUnlockList(sqlite3*);
   int sqlite3VtabSavepoint(sqlite3 *, int, int);
   void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
   VTable *sqlite3GetVTable(sqlite3*, Table*);
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
void sqlite3VtabMakeWritable(Parse*,Table*);
void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
void sqlite3VtabFinishParse(Parse*, Token*);
void sqlite3VtabArgInit(Parse*);
Changes to src/vdbe.c.
493
494
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
493
494
495
496
497
498
499













500
501
502
503
504
505
506







-
-
-
-
-
-
-
-
-
-
-
-
-







  Savepoint *p;
  for(p=db->pSavepoint; p; p=p->pNext) n++;
  assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
  return 1;
}
#endif

/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
  sqlite3 *db = p->db;
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
}


/*
** Execute as much of a VDBE program as we can then return.
**
** sqlite3VdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
4346
4347
4348
4349
4350
4351
4352
4353

4354
4355
4356
4357
4358
4359
4360
4333
4334
4335
4336
4337
4338
4339

4340
4341
4342
4343
4344
4345
4346
4347







-
+







    v = pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( pC->pVtabCursor ){
    pVtab = pC->pVtabCursor->pVtab;
    pModule = pVtab->pModule;
    assert( pModule->xRowid );
    rc = pModule->xRowid(pC->pVtabCursor, &v);
    importVtabErrMsg(p, pVtab);
    sqlite3VtabImportErrmsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
    assert( pC->pCursor!=0 );
    rc = sqlite3VdbeCursorMoveto(pC);
    if( rc ) goto abort_due_to_error;
    if( pC->rowidIsValid ){
      v = pC->lastRowid;
5739
5740
5741
5742
5743
5744
5745
5746

5747
5748
5749
5750
5751
5752
5753
5726
5727
5728
5729
5730
5731
5732

5733
5734
5735
5736
5737
5738
5739
5740







-
+







** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
  VTable *pVTab;
  pVTab = pOp->p4.pVtab;
  rc = sqlite3VtabBegin(db, pVTab);
  if( pVTab ) importVtabErrMsg(p, pVTab->pVtab);
  if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**
5790
5791
5792
5793
5794
5795
5796
5797

5798
5799
5800
5801
5802
5803
5804
5777
5778
5779
5780
5781
5782
5783

5784
5785
5786
5787
5788
5789
5790
5791







-
+







  assert( p->bIsReader );
  pCur = 0;
  pVtabCursor = 0;
  pVtab = pOp->p4.pVtab->pVtab;
  pModule = (sqlite3_module *)pVtab->pModule;
  assert(pVtab && pModule);
  rc = pModule->xOpen(pVtab, &pVtabCursor);
  importVtabErrMsg(p, pVtab);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( SQLITE_OK==rc ){
    /* Initialize sqlite3_vtab_cursor base class */
    pVtabCursor->pVtab = pVtab;

    /* Initialize vdbe cursor object */
    pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
    if( pCur ){
5868
5869
5870
5871
5872
5873
5874
5875

5876
5877
5878
5879
5880
5881
5882
5855
5856
5857
5858
5859
5860
5861

5862
5863
5864
5865
5866
5867
5868
5869







-
+







      apArg[i] = &pArgc[i+1];
      sqlite3VdbeMemStoreType(apArg[i]);
    }

    p->inVtabMethod = 1;
    rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
    p->inVtabMethod = 0;
    importVtabErrMsg(p, pVtab);
    sqlite3VtabImportErrmsg(p, pVtab);
    if( rc==SQLITE_OK ){
      res = pModule->xEof(pVtabCursor);
    }

    if( res ){
      pc = pOp->p2 - 1;
    }
5919
5920
5921
5922
5923
5924
5925
5926

5927
5928
5929
5930
5931
5932
5933
5906
5907
5908
5909
5910
5911
5912

5913
5914
5915
5916
5917
5918
5919
5920







-
+







  ** can use the already allocated buffer instead of allocating a 
  ** new one.
  */
  sqlite3VdbeMemMove(&sContext.s, pDest);
  MemSetTypeFlag(&sContext.s, MEM_Null);

  rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
  importVtabErrMsg(p, pVtab);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( sContext.isError ){
    rc = sContext.isError;
  }

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occurred to ensure any
  ** dynamic allocation in sContext.s (a Mem struct) is  released.
5972
5973
5974
5975
5976
5977
5978
5979

5980
5981
5982
5983
5984
5985
5986
5959
5960
5961
5962
5963
5964
5965

5966
5967
5968
5969
5970
5971
5972
5973







-
+







  ** xNext(). Instead, if an error occurs, true is returned (indicating that 
  ** data is available) and the error code returned when xColumn or
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
  rc = pModule->xNext(pCur->pVtabCursor);
  p->inVtabMethod = 0;
  importVtabErrMsg(p, pVtab);
  sqlite3VtabImportErrmsg(p, pVtab);
  if( rc==SQLITE_OK ){
    res = pModule->xEof(pCur->pVtabCursor);
  }

  if( !res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
6009
6010
6011
6012
6013
6014
6015
6016

6017
6018
6019
6020
6021
6022
6023
5996
5997
5998
5999
6000
6001
6002

6003
6004
6005
6006
6007
6008
6009
6010







-
+







  assert( pName->flags & MEM_Str );
  testcase( pName->enc==SQLITE_UTF8 );
  testcase( pName->enc==SQLITE_UTF16BE );
  testcase( pName->enc==SQLITE_UTF16LE );
  rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
  if( rc==SQLITE_OK ){
    rc = pVtab->pModule->xRename(pVtab, pName->z);
    importVtabErrMsg(p, pVtab);
    sqlite3VtabImportErrmsg(p, pVtab);
    p->expired = 0;
  }
  break;
}
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE
6071
6072
6073
6074
6075
6076
6077
6078

6079
6080
6081
6082
6083
6084
6085
6058
6059
6060
6061
6062
6063
6064

6065
6066
6067
6068
6069
6070
6071
6072







-
+







      sqlite3VdbeMemStoreType(pX);
      apArg[i] = pX;
      pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, pVtab);
    sqlite3VtabImportErrmsg(p, pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = rowid;
    }
    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE_OK;
Changes to src/vdbeaux.c.
1761
1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775







-
+








  /* Before doing anything else, call the xSync() callback for any
  ** virtual module tables written in this transaction. This has to
  ** be done before determining whether a master journal file is 
  ** required, as an xSync() callback may add an attached database
  ** to the transaction.
  */
  rc = sqlite3VtabSync(db, &p->zErrMsg);
  rc = sqlite3VtabSync(db, p);

  /* This loop determines (a) if the commit hook should be invoked and
  ** (b) how many database files have open write transactions, not 
  ** including the temp database. (b) is important because if more than 
  ** one database file has an open write transaction, a master journal
  ** file is required for an atomic commit.
  */ 
3300
3301
3302
3303
3304
3305
3306















3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
  assert( iVar>0 );
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
  sqlite3 *db = p->db;
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
Changes to src/vtab.c.
806
807
808
809
810
811
812
813
814

815
816

817
818
819
820
821
822
823
824
825
826
827

828
829
830
831
832
833
834
835
836
806
807
808
809
810
811
812


813
814

815
816
817
818
819
820
821
822
823
824
825

826


827
828
829
830
831
832
833







-
-
+

-
+










-
+
-
-







}

/*
** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
** array. Return the error code for the first error that occurs, or
** SQLITE_OK if all xSync operations are successful.
**
** Set *pzErrmsg to point to a buffer that should be released using 
** sqlite3DbFree() containing an error message, if one is available.
** If an error message is available, leave it in p->zErrMsg.
*/
int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
  int i;
  int rc = SQLITE_OK;
  VTable **aVTrans = db->aVTrans;

  db->aVTrans = 0;
  for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
    int (*x)(sqlite3_vtab *);
    sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
    if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
      rc = x(pVtab);
      sqlite3DbFree(db, *pzErrmsg);
      sqlite3VtabImportErrmsg(p, pVtab);
      *pzErrmsg = pVtab->zErrMsg;
      pVtab->zErrMsg = 0;
    }
  }
  db->aVTrans = aVTrans;
  return rc;
}

/*