SQLite

Check-in [6e5907e14d]
Login

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

Overview
Comment:Fix a problem with resizing a hash table in sqlite3session.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 6e5907e14d3316d56313243c4f8ce8f14d0858fc
User & Date: dan 2011-03-19 16:26:12.000
Context
2011-03-19
17:07
Move session1.test from test/ to ext/session/. (check-in: c4436a936a user: dan tags: sessions)
16:26
Fix a problem with resizing a hash table in sqlite3session.c. (check-in: 6e5907e14d user: dan tags: sessions)
15:37
Fix some bugs in sqlite3changeset_apply(). (check-in: 7250318dda user: dan tags: sessions)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to ext/session/session2.test.
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124

125

126
127
128
129

130

131
















132
133
134
135
136
137
138
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
}

foreach {tn sql} {
  1 { INSERT INTO t1 VALUES(1, 2) } 

  2 {
    INSERT INTO t2 VALUES(1, NULL);
    INSERT INTO t2 VALUES(2, NULL);
    INSERT INTO t2 VALUES(3, NULL);
    DELETE FROM t2 WHERE a = 2;
    INSERT INTO t2 VALUES(4, NULL);
    UPDATE t2 SET b=0 WHERE b=1;
  } 

  3 { INSERT INTO t3 SELECT *, NULL FROM t2 }

  4 {
    INSERT INTO t3 SELECT a||a, b||b, NULL FROM t3;
    DELETE FROM t3 WHERE rowid%2;
  }

  5 { UPDATE t3 SET c = a||b }

  6 { UPDATE t1 SET a = 32 }
















} {
  do_then_apply_sql $sql
  do_test $tn { compare_db db db2 } {}
}

finish_test








>








>

>




>

>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
}

foreach {tn sql} {
  1 { INSERT INTO t1 VALUES(1, 2) } 

  2 {
    INSERT INTO t2 VALUES(1, NULL);
    INSERT INTO t2 VALUES(2, NULL);
    INSERT INTO t2 VALUES(3, NULL);
    DELETE FROM t2 WHERE a = 2;
    INSERT INTO t2 VALUES(4, NULL);
    UPDATE t2 SET b=0 WHERE b=1;
  } 

  3 { INSERT INTO t3 SELECT *, NULL FROM t2 }

  4 {
    INSERT INTO t3 SELECT a||a, b||b, NULL FROM t3;
    DELETE FROM t3 WHERE rowid%2;
  }

  5 { UPDATE t3 SET c = a||b }

  6 { UPDATE t1 SET a = 32 }

  7 { 
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --    2
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --    4
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --    8
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --   16
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --   32
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --   64
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --  128
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --  256
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; --  512
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 1024
    INSERT INTO t1 SELECT randomblob(32), randomblob(32) FROM t1; -- 2048
    DELETE FROM t1 WHERE (rowid%3)==0;
  }

} {
  do_then_apply_sql $sql
  do_test $tn { compare_db db db2 } {}
}

finish_test

Changes to ext/session/sqlite3session.c.
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
    }
  }

  *pnWrite += nByte;
  return SQLITE_OK;
}

#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (int)(add)
static int sessionHashAppendI64(int h, i64 i){
  h = HASH_APPEND(h, i & 0xFFFFFFFF);
  return HASH_APPEND(h, (i>>32)&0xFFFFFFFF);
}
static int sessionHashAppendBlob(int h, int n, const u8 *z){
  int i;
  for(i=0; i<n; i++) h = HASH_APPEND(h, z[i]);
  return h;
}

/*

** This function calculates a hash based on the primary key values of
** the old.* or new.* row currently available.

*/
static int sessionPreupdateHash(
  sqlite3 *db,                    /* Database handle */
  SessionTable *pTab,             /* Session table handle */
  int bNew,                       /* True to hash the new.* PK */
  int *piHash                     /* OUT: Hash value */
){
  int h = 0;
  int i;

  assert( pTab->nCol==sqlite3_preupdate_count(db) );
  for(i=0; i<pTab->nCol; i++){
    if( pTab->abPK[i] ){
      int rc;
      int eType;
      sqlite3_value *pVal;







|
|



|






>
|
|
>

|





|
|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    }
  }

  *pnWrite += nByte;
  return SQLITE_OK;
}

#define HASH_APPEND(hash, add) ((hash) << 3) ^ (hash) ^ (unsigned int)(add)
static unsigned int sessionHashAppendI64(unsigned int h, i64 i){
  h = HASH_APPEND(h, i & 0xFFFFFFFF);
  return HASH_APPEND(h, (i>>32)&0xFFFFFFFF);
}
static unsigned int sessionHashAppendBlob(unsigned int h, int n, const u8 *z){
  int i;
  for(i=0; i<n; i++) h = HASH_APPEND(h, z[i]);
  return h;
}

/*
** This function may only be called from within a pre-update callback.
** It calculates a hash based on the primary key values of the old.* or 
** new.* row currently available. The value returned is guaranteed to
** be less than pTab->nBucket.
*/
static unsigned int sessionPreupdateHash(
  sqlite3 *db,                    /* Database handle */
  SessionTable *pTab,             /* Session table handle */
  int bNew,                       /* True to hash the new.* PK */
  int *piHash                     /* OUT: Hash value */
){
  unsigned int h = 0;             /* Hash value to return */
  int i;                          /* Used to iterate through columns */

  assert( pTab->nCol==sqlite3_preupdate_count(db) );
  for(i=0; i<pTab->nCol; i++){
    if( pTab->abPK[i] ){
      int rc;
      int eType;
      sqlite3_value *pVal;
331
332
333
334
335
336
337






338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    }
  }

  *piHash = (h % pTab->nChange);
  return SQLITE_OK;
}







static int sessionChangeHash(
  sqlite3 *db,
  SessionTable *pTab,
  SessionChange *pChange,
  int nBucket
){
  int h = 0;
  int i;
  u8 *a = pChange->aRecord;

  for(i=0; i<pTab->nCol; i++){
    int eType = *a++;
    int isPK = pTab->abPK[i];

    if( isPK ) h = HASH_APPEND(h, eType);
    switch( eType ){







>
>
>
>
>
>
|
|
|
|
|

|
|
|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
    }
  }

  *piHash = (h % pTab->nChange);
  return SQLITE_OK;
}

/*
** Based on the primary key values stored in change pChange, 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(
  sqlite3 *db,                    /* Database handle */
  SessionTable *pTab,             /* Table handle */
  SessionChange *pChange,         /* Change handle */
  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 = pChange->aRecord;       /* Used to iterate through change record */

  for(i=0; i<pTab->nCol; i++){
    int eType = *a++;
    int isPK = pTab->abPK[i];

    if( isPK ) h = HASH_APPEND(h, eType);
    switch( eType ){