SQLite

Check-in [e148cdad35]
Login

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

Overview
Comment:Make sure cursors are opened on all indexes for an UPDATE OR REPLACE regardless of whether or not the indexes are partial or contain columns that might need to be updated.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e148cdad35520e6684cfeba23b003f60b55f83a6bf621aff16be8aa5612cdcee
User & Date: drh 2019-01-22 13:45:48.673
Context
2019-01-22
16:06
Enhancements to deserialize: (1) Add the SQLITE_FCNTL_SIZE_LIMIT file control to set a maximum size for an in-memory database, defaulting to SQLITE_MEMDB_DEFAULT_MAXSIZE or 1GiB. (2) Honor the SQLITE_DESERIALIZE_READONLY flag. (3) Enhance the TCL interface to support -maxsize N and -readonly BOOLEAN. (4) Add the --maxsize option to the ".open" command and on the command-line for the CLI. (check-in: 30f08d5888 user: drh tags: trunk)
13:45
Make sure cursors are opened on all indexes for an UPDATE OR REPLACE regardless of whether or not the indexes are partial or contain columns that might need to be updated. (check-in: e148cdad35 user: drh tags: trunk)
12:21
Fix another segfault caused by a corrupt fts3 database. (check-in: ba3b841272 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/update.c.
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

  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);

  /* There is one entry in the aRegIdx[] array for each index on the table
  ** being updated.  Fill in aRegIdx[] with a register number that will hold
  ** the key for accessing each index.
  */

  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
    int reg;
    if( chngKey || hasFK>1 || pIdx==pPk
     || indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
    ){
      reg = ++pParse->nMem;
      pParse->nMem += pIdx->nColumn;
    }else{
      reg = 0;
      for(i=0; i<pIdx->nKeyCol; i++){
        if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
          reg = ++pParse->nMem;
          pParse->nMem += pIdx->nColumn;
          if( (onError==OE_Replace)
           || (onError==OE_Default && pIdx->onError==OE_Replace) 
          ){
            bReplace = 1;
          }
          break;
        }
      }
    }
    if( reg==0 ) aToOpen[j+1] = 0;







>













<
|
<







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

  hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);

  /* There is one entry in the aRegIdx[] array for each index on the table
  ** being updated.  Fill in aRegIdx[] with a register number that will hold
  ** the key for accessing each index.
  */
  if( onError==OE_Replace ) bReplace = 1;
  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
    int reg;
    if( chngKey || hasFK>1 || pIdx==pPk
     || indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
    ){
      reg = ++pParse->nMem;
      pParse->nMem += pIdx->nColumn;
    }else{
      reg = 0;
      for(i=0; i<pIdx->nKeyCol; i++){
        if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
          reg = ++pParse->nMem;
          pParse->nMem += pIdx->nColumn;

          if( onError==OE_Default && pIdx->onError==OE_Replace ){

            bReplace = 1;
          }
          break;
        }
      }
    }
    if( reg==0 ) aToOpen[j+1] = 0;
Changes to test/update2.test.
211
212
213
214
215
216
217
















218
219
do_execsql_test 6.1 {
  UPDATE d1 SET a = a+2 WHERE a>0 OR b>0;
}

do_execsql_test 6.2 {
  SELECT * FROM d1;
} {3 2}

















finish_test







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


211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
do_execsql_test 6.1 {
  UPDATE d1 SET a = a+2 WHERE a>0 OR b>0;
}

do_execsql_test 6.2 {
  SELECT * FROM d1;
} {3 2}

# 2019-01-22 Bug in UPDATE OR REPLACE discovered by the 
# Matt Denton's LPM fuzzer
#
do_execsql_test 7.100 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(x,y);
  CREATE UNIQUE INDEX t1x1 ON t1(x) WHERE x IS NOT NULL;
  INSERT INTO t1(x) VALUES(NULL),(NULL);
  CREATE INDEX t1x2 ON t1(y);
  SELECT quote(x), quote(y), '|' FROM t1;
} {NULL NULL | NULL NULL |}
do_execsql_test 7.110 {
  UPDATE OR REPLACE t1 SET x=1;
  SELECT quote(x), quote(y), '|' FROM t1;
} {1 NULL |}

finish_test