Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add further tests for the sqlite3changeset_concat() function. Also fixes. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
1fc3f15d88c160b45642b46d1d54c591 |
User & Date: | dan 2011-04-14 18:01:41.789 |
Context
2011-04-15
| ||
12:04 | Add documentation for sqlite3changeset_concat() to sqlite3session.h. (check-in: ada9efa53a user: dan tags: sessions) | |
2011-04-14
| ||
18:01 | Add further tests for the sqlite3changeset_concat() function. Also fixes. (check-in: 1fc3f15d88 user: dan tags: sessions) | |
11:16 | Start adding the sqlite3changeset_concat() function to the session module. (check-in: 8927b2260b user: dan tags: sessions) | |
Changes
Changes to ext/session/session5.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 | } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix session5 | | > > > > | > | | | | | > > | | > > > > > | > | > > > | > | < | | | < < < < < > | | > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix session5 # Organization of tests: # # session5-1.*: Simple tests to check the concat() function produces # correct results. # # session5-2.*: More complicated tests. # # session5-3.*: Schema mismatch errors. # proc changeset_to_list {c} { set list [list] sqlite3session_foreach elem $c { lappend list $elem } lsort $list } proc do_concat_test {tn args} { set subtest 0 foreach sql $args { incr subtest sqlite3session S db main ; S attach * execsql $sql set c [S changeset] if {[info commands s_prev] != ""} { set c_concat [sqlite3changeset_concat $c_prev $c] set c_two [s_prev changeset] s_prev delete set h_concat [changeset_to_list $c_concat] set h_two [changeset_to_list $c_two] do_test $tn.$subtest [list set {} $h_concat] $h_two } set c_prev $c rename S s_prev } catch { s_prev delete } } do_execsql_test 1.0 { CREATE TABLE t1(a PRIMARY KEY, b); } do_concat_test 1.1.1 { |
︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 | UPDATE t1 SET b = 'seven' WHERE a = 'I'; } do_concat_test 1.2.7 { UPDATE t1 SET b = 'eight' WHERE a = 'I'; } { DELETE FROM t1 WHERE a = 'I'; } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | UPDATE t1 SET b = 'seven' WHERE a = 'I'; } do_concat_test 1.2.7 { UPDATE t1 SET b = 'eight' WHERE a = 'I'; } { DELETE FROM t1 WHERE a = 'I'; } db function indirect indirect proc indirect {{x -1}} { S indirect $x s_prev indirect $x } do_concat_test 2.1 { CREATE TABLE abc(a, b, c PRIMARY KEY); INSERT INTO abc VALUES(NULL, NULL, 1); INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); } { DELETE FROM abc WHERE c = 1; UPDATE abc SET c = 1 WHERE c = 2; } { INSERT INTO abc VALUES('abcdefghijkl', NULL, 2); INSERT INTO abc VALUES(1.0, 2.0, 3); } { UPDATE abc SET a = a-1; } { CREATE TABLE def(d, e, f, PRIMARY KEY(e, f)); INSERT INTO def VALUES('x', randomblob(11000), 67); INSERT INTO def SELECT d, e, f+1 FROM def; INSERT INTO def SELECT d, e, f+2 FROM def; INSERT INTO def SELECT d, e, f+4 FROM def; } { DELETE FROM def WHERE rowid>4; } { INSERT INTO def SELECT d, e, f+4 FROM def; } { INSERT INTO abc VALUES(22, 44, -1); } { UPDATE abc SET c=-2 WHERE c=-1; UPDATE abc SET c=-3 WHERE c=-2; } { UPDATE abc SET c=-4 WHERE c=-3; } { UPDATE abc SET a=a+1 WHERE c=-3; UPDATE abc SET a=a+1 WHERE c=-3; } { UPDATE abc SET a=a+1 WHERE c=-3; UPDATE abc SET a=a+1 WHERE c=-3; } { INSERT INTO abc VALUES('one', 'two', 'three'); } { SELECT indirect(1); UPDATE abc SET a='one point five' WHERE c = 'three'; } { SELECT indirect(0); UPDATE abc SET a='one point six' WHERE c = 'three'; } finish_test |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | } } } *piHash = (h % pTab->nChange); return SQLITE_OK; } /* ** Based on the primary key values stored in change aRecord, calculate a ** hash key, assuming the has table has nBucket buckets. The hash keys ** calculated by this function are compatible with those calculated by ** sessionPreupdateHash(). */ static unsigned int sessionChangeHash( SessionTable *pTab, /* Table handle */ u8 *aRecord, /* Change record */ int nBucket /* Assume this many buckets in hash table */ ){ unsigned int h = 0; /* Value to return */ int i; /* Used to iterate through columns */ u8 *a = aRecord; /* Used to iterate through change record */ for(i=0; i<pTab->nCol; i++){ | > > > > > > > > > > > > > > | > > > > | | | | | | | | | > > > < < < < < < < < < | | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | } } } *piHash = (h % pTab->nChange); return SQLITE_OK; } /* ** The buffer that the argument points to contains a serialized SQL value. ** Return the number of bytes of space occupied by the value (including ** the type byte). */ static int sessionSerialLen(u8 *a){ int e = *a; int n; if( e==0 ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; return sessionVarintGet(&a[1], &n) + 1 + n; } /* ** Based on the primary key values stored in change aRecord, calculate a ** hash key, assuming the has table has nBucket buckets. The hash keys ** calculated by this function are compatible with those calculated by ** sessionPreupdateHash(). */ static unsigned int sessionChangeHash( SessionTable *pTab, /* Table handle */ u8 *aRecord, /* Change record */ int nBucket /* Assume this many buckets in hash table */ ){ unsigned int h = 0; /* Value to return */ int i; /* Used to iterate through columns */ u8 *a = aRecord; /* Used to iterate through change record */ for(i=0; i<pTab->nCol; i++){ int eType = *a; int isPK = pTab->abPK[i]; /* It is not possible for eType to be SQLITE_NULL here. The session ** module does not record changes for rows with NULL values stored in ** primary key columns. */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT || eType==SQLITE_TEXT || eType==SQLITE_BLOB || eType==SQLITE_NULL || eType==0 ); assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); if( isPK ){ a++; h = HASH_APPEND(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; }else{ int n; a += sessionVarintGet(a, &n); if( isPK ) h = sessionHashAppendBlob(h, n, a); a += n; } }else{ a += sessionSerialLen(a); } } return (h % nBucket); } static int sessionChangeEqual( SessionTable *pTab, u8 *aLeft, /* Change record */ u8 *aRight /* Change record */ ){ u8 *a1 = aLeft; u8 *a2 = aRight; int i; for(i=0; i<pTab->nCol; i++){ int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); if( pTab->abPK[i] && (n1!=n2 || memcmp(a1, a2, n1)) ){ return 0; } a1 += n1; a2 += n2; } return 1; } static void sessionMergeRecord( u8 **paOut, |
︙ | ︙ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
518 519 520 521 522 523 524 525 | ** changeset. If it is not, the results are undefined. */ int sqlite3changeset_invert( int nIn, void *pIn, /* Input changeset */ int *pnOut, void **ppOut /* OUT: Inverse of input */ ); int sqlite3changeset_concat( | > > > | | | | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | ** changeset. If it is not, the results are undefined. */ int sqlite3changeset_invert( int nIn, void *pIn, /* Input changeset */ int *pnOut, void **ppOut /* OUT: Inverse of input */ ); /* ** CAPI3REF: Combine Two Changeset Objects */ int sqlite3changeset_concat( int nLeft, void *pLeft, /* First input changeset */ int nRight, void *Right, /* Second input changeset */ int *pnOut, void **ppOut /* OUT: Output changeset */ ); /* ** CAPI3REF: Apply A Changeset To A Database ** ** Apply a changeset to a database. This function attempts to update the ** "main" database attached to handle db with the changes found in the |
︙ | ︙ |