/ Check-in [ad91d300]
Login

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

Overview
Comment:Fix a problem involving session objects and attached databases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: ad91d30073a8faa7eb064dd2e1cc4d2297d7b3f8
User & Date: dan 2011-03-19 19:19:26
Context
2011-03-20
11:20
Documentation format updates to sqlite3session.h. check-in: f227f602 user: dan tags: sessions
2011-03-19
19:19
Fix a problem involving session objects and attached databases. check-in: ad91d300 user: dan tags: sessions
18:46
Fix a bug in changeset generation code. check-in: 825df75b user: dan tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/session/session2.test.

    30     30   
    31     31   proc do_common_sql {sql} {
    32     32     execsql $sql db
    33     33     execsql $sql db2
    34     34   }
    35     35   proc xConflict args { return "OMIT" }
    36     36   
    37         -proc do_then_apply_sql {sql} {
    38         -  sqlite3session S db main
    39         -  db eval {SELECT name FROM sqlite_master WHERE type = 'table'} {
           37  +proc do_then_apply_sql {sql {dbname main}} {
           38  +
           39  +  sqlite3session S db $dbname
           40  +  db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
    40     41       S attach $name
    41     42     }
    42     43   
    43     44     db eval $sql
    44     45     sqlite3changeset_apply db2 [S changeset] xConflict
    45     46     S delete
    46     47   }
................................................................................
   167    168     }
   168    169     10 {
   169    170       BEGIN;
   170    171         DELETE FROM t1 WHERE 1;
   171    172       ROLLBACK;
   172    173     }
   173    174   } {
   174         -if {$tn==9} breakpoint
   175    175     do_then_apply_sql $sql
   176         -  do_test $tn { compare_db db db2 } {}
          176  +  do_test 1.$tn { compare_db db db2 } {}
          177  +}
          178  +
          179  +# The following block of tests is similar to the last, except that the
          180  +# session object is recording changes made to an attached database. The
          181  +# main database contains a table of the same name as the table being
          182  +# modified within the attached db.
          183  +#
          184  +test_reset
          185  +forcedelete test.db3
          186  +sqlite3 db3 test.db3
          187  +do_test 2.0 {
          188  +  execsql {
          189  +    ATTACH 'test.db3' AS 'aux';
          190  +    CREATE TABLE t1(a, b PRIMARY KEY);
          191  +    CREATE TABLE t2(x, y, z);
          192  +    CREATE TABLE t3(a);
          193  +
          194  +    CREATE TABLE aux.t1(a PRIMARY KEY, b);
          195  +    CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
          196  +    CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
          197  +  }
          198  +  execsql {
          199  +    CREATE TABLE t1(a PRIMARY KEY, b);
          200  +    CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
          201  +    CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
          202  +  } db2
          203  +} {}
          204  +
          205  +foreach {tn sql} {
          206  +  1 { INSERT INTO aux.t1 VALUES(1, 2) } 
          207  +
          208  +  2 {
          209  +    INSERT INTO aux.t2 VALUES(1, NULL);
          210  +    INSERT INTO aux.t2 VALUES(2, NULL);
          211  +    INSERT INTO aux.t2 VALUES(3, NULL);
          212  +    DELETE FROM aux.t2 WHERE a = 2;
          213  +    INSERT INTO aux.t2 VALUES(4, NULL);
          214  +    UPDATE aux.t2 SET b=0 WHERE b=1;
          215  +  } 
          216  +
          217  +  3 { INSERT INTO aux.t3 SELECT *, NULL FROM aux.t2 }
          218  +
          219  +  4 {
          220  +    INSERT INTO aux.t3 SELECT a||a, b||b, NULL FROM aux.t3;
          221  +    DELETE FROM aux.t3 WHERE rowid%2;
          222  +  }
          223  +
          224  +  5 { UPDATE aux.t3 SET c = a||b }
          225  +
          226  +  6 { UPDATE aux.t1 SET a = 32 }
          227  +
          228  +  7 { 
          229  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          230  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          231  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          232  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          233  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          234  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          235  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          236  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          237  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          238  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          239  +    INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1; 
          240  +    DELETE FROM aux.t1 WHERE (rowid%3)==0;
          241  +  }
          242  +
          243  +  8 {
          244  +    BEGIN;
          245  +      INSERT INTO aux.t1 SELECT randomblob(32), randomblob(32) FROM aux.t1;
          246  +    ROLLBACK;
          247  +  }
          248  +  9 {
          249  +    BEGIN;
          250  +      UPDATE aux.t1 SET b = 'xxx';
          251  +    ROLLBACK;
          252  +  }
          253  +  10 {
          254  +    BEGIN;
          255  +      DELETE FROM aux.t1 WHERE 1;
          256  +    ROLLBACK;
          257  +  }
          258  +} {
          259  +  do_then_apply_sql $sql aux
          260  +  do_test 2.$tn { compare_db db3 db2 } {}
   177    261   }
   178    262   
          263  +
          264  +catch {db3 close}
          265  +
   179    266   finish_test
   180    267   

Changes to ext/session/sqlite3session.c.

  1187   1187       }
  1188   1188       sqlite3_free(buf2.aBuf);
  1189   1189     }
  1190   1190   }
  1191   1191   
  1192   1192   static int sessionSelectStmt(
  1193   1193     sqlite3 *db,                    /* Database handle */
         1194  +  const char *zDb,                /* Database name */
  1194   1195     const char *zTab,               /* Table name */
  1195   1196     int nCol,
  1196   1197     const char **azCol,
  1197   1198     u8 *abPK,
  1198   1199     sqlite3_stmt **ppStmt
  1199   1200   ){
  1200   1201     int rc = SQLITE_OK;
  1201   1202     int i;
  1202   1203     const char *zSep = "";
  1203   1204     SessionBuffer buf = {0, 0, 0};
  1204   1205   
  1205   1206     sessionAppendStr(&buf, "SELECT * FROM ", &rc);
         1207  +  sessionAppendIdent(&buf, zDb, &rc);
         1208  +  sessionAppendStr(&buf, ".", &rc);
  1206   1209     sessionAppendIdent(&buf, zTab, &rc);
  1207   1210     sessionAppendStr(&buf, " WHERE ", &rc);
  1208   1211     for(i=0; i<nCol; i++){
  1209   1212       if( abPK[i] ){
  1210   1213         sessionAppendStr(&buf, zSep, &rc);
  1211   1214         sessionAppendIdent(&buf, azCol[i], &rc);
  1212   1215         sessionAppendStr(&buf, " = ?", &rc);
................................................................................
  1309   1312     ** this call will be a no-op.  */
  1310   1313     *pnChangeset = 0;
  1311   1314     *ppChangeset = 0;
  1312   1315     rc = pSession->rc;
  1313   1316   
  1314   1317     for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
  1315   1318       if( pTab->nEntry ){
         1319  +      const char *zName = pTab->zName;
  1316   1320         int nCol = pTab->nCol;      /* Local copy of member variable */
  1317   1321         u8 *abPK = pTab->abPK;      /* Local copy of member variable */
  1318   1322         int i;                      /* Used to iterate through hash buckets */
  1319   1323         sqlite3_stmt *pSel = 0;     /* SELECT statement to query table pTab */
  1320   1324         int nRewind = buf.nBuf;     /* Initial size of write buffer */
  1321   1325         int nNoop;                  /* Size of buffer after writing tbl header */
  1322   1326   
  1323   1327         /* Write a table header */
  1324   1328         sessionAppendByte(&buf, 'T', &rc);
  1325   1329         sessionAppendVarint(&buf, nCol, &rc);
  1326         -      sessionAppendBlob(&buf, (u8 *)pTab->zName, strlen(pTab->zName)+1, &rc);
         1330  +      sessionAppendBlob(&buf, (u8 *)zName, strlen(zName)+1, &rc);
  1327   1331   
  1328   1332         /* Build and compile a statement to execute: */
  1329   1333         if( rc==SQLITE_OK ){
  1330         -        rc = sessionSelectStmt(db, pTab->zName, nCol, pTab->azCol, abPK, &pSel);
         1334  +        rc = sessionSelectStmt(
         1335  +            db, pSession->zDb, zName, nCol, pTab->azCol, abPK, &pSel);
  1331   1336         }
  1332   1337   
  1333   1338         if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){
  1334   1339           rc = SQLITE_SCHEMA;
  1335   1340         }
  1336   1341   
  1337   1342         nNoop = buf.nBuf;
................................................................................
  1938   1943   ** pointing to the prepared version of the SQL statement.
  1939   1944   */
  1940   1945   static int sessionSelectRow(
  1941   1946     sqlite3 *db,                    /* Database handle */
  1942   1947     const char *zTab,               /* Table name */
  1943   1948     SessionApplyCtx *p              /* Session changeset-apply context */
  1944   1949   ){
  1945         -  return sessionSelectStmt(db, zTab, p->nCol, p->azCol, p->abPK, &p->pSelect);
         1950  +  return sessionSelectStmt(
         1951  +      db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect);
  1946   1952   }
  1947   1953   
  1948   1954   /*
  1949   1955   ** Formulate and prepare an INSERT statement to add a record to table zTab.
  1950   1956   ** For example:
  1951   1957   **
  1952   1958   **     INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...);