/ Check-in [c6239bf9]
Login

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

Overview
Comment:Change the code generator for UPDATE to generate code in an order that might run more efficiently in many cases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | improved-update
Files: files | file ages | folders
SHA1:c6239bf943fc42b8fc1ece95c9268240b7c53e80
User & Date: drh 2015-10-17 01:00:03
Context
2015-10-17
01:00
Change the code generator for UPDATE to generate code in an order that might run more efficiently in many cases. Leaf check-in: c6239bf9 user: drh tags: improved-update
2015-10-16
23:55
Fix a comment in expr.c and add a CORRUPT_DB to an assert() in btree.c. check-in: 0df371d1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/update.c.

492
493
494
495
496
497
498







499
500
501
502
503
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528




529
530
531
532
533
534
535
  }

  /* Populate the array of registers beginning at regNew with the new
  ** row data. This array is used to check constants, create the new
  ** table and index records, and as the values for any new.* references
  ** made by triggers.
  **







  ** If there are one or more BEFORE triggers, then do not populate the
  ** registers associated with columns that are (a) not modified by
  ** this UPDATE statement and (b) not accessed by new.* references. The
  ** values for registers not modified by the UPDATE must be reloaded from 
  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  for(i=0; i<pTab->nCol; i++){

    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
    }else{
      j = aXRef[i];
      if( j>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
        /* This branch loads the value of a column that will not be changed 
        ** into a register. This is done if there are no BEFORE triggers, or
        ** if there are one or more BEFORE triggers that use this value via
        ** a new.* reference in a trigger program.
        */

        testcase( i==31 );
        testcase( i==32 );
        sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
      }




    }
  }

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){







>
>
>
>
>
>
>











|
>
|
<
<
<
<
<
|
<
<
<
<
<
>
|
|
|
|
|
|
>
>
>
>







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519





520





521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  }

  /* Populate the array of registers beginning at regNew with the new
  ** row data. This array is used to check constants, create the new
  ** table and index records, and as the values for any new.* references
  ** made by triggers.
  **
  ** As an optimization, the array is loaded in two passes.  The first pass
  ** loads unchanged values using OP_Column opcodes so that they can be
  ** cached and potentially reused by subsequent expressions.  Also, the
  ** OP_Columns are loaded in reverse order so that the row type/offset cache
  ** inside the OP_Column implementation in the VDBE will warm up completely
  ** on the first opcode, rather than incrementally across each opcode.
  **
  ** If there are one or more BEFORE triggers, then do not populate the
  ** registers associated with columns that are (a) not modified by
  ** this UPDATE statement and (b) not accessed by new.* references. The
  ** values for registers not modified by the UPDATE must be reloaded from 
  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  for(i=pTab->nCol-1; i>=0; i--){
    if( aXRef[i]>=0 && i!=pTab->iPKey ) continue;
    if( i!=pTab->iPKey





     && (0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i))!=0)





    ){
      testcase( i==31 );
      testcase( i==32 );
      sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
    }else{
      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
    }  
  }
  for(i=0; i<pTab->nCol; i++){
    if( (j = aXRef[i])>=0 && i!=pTab->iPKey ){
      sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
    }
  }

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){