/ Check-in [c698a21a]
Login

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

Overview
Comment:Add the sqlite3_snapshot_cmp() API.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | snapshot-cmp
Files: files | file ages | folders
SHA1:c698a21af740ca1019c3a771fb83e569cd6bf23e
User & Date: dan 2016-04-11 19:59:52
Context
2016-04-12
15:14
Update the documentation for sqlite3_snapshot_cmp() to make the circumstances under which the comparison is valid clearer. Add tests for the same. Closed-Leaf check-in: 8fc83474 user: dan tags: snapshot-cmp
2016-04-11
19:59
Add the sqlite3_snapshot_cmp() API. check-in: c698a21a user: dan tags: snapshot-cmp
19:01
Performance optimization to sqlite3Dequote() and its callers. check-in: 9efe2265 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

  8123   8123   ** The application must eventually free every [sqlite3_snapshot] object
  8124   8124   ** using this routine to avoid a memory leak.
  8125   8125   **
  8126   8126   ** The [sqlite3_snapshot_free()] interface is only available when the
  8127   8127   ** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
  8128   8128   */
  8129   8129   SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
         8130  +
         8131  +/*
         8132  +** CAPI3REF: Compare the ages of two snapshot handles.
         8133  +** EXPERIMENTAL
         8134  +**
         8135  +** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
         8136  +** of two valid snapshot handles. 
         8137  +**
         8138  +** If the two snapshot handles are not associated with the same database 
         8139  +** file, the results are undefined. If either of the snapshot handles
         8140  +** is no longer valid because the database snapshot they refer to has been
         8141  +** destroyed by a checkpoint, the results are undefined. 
         8142  +**
         8143  +** Otherwise, this API returns a negative value if P1 refers to an older
         8144  +** snapshot than P2, zero if the two handles refer to the same database
         8145  +** snapshot, and a positive value if P1 is a newer snapshot than P2.
         8146  +*/
         8147  +SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
         8148  +  sqlite3_snapshot *p1,
         8149  +  sqlite3_snapshot *p2
         8150  +);
  8130   8151   
  8131   8152   /*
  8132   8153   ** Undo the hack that converts floating point types to integer for
  8133   8154   ** builds on processors without floating point support.
  8134   8155   */
  8135   8156   #ifdef SQLITE_OMIT_FLOATING_POINT
  8136   8157   # undef double
  8137   8158   #endif
  8138   8159   
  8139   8160   #ifdef __cplusplus
  8140   8161   }  /* End of the 'extern "C"' block */
  8141   8162   #endif
  8142   8163   #endif /* _SQLITE3_H_ */

Changes to src/test1.c.

  2355   2355     }
  2356   2356     pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
  2357   2357     sqlite3_snapshot_free(pSnapshot);
  2358   2358     return TCL_OK;
  2359   2359   }
  2360   2360   #endif /* SQLITE_ENABLE_SNAPSHOT */
  2361   2361   
         2362  +#ifdef SQLITE_ENABLE_SNAPSHOT
         2363  +/*
         2364  +** Usage: sqlite3_snapshot_cmp SNAPSHOT1 SNAPSHOT2
         2365  +*/
         2366  +static int test_snapshot_cmp(
         2367  +  void * clientData,
         2368  +  Tcl_Interp *interp,
         2369  +  int objc,
         2370  +  Tcl_Obj *CONST objv[]
         2371  +){
         2372  +  int res;
         2373  +  sqlite3_snapshot *p1;
         2374  +  sqlite3_snapshot *p2;
         2375  +  if( objc!=3 ){
         2376  +    Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
         2377  +    return TCL_ERROR;
         2378  +  }
         2379  +  p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
         2380  +  p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2]));
         2381  +  res = sqlite3_snapshot_cmp(p1, p2);
         2382  +  Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
         2383  +  return TCL_OK;
         2384  +}
         2385  +#endif /* SQLITE_ENABLE_SNAPSHOT */
         2386  +
  2362   2387   /*
  2363   2388   ** Usage:  sqlite3_next_stmt  DB  STMT
  2364   2389   **
  2365   2390   ** Return the next statment in sequence after STMT.
  2366   2391   */
  2367   2392   static int test_next_stmt(
  2368   2393     void * clientData,
................................................................................
  7245   7270        { "sqlite3_config_sqllog",         test_config_sqllog,   0 },
  7246   7271   #endif
  7247   7272        { "vfs_current_time_int64",           vfsCurrentTimeInt64,   0 },
  7248   7273   #ifdef SQLITE_ENABLE_SNAPSHOT
  7249   7274        { "sqlite3_snapshot_get", test_snapshot_get, 0 },
  7250   7275        { "sqlite3_snapshot_open", test_snapshot_open, 0 },
  7251   7276        { "sqlite3_snapshot_free", test_snapshot_free, 0 },
         7277  +     { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
  7252   7278   #endif
  7253   7279     };
  7254   7280     static int bitmask_size = sizeof(Bitmask)*8;
  7255   7281     static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  7256   7282     int i;
  7257   7283     extern int sqlite3_sync_count, sqlite3_fullsync_count;
  7258   7284     extern int sqlite3_opentemp_count;

Changes to src/wal.c.

  3395   3395   }
  3396   3396   
  3397   3397   /* Try to open on pSnapshot when the next read-transaction starts
  3398   3398   */
  3399   3399   void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
  3400   3400     pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
  3401   3401   }
         3402  +
         3403  +/* 
         3404  +** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
         3405  +** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
         3406  +*/
         3407  +int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
         3408  +  WalIndexHdr *pHdr1 = (WalIndexHdr*)p1;
         3409  +  WalIndexHdr *pHdr2 = (WalIndexHdr*)p2;
         3410  +
         3411  +  /* aSalt[0] is a copy of the value stored in the wal file header. It
         3412  +  ** is incremented each time the wal file is restarted.  */
         3413  +  if( pHdr1->aSalt[0]<pHdr2->aSalt[0] ) return -1;
         3414  +  if( pHdr1->aSalt[0]>pHdr2->aSalt[0] ) return +1;
         3415  +  if( pHdr1->mxFrame<pHdr2->mxFrame ) return -1;
         3416  +  if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1;
         3417  +  return 0;
         3418  +}
  3402   3419   #endif /* SQLITE_ENABLE_SNAPSHOT */
  3403   3420   
  3404   3421   #ifdef SQLITE_ENABLE_ZIPVFS
  3405   3422   /*
  3406   3423   ** If the argument is not NULL, it points to a Wal object that holds a
  3407   3424   ** read-lock. This function returns the database page-size if it is known,
  3408   3425   ** or zero if it is not (or if pWal is NULL).

Changes to test/snapshot.test.

   360    360     db2 close
   361    361     sqlite3 db2 test.db 
   362    362     db2 eval "BEGIN"
   363    363     list [catch {sqlite3_snapshot_open db2 main $::snapshot} msg] $msg
   364    364   } {1 SQLITE_ERROR}
   365    365   
   366    366   sqlite3_snapshot_free $snapshot
          367  +
          368  +#-------------------------------------------------------------------------
          369  +# The following tests investigate the sqlite3_snapshot_cmp() API.
          370  +#
          371  +catch { db2 close }
          372  +reset_db
          373  +do_execsql_test 7.1 {
          374  +  PRAGMA journal_mode = wal;
          375  +  CREATE TABLE t1(x);
          376  +} wal
          377  +
          378  +do_test 7.1.2 {
          379  +  execsql { BEGIN ; PRAGMA application_id }
          380  +  set p1 [sqlite3_snapshot_get db main]
          381  +  execsql {
          382  +    INSERT INTO t1 VALUES(10);
          383  +    COMMIT;
          384  +  }
          385  +  execsql { BEGIN ; PRAGMA application_id }
          386  +  set p2 [sqlite3_snapshot_get db main]
          387  +  execsql COMMIT
          388  +
          389  +  sqlite3_snapshot_cmp $p1 $p2
          390  +} {-1}
          391  +
          392  +do_test 7.1.3 {
          393  +  sqlite3_snapshot_cmp $p2 $p1
          394  +} {1}
          395  +
          396  +do_test 7.1.4 {
          397  +  list [sqlite3_snapshot_cmp $p1 $p1] [sqlite3_snapshot_cmp $p2 $p2]
          398  +} {0 0}
          399  +sqlite3_snapshot_free $p1
          400  +sqlite3_snapshot_free $p2
   367    401   
   368    402   finish_test