Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Note in the documentation that when iterating through a changeset, all changes to a single table are grouped together. Also add the sqlite3session_isempty() function. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
364f3b820a26f9b15cf74a0222ed5e30 |
User & Date: | dan 2011-07-16 18:05:07.557 |
Context
2011-07-16
| ||
18:35 | Fix error in a comment in sqlite3session.h. No changes to code. (check-in: 70c84e5020 user: dan tags: sessions) | |
18:05 | Note in the documentation that when iterating through a changeset, all changes to a single table are grouped together. Also add the sqlite3session_isempty() function. (check-in: 364f3b820a user: dan tags: sessions) | |
2011-07-15
| ||
19:11 | Add a few casts required by 64-bit VS2010 to the sessions code. (check-in: 5ac4a06111 user: dan tags: sessions) | |
Changes
Changes to ext/session/session1.test.
︙ | ︙ | |||
460 461 462 463 464 465 466 467 468 469 | INSERT INTO aux.t1 VALUES('three', 3); INSERT INTO aux.t1 VALUES('four', 4); } { {INSERT t1 0 X. {} {t two i 2}} {INSERT t1 0 X. {} {t one i 1}} } catch { db2 close } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | INSERT INTO aux.t1 VALUES('three', 3); INSERT INTO aux.t1 VALUES('four', 4); } { {INSERT t1 0 X. {} {t two i 2}} {INSERT t1 0 X. {} {t one i 1}} } #------------------------------------------------------------------------- # Test the sqlite3session_isempty() function. # do_test 8.1 { execsql { CREATE TABLE t5(x PRIMARY KEY, y); CREATE TABLE t6(x PRIMARY KEY, y); INSERT INTO t5 VALUES('a', 'b'); INSERT INTO t6 VALUES('a', 'b'); } sqlite3session S db main S attach * S isempty } {0} do_test 8.2 { execsql { DELETE FROM t5 } S isempty } {1} do_test 8.3 { S delete sqlite3session S db main S attach t5 execsql { DELETE FROM t5 } S isempty } {0} do_test 8.4 { S delete } {} catch { db2 close } finish_test |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 | int ret; sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( bIndirect>=0 ){ pSession->bIndirect = bIndirect; } ret = pSession->bIndirect; 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( | > > > > > > > > > > > > > > > > > | 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 | int ret; sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); if( bIndirect>=0 ){ pSession->bIndirect = bIndirect; } ret = pSession->bIndirect; sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db)); return ret; } /* ** Return true if there have been no changes to monitored tables recorded ** by the session object passed as the only argument. */ int sqlite3session_isempty(sqlite3_session *pSession){ int ret = 0; SessionTable *pTab; sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db)); for(pTab=pSession->pTable; pTab && ret==0; pTab=pTab->pNext){ ret = (pTab->nEntry>0); } 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( |
︙ | ︙ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
250 251 252 253 254 255 256 257 258 259 260 261 262 263 | */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK ** is returned. Otherwise, if an error occurs, *pp is set to zero and an ** SQLite error code is returned. | > > > > > > > > > > > > > > > > > | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Test if a changeset has recorded any changes. ** ** Return non-zero if no changes to attached tables have been recorded by ** the session object passed as the first argument. Otherwise, if one or ** more changes have been recorded, return zero. ** ** Even if this function returns zero, it is possible that calling ** [sqlite3session_changeset()] on the session handle may still return a ** changeset that contains no changes. This can happen when a row in ** an attached table is modified and then later on the original values ** are restored. However, if this function returns non-zero, then it is ** guaranteed that a call to sqlite3session_changeset() will return a ** changeset containing zero changes. */ int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK ** is returned. Otherwise, if an error occurs, *pp is set to zero and an ** SQLite error code is returned. |
︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 285 | ** <li> [sqlite3changeset_old()] ** </ul> ** ** It is the responsibility of the caller to eventually destroy the iterator ** by passing it to [sqlite3changeset_finalize()]. The buffer containing the ** changeset (pChangeset) must remain valid until after the iterator is ** destroyed. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); | > > > > > > > > > | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | ** <li> [sqlite3changeset_old()] ** </ul> ** ** It is the responsibility of the caller to eventually destroy the iterator ** by passing it to [sqlite3changeset_finalize()]. The buffer containing the ** changeset (pChangeset) must remain valid until after the iterator is ** destroyed. ** ** Assuming the changeset blob was created by one of the ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or ** [sqlite3changest_invert()], all changes within the changeset that apply ** to a single table are grouped together. This means that when an application ** iterates through a changeset using an iterator created by this function, ** all changes that relate to a single table are visted consecutively. There ** is no chance that the iterator will visit a change the applies to table X, ** then one for table Y, and then later on visit another change for table X. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); |
︙ | ︙ |
Changes to ext/session/test_session.c.
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | int iSub; } aSub[] = { { "attach", 1, "TABLE", }, /* 0 */ { "changeset", 0, "", }, /* 1 */ { "delete", 0, "", }, /* 2 */ { "enable", 1, "BOOL", }, /* 3 */ { "indirect", 1, "BOOL", }, /* 4 */ { 0 } }; int iSub; int rc; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); | > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | int iSub; } aSub[] = { { "attach", 1, "TABLE", }, /* 0 */ { "changeset", 0, "", }, /* 1 */ { "delete", 0, "", }, /* 2 */ { "enable", 1, "BOOL", }, /* 3 */ { "indirect", 1, "BOOL", }, /* 4 */ { "isempty", 0, "", }, /* 5 */ { 0 } }; int iSub; int rc; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); |
︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 | case 4: { /* indirect */ int val; if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; val = sqlite3session_indirect(pSession, val); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } } return TCL_OK; } static void test_session_del(void *clientData){ sqlite3_session *pSession = (sqlite3_session *)clientData; | > > > > > > > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | case 4: { /* indirect */ int val; if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; val = sqlite3session_indirect(pSession, val); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } case 5: { /* isempty */ int val; val = sqlite3session_isempty(pSession); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; } } return TCL_OK; } static void test_session_del(void *clientData){ sqlite3_session *pSession = (sqlite3_session *)clientData; |
︙ | ︙ |