/ Check-in [c615c38c]
Login

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

Overview
Comment:Hold the database mutex for the duration of an sqlite3changeset_apply() call. Also for the duration of all sqlite3session_xxx() calls.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: c615c38c3283e21c33550c093099a793761123a7
User & Date: dan 2011-03-18 18:03:14
Context
2011-03-19
02:37
Merge the fix to ticket [f7b4edece25c99485] into the sessions branch. check-in: 1b736ac2 user: drh tags: sessions
2011-03-18
18:03
Hold the database mutex for the duration of an sqlite3changeset_apply() call. Also for the duration of all sqlite3session_xxx() calls. check-in: c615c38c user: dan tags: sessions
16:47
Fixes for compiler warnings. Minor code cleanup. check-in: 9604d130 user: drh tags: sessions
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to ext/session/sqlite3session.c.

748
749
750
751
752
753
754


755
756
757
758
759
760
761
...
862
863
864
865
866
867
868



869
870
871
872
873
874
875
876
877
878

879
880

881
882

883
884
885
886
887
888
889



890
891
892
893
894
895
896
897
....
1280
1281
1282
1283
1284
1285
1286


1287
1288
1289
1290
1291
1292
1293
....
1353
1354
1355
1356
1357
1358
1359


1360
1361
1362
1363
1364
1365
1366


1367
1368
1369
1370


1371
1372
1373
1374
1375
1376
1377
....
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
....
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
  char const *zName,              /* Table name */
  sqlite3_int64 iKey1,            /* Rowid of row about to be deleted/updated */
  sqlite3_int64 iKey2             /* New rowid value (for a rowid UPDATE) */
){
  sqlite3_session *pSession;
  int nDb = strlen(zDb);
  int nName = strlen(zDb);


 
  for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){
    SessionTable *pTab;

    /* If this session is attached to a different database ("main", "temp" 
    ** etc.), or if it is not currently enabled, there is nothing to do. Skip 
    ** to the next session object attached to this database. */
................................................................................
*/
int sqlite3session_attach(
  sqlite3_session *pSession,      /* Session object */
  const char *zName               /* Table name */
){
  SessionTable *pTab;             /* New table object (if required) */
  int nName;                      /* Number of bytes in string zName */




  /* First search for an existing entry. If one is found, this call is
  ** a no-op. Return early. */
  nName = strlen(zName);
  for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){
    if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){
      return SQLITE_OK;
    }
  }


  /* Allocate new SessionTable object. */
  pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);

  if( !pTab ) return SQLITE_NOMEM;


  /* Populate the new SessionTable object and link it into the list. */
  memset(pTab, 0, sizeof(SessionTable));
  pTab->zName = (char *)&pTab[1];
  memcpy(pTab->zName, zName, nName+1);
  pTab->pNext = pSession->pTable;
  pSession->pTable = pTab;




  return SQLITE_OK;
}

/*
** Ensure that there is room in the buffer to append nByte bytes of data.
** If not, use sqlite3_realloc() to grow the buffer so that there is.
**
** If successful, return zero. Otherwise, if an OOM condition is encountered,
................................................................................
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  sqlite3 *db = pSession->db;     /* Source database handle */
  SessionTable *pTab;             /* Used to iterate through attached tables */
  SessionBuffer buf = {0,0,0};    /* Buffer in which to accumlate changeset */
  int rc;                         /* Return code */



  /* Zero the output variables in case an error occurs. If this session
  ** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
  ** this call will be a no-op.  */
  *pnChangeset = 0;
  *ppChangeset = 0;
  rc = pSession->rc;
................................................................................

  if( rc==SQLITE_OK ){
    *pnChangeset = buf.nBuf;
    *ppChangeset = buf.aBuf;
  }else{
    sqlite3_free(buf.aBuf);
  }


  return rc;
}

/*
** Enable or disable the session object passed as the first argument.
*/
int sqlite3session_enable(sqlite3_session *pSession, int bEnable){


  if( bEnable>=0 ){
    pSession->bEnable = bEnable;
  }
  return pSession->bEnable;


}

/*
** Create an iterator used to iterate through the contents of a changeset.
*/
int sqlite3changeset_start(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
................................................................................
  const char *zTab = 0;           /* Name of current table */
  int nTab = 0;                   /* Result of strlen(zTab) */
  SessionApplyCtx sApply;         /* changeset_apply() context object */

  memset(&sApply, 0, sizeof(sApply));
  sqlite3changeset_start(&pIter, nChangeset, pChangeset);


  rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
    int nCol;
    int op;
    int bReplace = 0;
    int bRetry = 0;
    const char *zNew;
................................................................................
  }

  sqlite3_finalize(sApply.pInsert);
  sqlite3_finalize(sApply.pDelete);
  sqlite3_finalize(sApply.pUpdate);
  sqlite3_finalize(sApply.pSelect);
  sqlite3_free(sApply.azCol);

  return rc;
}

#endif        /* #ifdef SQLITE_ENABLE_SESSION */







>
>







 







>
>
>





|
<
|
|
<
>
|
|
>
|
<
>






|
>
>
>
|







 







>
>







 







>
>







>
>



|
>
>







 







>







 







>




748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879

880
881

882
883
884
885
886

887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
....
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
....
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
....
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
  char const *zName,              /* Table name */
  sqlite3_int64 iKey1,            /* Rowid of row about to be deleted/updated */
  sqlite3_int64 iKey2             /* New rowid value (for a rowid UPDATE) */
){
  sqlite3_session *pSession;
  int nDb = strlen(zDb);
  int nName = strlen(zDb);

  assert( sqlite3_mutex_held(db->mutex) );

  for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){
    SessionTable *pTab;

    /* If this session is attached to a different database ("main", "temp" 
    ** etc.), or if it is not currently enabled, there is nothing to do. Skip 
    ** to the next session object attached to this database. */
................................................................................
*/
int sqlite3session_attach(
  sqlite3_session *pSession,      /* Session object */
  const char *zName               /* Table name */
){
  SessionTable *pTab;             /* New table object (if required) */
  int nName;                      /* Number of bytes in string zName */
  int rc = SQLITE_OK;

  sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));

  /* First search for an existing entry. If one is found, this call is
  ** a no-op. Return early. */
  nName = strlen(zName);
  for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){
    if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break;

  }


  if( !pTab ){
    /* Allocate new SessionTable object. */
    pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
    if( !pTab ){
      rc = SQLITE_NOMEM;

    }else{
      /* Populate the new SessionTable object and link it into the list. */
      memset(pTab, 0, sizeof(SessionTable));
      pTab->zName = (char *)&pTab[1];
      memcpy(pTab->zName, zName, nName+1);
      pTab->pNext = pSession->pTable;
      pSession->pTable = pTab;
    }
  }

  sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
  return rc;
}

/*
** Ensure that there is room in the buffer to append nByte bytes of data.
** If not, use sqlite3_realloc() to grow the buffer so that there is.
**
** If successful, return zero. Otherwise, if an OOM condition is encountered,
................................................................................
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  sqlite3 *db = pSession->db;     /* Source database handle */
  SessionTable *pTab;             /* Used to iterate through attached tables */
  SessionBuffer buf = {0,0,0};    /* Buffer in which to accumlate changeset */
  int rc;                         /* Return code */

  sqlite3_mutex_enter(sqlite3_db_mutex(db));

  /* Zero the output variables in case an error occurs. If this session
  ** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
  ** this call will be a no-op.  */
  *pnChangeset = 0;
  *ppChangeset = 0;
  rc = pSession->rc;
................................................................................

  if( rc==SQLITE_OK ){
    *pnChangeset = buf.nBuf;
    *ppChangeset = buf.aBuf;
  }else{
    sqlite3_free(buf.aBuf);
  }

  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}

/*
** Enable or disable the session object passed as the first argument.
*/
int sqlite3session_enable(sqlite3_session *pSession, int bEnable){
  int ret;
  sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
  if( bEnable>=0 ){
    pSession->bEnable = bEnable;
  }
  ret = pSession->bEnable;
  sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
  return ret;
}

/*
** Create an iterator used to iterate through the contents of a changeset.
*/
int sqlite3changeset_start(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
................................................................................
  const char *zTab = 0;           /* Name of current table */
  int nTab = 0;                   /* Result of strlen(zTab) */
  SessionApplyCtx sApply;         /* changeset_apply() context object */

  memset(&sApply, 0, sizeof(sApply));
  sqlite3changeset_start(&pIter, nChangeset, pChangeset);

  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
    int nCol;
    int op;
    int bReplace = 0;
    int bRetry = 0;
    const char *zNew;
................................................................................
  }

  sqlite3_finalize(sApply.pInsert);
  sqlite3_finalize(sApply.pDelete);
  sqlite3_finalize(sApply.pUpdate);
  sqlite3_finalize(sApply.pSelect);
  sqlite3_free(sApply.azCol);
  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}

#endif        /* #ifdef SQLITE_ENABLE_SESSION */

install-sh became a regular file.

whitespace changes only

test/progress.test became executable.

whitespace changes only

tool/mkopts.tcl became executable.

whitespace changes only