SQLite4
Check-in [69cf7caf80]
Not logged in

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

Overview
Comment:Fixes to foreign key logic. And other things.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | primary-keys
Files: files | file ages | folders
SHA1: 69cf7caf80f1b55fa708147a2912d1246f9dee37
User & Date: dan 2012-04-14 19:38:34
Context
2012-04-16
19:04
Get most of the trigger logic working again. Still some problems. check-in: b480943c48 user: dan tags: primary-keys
2012-04-14
19:38
Fixes to foreign key logic. And other things. check-in: 69cf7caf80 user: dan tags: primary-keys
2012-04-13
19:17
Fix sub-transaction commit in kvmem.c. Also various aspects of constraint handling. check-in: 365eb3c6de user: dan tags: primary-keys
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

331
332
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
...
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491

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
539
540
541
542
543
544
545
546
547
...
549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
564
565
566
567
568
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pParse;
  sNC.pSrcList = pTabList;
  if( sqlite4ResolveExprNames(&sNC, pWhere) ){
    goto delete_from_cleanup;
  }

  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( db->flags & SQLITE_CountRows ){
    memCnt = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, memCnt);
  }

#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to erase the whole table. Prior to version 3.6.5,
  ** this optimization caused the row change count (the value returned by 
  ** API function sqlite4_count_changes) to be set incorrectly.  */
  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   && 0==sqlite4FkRequired(pParse, pTab, 0, 0)
  ){
    assert( !isView );
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      sqlite4VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
    }
  }else
................................................................................
  int baseCur,                    /* Base cursor number */
  int regKey,                     /* Register containing PK of row to delete */
  int bCount,                     /* True to increment the row change counter */
  Trigger *pTrigger,              /* List of triggers to (potentially) fire */
  int onconf                      /* Default ON CONFLICT policy for triggers */
){
  Vdbe *v = pParse->pVdbe;        /* Vdbe */
  int iOld = 0;                   /* First register in OLD.* array */
  int iLabel;                     /* Label resolved to end of generated code */
  int iPk;


  /* Vdbe is guaranteed to have been allocated by this stage. */
  assert( v );

  sqlite4FindPrimaryKey(pTab, &iPk);


  /* Seek cursor iCur to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite4VdbeMakeLabel(v);
  sqlite4VdbeAddOp4(v, OP_NotFound, baseCur+iPk, iLabel, regKey, 0, P4_INT32);
 
  /* If there are any triggers to fire, allocate a range of registers to
  ** use for the old.* references in the triggers.  */
#if 0
  if( sqlite4FkRequired(pParse, pTab, 0, 0) || pTrigger ){
    u32 mask;                     /* Mask of OLD.* columns in use */
    int iCol;                     /* Iterator used while populating OLD.* */

    /* TODO: Could use temporary registers here. Also could attempt to
    ** avoid copying the contents of the rowid register.  */






    mask = sqlite4TriggerColmask(
        pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
    );
    mask |= sqlite4FkOldmask(pParse, pTab);
    iOld = pParse->nMem+1;
    pParse->nMem += (1 + pTab->nCol);

    /* Populate the OLD.* pseudo-table register array. These values will be 
    ** used by any BEFORE and AFTER triggers that exist.  */
    sqlite4VdbeAddOp2(v, OP_Copy, iRowid, iOld);
    for(iCol=0; iCol<pTab->nCol; iCol++){
      if( mask==0xffffffff || mask&(1<<iCol) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
      }
    }

    /* Invoke BEFORE DELETE trigger programs. */
    sqlite4CodeRowTrigger(pParse, pTrigger, 
        TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
    );

    /* Seek the cursor to the row to be deleted again. It may be that
    ** the BEFORE triggers coded above have already removed the row
    ** being deleted. Do not attempt to delete the row a second time, and 
    ** do not fire AFTER triggers.  */
    sqlite4VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);

    /* Do FK processing. This call checks that any FK constraints that
    ** refer to this table (i.e. constraints attached to other tables) 
    ** are not violated by deleting this row.  */
    sqlite4FkCheck(pParse, pTab, iOld, 0);
  }
#endif

  /* Delete the index and table entries. Skip this step if pTab is really
  ** a view (in which case the only effect of the DELETE statement is to
  ** fire the INSTEAD OF triggers).  */ 
  if( pTab->pSelect==0 ){
    sqlite4GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
#if 0
................................................................................
      sqlite4VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
    }
#endif
  }

  /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
  ** handle rows (possibly in other tables) that refer via a foreign key
  ** to the row just deleted. */ 

  sqlite4FkActions(pParse, pTab, 0, iOld);

  /* Invoke AFTER DELETE trigger programs. */
  sqlite4CodeRowTrigger(pParse, pTrigger, 
      TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
  );

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite4VdbeResolveLabel(v, iLabel);
}







<
<
<
<
<
<
<
<






|







 







|


>





>

|



|



<
|



|
|
>
>
>
>
>
>




|
|
|
|
|
|
|
|
|





|






|




|

<







 







|
>
|



|







331
332
333
334
335
336
337








338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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

539
540
541
542
543
544
545
...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pParse;
  sNC.pSrcList = pTabList;
  if( sqlite4ResolveExprNames(&sNC, pWhere) ){
    goto delete_from_cleanup;
  }









#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to erase the whole table. Prior to version 3.6.5,
  ** this optimization caused the row change count (the value returned by 
  ** API function sqlite4_count_changes) to be set incorrectly.  */
  if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   && 0==sqlite4FkRequired(pParse, pTab, 0)
  ){
    assert( !isView );
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      sqlite4VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
    }
  }else
................................................................................
  int baseCur,                    /* Base cursor number */
  int regKey,                     /* Register containing PK of row to delete */
  int bCount,                     /* True to increment the row change counter */
  Trigger *pTrigger,              /* List of triggers to (potentially) fire */
  int onconf                      /* Default ON CONFLICT policy for triggers */
){
  Vdbe *v = pParse->pVdbe;        /* Vdbe */
  int regOld = 0;                 /* First register in OLD.* array */
  int iLabel;                     /* Label resolved to end of generated code */
  int iPk;
  int iPkCsr;                     /* Primary key cursor number */

  /* Vdbe is guaranteed to have been allocated by this stage. */
  assert( v );

  sqlite4FindPrimaryKey(pTab, &iPk);
  iPkCsr = baseCur + iPk;

  /* Seek the PK cursor to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite4VdbeMakeLabel(v);
  sqlite4VdbeAddOp4Int(v, OP_NotFound, iPkCsr, iLabel, regKey, 0);
 
  /* If there are any triggers to fire, allocate a range of registers to
  ** use for the old.* references in the triggers.  */

  if( sqlite4FkRequired(pParse, pTab, 0) || pTrigger ){
    u32 mask;                     /* Mask of OLD.* columns in use */
    int iCol;                     /* Iterator used while populating OLD.* */

    /* Determine which table columns may be required by either foreign key
    ** logic or triggers. This block sets stack variable mask to a 32-bit mask
    ** where bit 0 corresponds to the left-most table column, bit 1 to the
    ** second left-most, and so on. If an OLD.* column may be required, then
    ** the corresponding bit is set.
    **
    ** Or, if the table contains more than 32 columns and at least one of
    ** the columns following the 32nd is required, set mask to 0xffffffff.  */
    mask = sqlite4TriggerColmask(
        pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
    );
    mask |= sqlite4FkOldmask(pParse, pTab);

    /* Allocate an array of registers - one for each column in the table.
    ** Then populate those array elements that may be used by FK or trigger
    ** logic with the OLD.* values.  */
    regOld = pParse->nMem+1;
    pParse->nMem += pTab->nCol;
    for(iCol=0; iCol<pTab->nCol; iCol++){
      if( mask==0xffffffff || mask&(1<<iCol) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iPkCsr, iCol, regOld+iCol);
      }
    }

    /* Invoke BEFORE DELETE trigger programs. */
    sqlite4CodeRowTrigger(pParse, pTrigger, 
        TK_DELETE, 0, TRIGGER_BEFORE, pTab, regOld, onconf, iLabel
    );

    /* Seek the cursor to the row to be deleted again. It may be that
    ** the BEFORE triggers coded above have already removed the row
    ** being deleted. Do not attempt to delete the row a second time, and 
    ** do not fire AFTER triggers.  */
    sqlite4VdbeAddOp4Int(v, OP_NotFound, iPkCsr, iLabel, regKey, 0);

    /* Do FK processing. This call checks that any FK constraints that
    ** refer to this table (i.e. constraints attached to other tables) 
    ** are not violated by deleting this row.  */
    sqlite4FkCheck(pParse, pTab, regOld, 0);
  }


  /* Delete the index and table entries. Skip this step if pTab is really
  ** a view (in which case the only effect of the DELETE statement is to
  ** fire the INSTEAD OF triggers).  */ 
  if( pTab->pSelect==0 ){
    sqlite4GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
#if 0
................................................................................
      sqlite4VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
    }
#endif
  }

  /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
  ** handle rows (possibly in other tables) that refer via a foreign key
  ** to the row just deleted. This is a no-op if there are no configured
  ** foreign keys that use this table as a parent table.  */ 
  sqlite4FkActions(pParse, pTab, 0, regOld);

  /* Invoke AFTER DELETE trigger programs. */
  sqlite4CodeRowTrigger(pParse, pTrigger, 
      TK_DELETE, 0, TRIGGER_AFTER, pTab, regOld, onconf, iLabel
  );

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite4VdbeResolveLabel(v, iLabel);
}

Changes to src/fkey.c.

329
330
331
332
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
362
363
364
365
366

367
368
369

370
371
372
373
374
375
376
...
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
...
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  if( isIgnore==0 ){
    int nCol = pFKey->nCol;
    int regTemp = sqlite4GetTempRange(pParse, nCol);
    int regRec = sqlite4GetTempReg(pParse);

    sqlite4OpenIndex(pParse, iCur, iDb, pIdx, OP_OpenRead);

    /* Assemble the child key values in a contiguous array of registers */

    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Copy, aiCol[i]+regContent, regTemp+i);
    }



    /* If the parent table is the same as the child table, and we are about
    ** to increment the constraint-counter (i.e. this is an INSERT operation),
    ** then check if the row being inserted matches itself. If so, do not
    ** increment the constraint-counter. 
    **
    ** If any of the parent-key values are NULL, then the row cannot match 
    ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
    ** of the parent-key values are NULL (at this point it is known that
    ** none of the child key values are).  */
    if( pTab==pFKey->pFrom && nIncr==1 ){
      int iJump = sqlite4VdbeCurrentAddr(v) + nCol + 1;
      for(i=0; i<nCol; i++){
        int iChild = aiCol[i]+regContent;
        int iParent = pIdx->aiColumn[i]+regContent;
        sqlite4VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
        sqlite4VdbeChangeP5(v, SQLITE_JUMPIFNULL);

      }
      sqlite4VdbeAddOp2(v, OP_Goto, 0, iOk);
    }

    /* FIXME: Affinities... */
    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iCur, regTemp, regRec);
    /* sqlite4VdbeChangeP5(v, 1); */

    sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);


    sqlite4VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
    sqlite4VdbeChangeP4(v, -1, sqlite4IndexAffinityStr(v,pIdx), P4_TRANSIENT);
    sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);


    sqlite4ReleaseTempReg(pParse, regRec);
    sqlite4ReleaseTempRange(pParse, regTemp, nCol);
  }

  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
    /* Special case: If this is an INSERT statement that will insert exactly
................................................................................
  }

  sqlite4VdbeResolveLabel(v, iOk);
  sqlite4VdbeAddOp1(v, OP_Close, iCur);
}

/*
** This function is called to generate code executed when a row is deleted
** from the parent table of foreign key constraint pFKey and, if pFKey is 
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.

**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
................................................................................
  int i;                          /* Iterator variable */
  Expr *pWhere = 0;               /* WHERE clause to scan with */
  NameContext sNameContext;       /* Context used to resolve WHERE clause */
  WhereInfo *pWInfo;              /* Context used by sqlite4WhereXXX() */
  int iFkIfZero = 0;              /* Address of OP_FkIfZero */
  Vdbe *v = sqlite4GetVdbe(pParse);

  assert( !pIdx || pIdx->pTable==pTab );

  if( nIncr<0 ){
    iFkIfZero = sqlite4VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
  }

  /* Create an Expr object representing an SQL expression like:
  **
................................................................................
    int iCol;                     /* Index of column in child table */ 
    const char *zCol;             /* Name of column in child table */

    pLeft = sqlite4Expr(db, TK_REGISTER, 0);
    if( pLeft ){
      /* Set the collation sequence and affinity of the LHS of each TK_EQ
      ** expression to the parent key column defaults.  */
      if( pIdx ){
        Column *pCol;
        iCol = pIdx->aiColumn[i];
        pCol = &pTab->aCol[iCol];
        pLeft->iTable = regData+iCol+1;
        pLeft->affinity = pCol->affinity;
        pLeft->pColl = sqlite4LocateCollSeq(pParse, pCol->zColl);
      }else{
        pLeft->iTable = regData;
        pLeft->affinity = SQLITE_AFF_INTEGER;
      }
    }
    iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
    assert( iCol>=0 );
    zCol = pFKey->pFrom->aCol[iCol].zName;
    pRight = sqlite4Expr(db, TK_ID, zCol);
    pEq = sqlite4PExpr(pParse, TK_EQ, pLeft, pRight, 0);
    pWhere = sqlite4ExprAnd(db, pWhere, pEq);
................................................................................
  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite4ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. If the constraint is not deferred, throw an exception for
  ** each row found. Otherwise, for deferred constraints, increment the
  ** deferred constraint counter by nIncr for each row selected.  */
  pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite4ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite4WhereEnd(pWInfo);
................................................................................
  }
}

#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))

/*
** This function is called before generating code to update or delete a 
** row contained in table pTab.
*/
u32 sqlite4FkOldmask(
  Parse *pParse,                  /* Parse context */
  Table *pTab                     /* Table being modified */
){
  u32 mask = 0;
  if( pParse->db->flags&SQLITE_ForeignKeys ){
................................................................................
** If any foreign key processing will be required, this function returns
** true. If there is no foreign key related processing, this function 
** returns false.
*/
int sqlite4FkRequired(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being modified */
  int *aChange,                   /* Non-NULL for UPDATE operations */
  int chngRowid                   /* True for UPDATE that affects rowid */
){
  if( pParse->db->flags&SQLITE_ForeignKeys ){
    if( !aChange ){
      /* A DELETE operation. Foreign key processing is required if the 
      ** table in question is either the child or parent table for any 
      ** foreign key constraint.  */
      return (sqlite4FkReferences(pTab) || pTab->pFKey);







|
>



>
>













|



>




<

|
<


>



>







 







|
|
<
|
|
>







 







|







 







<
|
|
|
|
|
|
<
<
<
<







 







|
|
<







 







|







 







|
<







329
330
331
332
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
362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
...
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
...
463
464
465
466
467
468
469

470
471
472
473
474
475




476
477
478
479
480
481
482
...
505
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
...
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
...
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
  if( isIgnore==0 ){
    int nCol = pFKey->nCol;
    int regTemp = sqlite4GetTempRange(pParse, nCol);
    int regRec = sqlite4GetTempReg(pParse);

    sqlite4OpenIndex(pParse, iCur, iDb, pIdx, OP_OpenRead);

    /* Assemble the child key values in a contiguous array of registers.
    ** Then apply the affinity transformation for the parent index.  */
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Copy, aiCol[i]+regContent, regTemp+i);
    }
    sqlite4VdbeAddOp2(v, OP_Affinity, regTemp, nCol);
    sqlite4VdbeChangeP4(v, -1, sqlite4IndexAffinityStr(v, pIdx), P4_TRANSIENT);

    /* If the parent table is the same as the child table, and we are about
    ** to increment the constraint-counter (i.e. this is an INSERT operation),
    ** then check if the row being inserted matches itself. If so, do not
    ** increment the constraint-counter. 
    **
    ** If any of the parent-key values are NULL, then the row cannot match 
    ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
    ** of the parent-key values are NULL (at this point it is known that
    ** none of the child key values are).  */
    if( pTab==pFKey->pFrom && nIncr==1 ){
      int iJump = sqlite4VdbeCurrentAddr(v) + nCol + 1;
      for(i=0; i<nCol; i++){
        int iChild = regTemp+i;
        int iParent = pIdx->aiColumn[i]+regContent;
        sqlite4VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
        sqlite4VdbeChangeP5(v, SQLITE_JUMPIFNULL);
        assert( iChild<=pParse->nMem && iParent<=pParse->nMem );
      }
      sqlite4VdbeAddOp2(v, OP_Goto, 0, iOk);
    }


    sqlite4VdbeAddOp3(v, OP_MakeIdxKey, iCur, regTemp, regRec);
    sqlite4VdbeChangeP5(v, 1);

    sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);

#if 0
    sqlite4VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
    sqlite4VdbeChangeP4(v, -1, sqlite4IndexAffinityStr(v,pIdx), P4_TRANSIENT);
    sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
#endif

    sqlite4ReleaseTempReg(pParse, regRec);
    sqlite4ReleaseTempRange(pParse, regTemp, nCol);
  }

  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
    /* Special case: If this is an INSERT statement that will insert exactly
................................................................................
  }

  sqlite4VdbeResolveLabel(v, iOk);
  sqlite4VdbeAddOp1(v, OP_Close, iCur);
}

/*
** This function is called to generate code executed when a row is inserted
** into or deleted from the parent table of foreign key constraint pFKey.

** When generating code for an SQL UPDATE operation, this function may be 
** called twice - once to "delete" the old row and once to "insert" the 
** new row.
**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
................................................................................
  int i;                          /* Iterator variable */
  Expr *pWhere = 0;               /* WHERE clause to scan with */
  NameContext sNameContext;       /* Context used to resolve WHERE clause */
  WhereInfo *pWInfo;              /* Context used by sqlite4WhereXXX() */
  int iFkIfZero = 0;              /* Address of OP_FkIfZero */
  Vdbe *v = sqlite4GetVdbe(pParse);

  assert( pIdx && pIdx->pTable==pTab );

  if( nIncr<0 ){
    iFkIfZero = sqlite4VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
  }

  /* Create an Expr object representing an SQL expression like:
  **
................................................................................
    int iCol;                     /* Index of column in child table */ 
    const char *zCol;             /* Name of column in child table */

    pLeft = sqlite4Expr(db, TK_REGISTER, 0);
    if( pLeft ){
      /* Set the collation sequence and affinity of the LHS of each TK_EQ
      ** expression to the parent key column defaults.  */

      Column *pCol;
      iCol = pIdx->aiColumn[i];
      pCol = &pTab->aCol[iCol];
      pLeft->iTable = regData+iCol;
      pLeft->affinity = pCol->affinity;
      pLeft->pColl = sqlite4LocateCollSeq(pParse, pCol->zColl);




    }
    iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
    assert( iCol>=0 );
    zCol = pFKey->pFrom->aCol[iCol].zName;
    pRight = sqlite4Expr(db, TK_ID, zCol);
    pEq = sqlite4PExpr(pParse, TK_EQ, pLeft, pRight, 0);
    pWhere = sqlite4ExprAnd(db, pWhere, pEq);
................................................................................
  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite4ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. For each row found, increment the relevant constraint counter
  ** by nIncr.  */

  pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite4ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite4WhereEnd(pWInfo);
................................................................................
  }
}

#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))

/*
** This function is called before generating code to update or delete a 
** row contained in table pTab. 
*/
u32 sqlite4FkOldmask(
  Parse *pParse,                  /* Parse context */
  Table *pTab                     /* Table being modified */
){
  u32 mask = 0;
  if( pParse->db->flags&SQLITE_ForeignKeys ){
................................................................................
** If any foreign key processing will be required, this function returns
** true. If there is no foreign key related processing, this function 
** returns false.
*/
int sqlite4FkRequired(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being modified */
  int *aChange                    /* Non-NULL for UPDATE operations */

){
  if( pParse->db->flags&SQLITE_ForeignKeys ){
    if( !aChange ){
      /* A DELETE operation. Foreign key processing is required if the 
      ** table in question is either the child or parent table for any 
      ** foreign key constraint.  */
      return (sqlite4FkReferences(pTab) || pTab->pFKey);

Changes to src/insert.c.

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
....
1008
1009
1010
1011
1012
1013
1014



1015
1016
1017
1018
1019
1020
1021
....
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
....
1365
1366
1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1381
1382
....
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
1451
....
1458
1459
1460
1461
1462
1463
1464



1465
1466
1467
1468
1469
1470
1471
....
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
....
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
              pTabList, 0, pColumn->a[i].zName);
        pParse->checkSchema = 1;
        goto insert_cleanup;
      }
    }
  }

  /* Initialize the count of rows to be inserted
  */
  if( db->flags & SQLITE_CountRows ){
    regRowCount = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regRowCount);
  }

  /* If this is not a view, open a write cursor on each index. Allocate
  ** a contiguous array of (nIdx+1) registers, where nIdx is the total
  ** number of indexes (including the PRIMARY KEY index). 
  **
  **   Register aRegIdx[0]:         The PRIMARY KEY index key
  **   Register aRegIdx[1..nIdx-1]: Keys for other table indexes 
  **   Register aRegIdx[nIdx]:      Data record for table row.
................................................................................
      sqlite4VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
      appendFlag = 1;
    }
    autoIncStep(pParse, regAutoinc, regRowid);
#endif

    /* Push onto the stack, data for all columns of the new entry, beginning
    ** with the first column.
    */
    nHidden = 0;
    for(i=0; i<pTab->nCol; i++){
      int iRegStore = regContent + i;
      if( pColumn==0 ){
        if( IsHiddenColumn(&pTab->aCol[i]) ){
          assert( IsVirtual(pTab) );
          j = -1;
................................................................................
        sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
      }else if( pSelect ){
        sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
      }else{
        sqlite4ExprCode(pParse, pList->a[j].pExpr, iRegStore);
      }
    }




    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite4GetVTable(db, pTab);
................................................................................
      sqlite4MayAbort(pParse);
    }else
#endif
    {
      int isReplace;    /* Set to true if constraints may cause a replace */

      sqlite4GenerateConstraintChecks(pParse, pTab, baseCur, 
          regContent, aRegIdx, keyColumn>=0, 0, onError, endOfLoop, &isReplace
      );

      sqlite4FkCheck(pParse, pTab, 0, regContent);

      sqlite4CompleteInsertion(pParse, pTab, baseCur, 
          regContent, aRegIdx, 0, appendFlag, isReplace==0
      );
    }
  }

  /* Update the count of rows that are inserted
  */
  if( (db->flags & SQLITE_CountRows)!=0 ){
    sqlite4VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
  }

  if( pTrigger ){
    /* Code AFTER triggers */
    sqlite4CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
        pTab, regData-2-pTab->nCol, onError, endOfLoop);
  }

  /* The bottom of the main insertion loop, if the data source
................................................................................
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 ){
    sqlite4AutoincrementEnd(pParse);
  }

  /*
  ** Return the number of rows inserted. If this routine is 
  ** generating code because of a call to sqlite4NestedParse(), do not
  ** invoke the callback function.
  */
  if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){
    sqlite4VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
    sqlite4VdbeSetNumCols(v, 1);
    sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
  }

insert_cleanup:
  sqlite4SrcListDelete(db, pTabList);
  sqlite4ExprListDelete(db, pList);
  sqlite4SelectDelete(db, pSelect);
  sqlite4IdListDelete(db, pColumn);
  sqlite4DbFree(db, aRegIdx);
}
................................................................................
*/
void sqlite4GenerateConstraintChecks(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* First in array of cursors for pTab indexes */
  int regContent,     /* Index of the range of input registers */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */

  int rowidChng,      /* True if the rowid might collide with existing entry */

  int isUpdate,       /* True for UPDATE, False for INSERT */

  int overrideError,  /* Override onError to this if not OE_Default */
  int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
  int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
){
  u8 aPkRoot[10];                 /* Root page number for pPk as a varint */ 
  int nPkRoot;                    /* Size of aPkRoot in bytes */
  Index *pPk;                     /* Primary key index for table pTab */
................................................................................
    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the aRegIdx[iCur] register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;
    if( onError!=OE_None ){
      int iTest;                  /* Address of OP_IsUnique instruction */

      int regOut = 0;

      /* Figure out what to do if a UNIQUE constraint is encountered. 
      **
      ** TODO: If a previous constraint is a REPLACE, why change IGNORE to
      ** REPLACE and FAIL to ABORT here?  */
      if( overrideError!=OE_Default ){
        onError = overrideError;
................................................................................
      }

      if( onError==OE_Replace ){
        sqlite4VdbeAddOp3(v, OP_Blob, nPkRoot, regPk, 0);
        sqlite4VdbeChangeP4(v, -1, aPkRoot, nPkRoot);
        regOut = regPk;
      }



      iTest = sqlite4VdbeAddOp3(v, OP_IsUnique, baseCur+iCur, 0, aRegIdx[iCur]);
      sqlite4VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(regOut), P4_INT32);
      
      switch( onError ){
        case OE_Rollback:
        case OE_Abort:
        case OE_Fail: {
................................................................................
          seenReplace = 1;
          break;
        }
      }

      /* If the OP_IsUnique passes (no constraint violation) jump here */
      sqlite4VdbeJumpHere(v, iTest);

    }

    sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
  }
  
  if( pbMayReplace ){
    *pbMayReplace = seenReplace;
................................................................................
  ** the extra complication to make this rule less restrictive is probably
  ** not worth the effort.  Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
  */
  if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
    return 0;
  }
#endif
  if( (pParse->db->flags & SQLITE_CountRows)!=0 ){
    return 0;  /* xfer opt does not play well with PRAGMA count_changes */
  }

  /* If we get this far, it means that the xfer optimization is at
  ** least a possibility, though it might only work if the destination
  ** table (tab1) is initially empty.
  */
#ifdef SQLITE_TEST
  sqlite4_xferopt_count++;







<
<
<
<
<
<
<







 







|
<







 







>
>
>







 







|










<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<







 







<
<
>

<







 







>
|







 







>
>
>







 







>







 







<
<
<







784
785
786
787
788
789
790







791
792
793
794
795
796
797
...
973
974
975
976
977
978
979
980

981
982
983
984
985
986
987
....
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037






1038
1039
1040
1041
1042
1043
1044
....
1066
1067
1068
1069
1070
1071
1072











1073
1074
1075
1076
1077
1078
1079
....
1343
1344
1345
1346
1347
1348
1349


1350
1351

1352
1353
1354
1355
1356
1357
1358
....
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
....
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
....
1825
1826
1827
1828
1829
1830
1831



1832
1833
1834
1835
1836
1837
1838
              pTabList, 0, pColumn->a[i].zName);
        pParse->checkSchema = 1;
        goto insert_cleanup;
      }
    }
  }








  /* If this is not a view, open a write cursor on each index. Allocate
  ** a contiguous array of (nIdx+1) registers, where nIdx is the total
  ** number of indexes (including the PRIMARY KEY index). 
  **
  **   Register aRegIdx[0]:         The PRIMARY KEY index key
  **   Register aRegIdx[1..nIdx-1]: Keys for other table indexes 
  **   Register aRegIdx[nIdx]:      Data record for table row.
................................................................................
      sqlite4VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
      appendFlag = 1;
    }
    autoIncStep(pParse, regAutoinc, regRowid);
#endif

    /* Push onto the stack, data for all columns of the new entry, beginning
    ** with the first column.  */

    nHidden = 0;
    for(i=0; i<pTab->nCol; i++){
      int iRegStore = regContent + i;
      if( pColumn==0 ){
        if( IsHiddenColumn(&pTab->aCol[i]) ){
          assert( IsVirtual(pTab) );
          j = -1;
................................................................................
        sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
      }else if( pSelect ){
        sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
      }else{
        sqlite4ExprCode(pParse, pList->a[j].pExpr, iRegStore);
      }
    }

    sqlite4VdbeAddOp2(v, OP_Affinity, regContent, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite4GetVTable(db, pTab);
................................................................................
      sqlite4MayAbort(pParse);
    }else
#endif
    {
      int isReplace;    /* Set to true if constraints may cause a replace */

      sqlite4GenerateConstraintChecks(pParse, pTab, baseCur, 
          regContent, aRegIdx, 0, 0, onError, endOfLoop, &isReplace
      );

      sqlite4FkCheck(pParse, pTab, 0, regContent);

      sqlite4CompleteInsertion(pParse, pTab, baseCur, 
          regContent, aRegIdx, 0, appendFlag, isReplace==0
      );
    }
  }







  if( pTrigger ){
    /* Code AFTER triggers */
    sqlite4CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
        pTab, regData-2-pTab->nCol, onError, endOfLoop);
  }

  /* The bottom of the main insertion loop, if the data source
................................................................................
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 ){
    sqlite4AutoincrementEnd(pParse);
  }












insert_cleanup:
  sqlite4SrcListDelete(db, pTabList);
  sqlite4ExprListDelete(db, pList);
  sqlite4SelectDelete(db, pSelect);
  sqlite4IdListDelete(db, pColumn);
  sqlite4DbFree(db, aRegIdx);
}
................................................................................
*/
void sqlite4GenerateConstraintChecks(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* First in array of cursors for pTab indexes */
  int regContent,     /* Index of the range of input registers */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */


  int regOldKey,      /* For an update, the original encoded PK */
  int isUpdate,       /* True for UPDATE, False for INSERT */

  int overrideError,  /* Override onError to this if not OE_Default */
  int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
  int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
){
  u8 aPkRoot[10];                 /* Root page number for pPk as a varint */ 
  int nPkRoot;                    /* Size of aPkRoot in bytes */
  Index *pPk;                     /* Primary key index for table pTab */
................................................................................
    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the aRegIdx[iCur] register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;
    if( onError!=OE_None ){
      int iTest;                  /* Address of OP_IsUnique instruction */
      int iTest2 = 0;             /* Address of OP_Eq instruction */
      int regOut = 0;             /* PK of row to replace */

      /* Figure out what to do if a UNIQUE constraint is encountered. 
      **
      ** TODO: If a previous constraint is a REPLACE, why change IGNORE to
      ** REPLACE and FAIL to ABORT here?  */
      if( overrideError!=OE_Default ){
        onError = overrideError;
................................................................................
      }

      if( onError==OE_Replace ){
        sqlite4VdbeAddOp3(v, OP_Blob, nPkRoot, regPk, 0);
        sqlite4VdbeChangeP4(v, -1, aPkRoot, nPkRoot);
        regOut = regPk;
      }
      if( regOldKey && pIdx==pPk ){
        iTest2 = sqlite4VdbeAddOp3(v, OP_Eq, regOldKey, 0, aRegIdx[iCur]);
      }
      iTest = sqlite4VdbeAddOp3(v, OP_IsUnique, baseCur+iCur, 0, aRegIdx[iCur]);
      sqlite4VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(regOut), P4_INT32);
      
      switch( onError ){
        case OE_Rollback:
        case OE_Abort:
        case OE_Fail: {
................................................................................
          seenReplace = 1;
          break;
        }
      }

      /* If the OP_IsUnique passes (no constraint violation) jump here */
      sqlite4VdbeJumpHere(v, iTest);
      if( iTest2 ) sqlite4VdbeJumpHere(v, iTest2);
    }

    sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
  }
  
  if( pbMayReplace ){
    *pbMayReplace = seenReplace;
................................................................................
  ** the extra complication to make this rule less restrictive is probably
  ** not worth the effort.  Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
  */
  if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
    return 0;
  }
#endif




  /* If we get this far, it means that the xfer optimization is at
  ** least a possibility, though it might only work if the destination
  ** table (tab1) is initially empty.
  */
#ifdef SQLITE_TEST
  sqlite4_xferopt_count++;

Changes to src/kvmem.c.

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
    *ppParent = 0;
    pBalance = pOld->pUp;
  }else if( pOld->pBefore && pOld->pAfter ){
    KVMemNode *pX;                /* Smallest node that is larger than pOld */
    KVMemNode *pY;                /* Left-hand child of pOld */
    pX = kvmemFirst(pOld->pAfter);
    assert( pX->pBefore==0 );



    *kvmemFromPtr(pX, 0) = pX->pAfter;
    if( pX->pAfter ) pX->pAfter->pUp = pX->pUp;
    pBalance = pX->pUp;
    pX->pAfter = pOld->pAfter;
    if( pX->pAfter ){
      pX->pAfter->pUp = pX;
    }else{
      assert( pBalance==pOld );
      pBalance = pX;

    }
    pX->pBefore = pY = pOld->pBefore;
    if( pY ) pY->pUp = pX;
    pX->pUp = pOld->pUp;
    *ppParent = pX;
  }else if( pOld->pBefore==0 ){
    *ppParent = pBalance = pOld->pAfter;
    pBalance->pUp = pOld->pUp;
  }else if( pOld->pAfter==0 ){
    *ppParent = pBalance = pOld->pBefore;
    pBalance->pUp = pOld->pUp;
  }

  p->pRoot = kvmemBalance(pBalance);

  kvmemNodeUnref(pOld);
}

/*
** End of low-level access routines
***************************************************************************
** Interface routines follow







>
>
>
|
|
|
|
|
|
|
|
|
>












>

>







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
    *ppParent = 0;
    pBalance = pOld->pUp;
  }else if( pOld->pBefore && pOld->pAfter ){
    KVMemNode *pX;                /* Smallest node that is larger than pOld */
    KVMemNode *pY;                /* Left-hand child of pOld */
    pX = kvmemFirst(pOld->pAfter);
    assert( pX->pBefore==0 );
    if( pX==pOld->pAfter ){
      pBalance = pX;
    }else{
      *kvmemFromPtr(pX, 0) = pX->pAfter;
      if( pX->pAfter ) pX->pAfter->pUp = pX->pUp;
      pBalance = pX->pUp;
      pX->pAfter = pOld->pAfter;
      if( pX->pAfter ){
        pX->pAfter->pUp = pX;
      }else{
        assert( pBalance==pOld );
        pBalance = pX;
      }
    }
    pX->pBefore = pY = pOld->pBefore;
    if( pY ) pY->pUp = pX;
    pX->pUp = pOld->pUp;
    *ppParent = pX;
  }else if( pOld->pBefore==0 ){
    *ppParent = pBalance = pOld->pAfter;
    pBalance->pUp = pOld->pUp;
  }else if( pOld->pAfter==0 ){
    *ppParent = pBalance = pOld->pBefore;
    pBalance->pUp = pOld->pUp;
  }
  assertUpPointers(p->pRoot);
  p->pRoot = kvmemBalance(pBalance);
  assertUpPointers(p->pRoot);
  kvmemNodeUnref(pOld);
}

/*
** End of low-level access routines
***************************************************************************
** Interface routines follow

Changes to src/sqliteInt.h.

3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
  void sqlite4FkCheck(Parse*, Table*, int, int);
  void sqlite4FkDropTable(Parse*, SrcList *, Table*);
  void sqlite4FkActions(Parse*, Table*, ExprList*, int);
  int sqlite4FkRequired(Parse*, Table*, int*, int);
  u32 sqlite4FkOldmask(Parse*, Table*);
  FKey *sqlite4FkReferences(Table *);
#else
  #define sqlite4FkActions(a,b,c,d)
  #define sqlite4FkCheck(a,b,c,d)
  #define sqlite4FkDropTable(a,b,c)
  #define sqlite4FkOldmask(a,b)      0
  #define sqlite4FkRequired(a,b,c,d) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
  void sqlite4FkDelete(sqlite4 *, Table*);
#else
  #define sqlite4FkDelete(a,b)
#endif








|







|







3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
  void sqlite4FkCheck(Parse*, Table*, int, int);
  void sqlite4FkDropTable(Parse*, SrcList *, Table*);
  void sqlite4FkActions(Parse*, Table*, ExprList*, int);
  int sqlite4FkRequired(Parse*, Table*, int*);
  u32 sqlite4FkOldmask(Parse*, Table*);
  FKey *sqlite4FkReferences(Table *);
#else
  #define sqlite4FkActions(a,b,c,d)
  #define sqlite4FkCheck(a,b,c,d)
  #define sqlite4FkDropTable(a,b,c)
  #define sqlite4FkOldmask(a,b)      0
  #define sqlite4FkRequired(a,b,c) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
  void sqlite4FkDelete(sqlite4 *, Table*);
#else
  #define sqlite4FkDelete(a,b)
#endif

Changes to src/update.c.

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
403
404
405
406
407
408
409

410
411
412

413
414
415
416
417
418
419
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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
  int nIdx;              /* Number of indices that need updating */
  int iCur;              /* VDBE Cursor number of pTab */
  sqlite4 *db;           /* The database structure */
  int *aRegIdx = 0;      /* One register assigned to each index to be updated */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */
  int chngRowid;         /* True if the record number is being changed */
  Expr *pRowidExpr = 0;  /* Expression defining the new record number */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int okOnePass;         /* True for one-pass algorithm without the FIFO */
  int hasFK;             /* True if foreign key processing is required */

................................................................................
                       pWhere, onError);
    pWhere = 0;
    pSrc = 0;
    goto update_cleanup;
  }
#endif

  hasFK = sqlite4FkRequired(pParse, pTab, aXRef, chngRowid);

  /* Allocate memory for the array aRegIdx[].  There is one entry in the
  ** array for each index associated with table being updated.  Fill in
  ** the value with a register number for indices that are to be used
  ** and with zero for unused indices.  */
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
  aRegIdx = sqlite4DbMallocZero(db, sizeof(Index*) * nIdx );
................................................................................
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
      }else{
        sqlite4VdbeAddOp2(v, OP_Null, 0, regOld+i);
      }
    }

    if( chngRowid==0 ){
      sqlite4VdbeAddOp2(v, OP_Copy, regOldKey, regNewRowid);
    }

  }

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

  if( !isView ){
    int j1;                       /* Address of jump instruction */


    /* Do constraint checks. */
    assert( bChngPk==0 || bImplicitPk==0 );
    if( bChngPk==0 ) aRegIdx[iPk] = 0;
    sqlite4GenerateConstraintChecks(
        pParse, pTab, iCur, regNew, aRegIdx, 0, 1, onError, addr, 0
    );
    if( bChngPk==0 ) aRegIdx[iPk] = regOldKey;

    /* Do FK constraint checks. */
    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, regOldKey, 0);
    }

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32);
    sqlite4GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
  
    /* Delete the old record */
    if( hasFK || bChngPk ){
      sqlite4VdbeAddOp2(v, OP_Delete, iCur, 0);
    }
    sqlite4VdbeJumpHere(v, j1);

    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, 0, regNewRowid);
    }
  
    /* Insert the new index entries and the new record. */
    sqlite4CompleteInsertion(pParse, pTab, iCur, regNew, aRegIdx, 1, 0, 0);

    /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
    ** handle rows (possibly in other tables) that refer via a foreign key







<







 







|







 







>



>







 







<




|





|













|







102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
...
479
480
481
482
483
484
485

486
487
488
489
490
491
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
  int nIdx;              /* Number of indices that need updating */
  int iCur;              /* VDBE Cursor number of pTab */
  sqlite4 *db;           /* The database structure */
  int *aRegIdx = 0;      /* One register assigned to each index to be updated */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */

  Expr *pRowidExpr = 0;  /* Expression defining the new record number */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int okOnePass;         /* True for one-pass algorithm without the FIFO */
  int hasFK;             /* True if foreign key processing is required */

................................................................................
                       pWhere, onError);
    pWhere = 0;
    pSrc = 0;
    goto update_cleanup;
  }
#endif

  hasFK = sqlite4FkRequired(pParse, pTab, aXRef);

  /* Allocate memory for the array aRegIdx[].  There is one entry in the
  ** array for each index associated with table being updated.  Fill in
  ** the value with a register number for indices that are to be used
  ** and with zero for unused indices.  */
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
  aRegIdx = sqlite4DbMallocZero(db, sizeof(Index*) * nIdx );
................................................................................
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
      }else{
        sqlite4VdbeAddOp2(v, OP_Null, 0, regOld+i);
      }
    }
#if 0
    if( chngRowid==0 ){
      sqlite4VdbeAddOp2(v, OP_Copy, regOldKey, regNewRowid);
    }
#endif
  }

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

  if( !isView ){
    int j1;                       /* Address of jump instruction */


    /* Do constraint checks. */
    assert( bChngPk==0 || bImplicitPk==0 );
    if( bChngPk==0 ) aRegIdx[iPk] = 0;
    sqlite4GenerateConstraintChecks(
        pParse, pTab, iCur, regNew, aRegIdx, regOldKey, 1, onError, addr, 0
    );
    if( bChngPk==0 ) aRegIdx[iPk] = regOldKey;

    /* Do FK constraint checks. */
    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, regOld, 0);
    }

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32);
    sqlite4GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
  
    /* Delete the old record */
    if( hasFK || bChngPk ){
      sqlite4VdbeAddOp2(v, OP_Delete, iCur, 0);
    }
    sqlite4VdbeJumpHere(v, j1);

    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, 0, regNew);
    }
  
    /* Insert the new index entries and the new record. */
    sqlite4CompleteInsertion(pParse, pTab, iCur, regNew, aRegIdx, 1, 0, 0);

    /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
    ** handle rows (possibly in other tables) that refer via a foreign key

Changes to src/vdbe.c.

2151
2152
2153
2154
2155
2156
2157

2158
2159
2160
2161

2162
2163
2164
2165

2166
2167

2168

2169
2170
2171
2172
2173
2174
2175
....
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
....
2287
2288
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302
....
2384
2385
2386
2387
2388
2389
2390
2391

2392
2393
2394
2395
2396


2397
2398
2399
2400
2401
2402
2403
....
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442


2443
2444
2445
2446
2447
2448
2449
....
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
** P4 is a string that is P2 characters long. The nth character of the
** string indicates the column affinity that should be used for the nth
** memory cell in the range.
*/
case OP_Affinity: {
  const char *zAffinity;   /* The affinity to be applied */
  char cAff;               /* A single character of affinity */


  zAffinity = pOp->p4.z;
  assert( zAffinity!=0 );
  assert( zAffinity[pOp->p2]==0 );

  pIn1 = &aMem[pOp->p1];
  while( (cAff = *(zAffinity++))!=0 ){
    assert( pIn1 <= &p->aMem[p->nMem] );
    assert( memIsValid(pIn1) );

    applyAffinity(pIn1, cAff, encoding);
    pIn1++;

  }

  break;
}

/* Opcode: MakeIdxKey P1 P2 P3 * P5
**
** P1 is an open cursor. P2 is the first register in a contiguous array
** of N registers containing values to encode into a database key. Normally,
................................................................................
*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */

  
  pC = p->apCsr[pOp->p1];
  pKeyInfo = pC->pKeyInfo;
  pData0 = &aMem[pOp->p2];
  pOut = &aMem[pOp->p3];
  aRec = 0;

  memAboutToChange(p, pOut);

  assert( pOp->p5==0 );
  rc = sqlite4VdbeEncodeKey(
    db, pData0, pKeyInfo->nField, pC->iRoot, pKeyInfo, &aRec, &nRec, 0
  );

  if( rc ){
    sqlite4DbFree(db, aRec);
  }else{
    rc = sqlite4VdbeMemSetStr(pOut, aRec, nRec, 0, SQLITE_DYNAMIC);
    REGISTER_TRACE(pOp->p3, pOut);
................................................................................
      sqlite4VdbeMemExpandBlob(pMem);
    }
  }

  /* Compute the key (if this is a MakeKey opcode) */
  if( pC ){
    aRec = 0;
    rc = sqlite4VdbeEncodeKey(db, pData0, nField, pC->iRoot, pC->pKeyInfo,
                              &aRec, &nRec, 0);

    if( rc ){
      sqlite4DbFree(db, aRec);
    }else{
      rc = sqlite4VdbeMemSetStr(pKeyOut, aRec, nRec, 0, SQLITE_DYNAMIC);
      REGISTER_TRACE(keyReg, pKeyOut);
      UPDATE_MAX_BLOBSIZE(pKeyOut);
    }
................................................................................
  }

  else if( bAutoCommit==0 ){
    db->autoCommit = 0;
  }else{
    if( bRollback ){
      sqlite4RollbackAll(db);
    }else if( sqlite4VdbeCheckFk(p, 1) ){

      goto vdbe_return;
    }

    db->autoCommit = 1;
    sqlite4VdbeHalt(p);


  }

  break;
}

/* Opcode: Transaction P1 P2 * * *
**
................................................................................
  if( pOp->p2==0 ){
    /* Read transaction needed.  Start if we are not already in one. */
    if( pKV->iTransLevel==0 ){
      rc = sqlite4KVStoreBegin(pKV, 1);
    }
  }else{
    /* A write transaction is needed */
    needStmt = pKV->iTransLevel>0 && (p->needSavepoint || db->activeVdbeCnt>1);
    if( pKV->iTransLevel<2 ){
      rc = sqlite4KVStoreBegin(pKV, 2);
    }else if( p->needSavepoint ){


      rc = sqlite4KVStoreBegin(pKV, pKV->iTransLevel+1);
      if( rc==SQLITE_OK ){
        p->stmtTransMask |= ((yDbMask)1)<<pOp->p1;
      }
    }
  }
  break;
................................................................................
    nProbe = pIn3->n;
    pFree = 0;
  }
  if( rc==SQLITE_OK ){
    rc = sqlite4KVCursorSeek(pC->pKVCur, pProbe, nProbe, +1);
    if( rc==SQLITE_INEXACT || rc==SQLITE_OK ){
      rc = sqlite4KVCursorKey(pC->pKVCur, &pKey, &nKey);
      if( rc==SQLITE_OK && nKey>=nProbe && memcmp(pKey, pProbe, nKey)==0 ){
        alreadyExists = 1;
        pC->nullRow = 0;
      }
    }else if( rc==SQLITE_NOTFOUND ){
      rc = SQLITE_OK;
    }
  }







>



|
>
|
<
|

>
|
<
>

>







 







>









|

|







 







|
|
>







 







|
>





>
>







 







|


<
>
>







 







|







2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164

2165
2166
2167
2168

2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
....
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
....
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
....
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
....
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449

2450
2451
2452
2453
2454
2455
2456
2457
2458
....
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
** P4 is a string that is P2 characters long. The nth character of the
** string indicates the column affinity that should be used for the nth
** memory cell in the range.
*/
case OP_Affinity: {
  const char *zAffinity;   /* The affinity to be applied */
  char cAff;               /* A single character of affinity */
  Mem *pEnd;

  zAffinity = pOp->p4.z;
  assert( zAffinity!=0 );
  assert( sqlite4Strlen30(zAffinity)>=pOp->p2 );

  pEnd = &aMem[pOp->p2+pOp->p1];

  for(pIn1=&aMem[pOp->p1]; pIn1<pEnd; pIn1++){
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pIn1);
    applyAffinity(pIn1, *(zAffinity++), encoding);

    REGISTER_TRACE(pIn1-aMem, pIn1);
  }

  break;
}

/* Opcode: MakeIdxKey P1 P2 P3 * P5
**
** P1 is an open cursor. P2 is the first register in a contiguous array
** of N registers containing values to encode into a database key. Normally,
................................................................................
*/
case OP_MakeIdxKey: {
  VdbeCursor *pC;
  KeyInfo *pKeyInfo;
  Mem *pData0;                    /* First in array of input registers */
  u8 *aRec;                       /* The constructed database key */
  int nRec;                       /* Size of aRec[] in bytes */
  int nField;                     /* Number of fields in encoded record */
  
  pC = p->apCsr[pOp->p1];
  pKeyInfo = pC->pKeyInfo;
  pData0 = &aMem[pOp->p2];
  pOut = &aMem[pOp->p3];
  aRec = 0;

  memAboutToChange(p, pOut);

  nField = pKeyInfo->nField - (pOp->p5 ? pKeyInfo->nPK : 0);
  rc = sqlite4VdbeEncodeKey(
    db, pData0, nField, pC->iRoot, pKeyInfo, &aRec, &nRec, 0
  );

  if( rc ){
    sqlite4DbFree(db, aRec);
  }else{
    rc = sqlite4VdbeMemSetStr(pOut, aRec, nRec, 0, SQLITE_DYNAMIC);
    REGISTER_TRACE(pOp->p3, pOut);
................................................................................
      sqlite4VdbeMemExpandBlob(pMem);
    }
  }

  /* Compute the key (if this is a MakeKey opcode) */
  if( pC ){
    aRec = 0;
    rc = sqlite4VdbeEncodeKey(db, 
        pData0, pC->pKeyInfo->nField, pC->iRoot, pC->pKeyInfo, &aRec, &nRec, 0
    );
    if( rc ){
      sqlite4DbFree(db, aRec);
    }else{
      rc = sqlite4VdbeMemSetStr(pKeyOut, aRec, nRec, 0, SQLITE_DYNAMIC);
      REGISTER_TRACE(keyReg, pKeyOut);
      UPDATE_MAX_BLOBSIZE(pKeyOut);
    }
................................................................................
  }

  else if( bAutoCommit==0 ){
    db->autoCommit = 0;
  }else{
    if( bRollback ){
      sqlite4RollbackAll(db);
    }else if( rc = sqlite4VdbeCheckFk(p, 1) ){
      rc = SQLITE_ERROR;
      goto vdbe_return;
    }

    db->autoCommit = 1;
    sqlite4VdbeHalt(p);
    rc = (p->rc ? SQLITE_DONE : SQLITE_ERROR);
    goto vdbe_return;
  }

  break;
}

/* Opcode: Transaction P1 P2 * * *
**
................................................................................
  if( pOp->p2==0 ){
    /* Read transaction needed.  Start if we are not already in one. */
    if( pKV->iTransLevel==0 ){
      rc = sqlite4KVStoreBegin(pKV, 1);
    }
  }else{
    /* A write transaction is needed */
    needStmt = db->autoCommit==0 && (p->needSavepoint || db->activeVdbeCnt>1);
    if( pKV->iTransLevel<2 ){
      rc = sqlite4KVStoreBegin(pKV, 2);

    }
    if( needStmt ){
      rc = sqlite4KVStoreBegin(pKV, pKV->iTransLevel+1);
      if( rc==SQLITE_OK ){
        p->stmtTransMask |= ((yDbMask)1)<<pOp->p1;
      }
    }
  }
  break;
................................................................................
    nProbe = pIn3->n;
    pFree = 0;
  }
  if( rc==SQLITE_OK ){
    rc = sqlite4KVCursorSeek(pC->pKVCur, pProbe, nProbe, +1);
    if( rc==SQLITE_INEXACT || rc==SQLITE_OK ){
      rc = sqlite4KVCursorKey(pC->pKVCur, &pKey, &nKey);
      if( rc==SQLITE_OK && nKey>=nProbe && memcmp(pKey, pProbe, nProbe)==0 ){
        alreadyExists = 1;
        pC->nullRow = 0;
      }
    }else if( rc==SQLITE_NOTFOUND ){
      rc = SQLITE_OK;
    }
  }

Changes to src/vdbecodec.c.

644
645
646
647
648
649
650
651
652
653
654
655



656
657
658
659
660
661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  int *pnShort                 /* Number of bytes without the primary key */
){
  int i;
  int rc = SQLITE_OK;
  KeyEncoder x;
  u8 *so;
  int iShort;
  int nField;
  CollSeq **aColl;
  CollSeq *xColl;
  static const CollSeq defaultColl;




  x.db = db;
  x.aOut = 0;
  x.nOut = 0;
  x.nAlloc = 0;
  *paOut = 0;
  *pnOut = 0;

  if( enlargeEncoderAllocation(&x, (nIn+1)*10) ) return SQLITE_NOMEM;
  x.nOut = sqlite4PutVarint64(x.aOut, iTabno);
  if( pKeyInfo ){
    nField = pKeyInfo->nField;
    iShort = nField - pKeyInfo->nPK;
    aColl = pKeyInfo->aColl;
    so = pKeyInfo->aSortOrder;
  }else{
    nField = 1;
    iShort = 0;
    xColl = &defaultColl;
    aColl = &xColl;
    so = 0;
  }
  for(i=0; i<nField && rc==SQLITE_OK; i++){
    rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE_SO_ASC, aColl[i]);
    if( pnShort && i+1==iShort ) *pnShort = x.nOut;
  }
  if( rc ){
    sqlite4DbFree(db, x.aOut);
  }else{
    *paOut = x.aOut;







<




>
>
>






>


<
<
|
|
|
<
<
<
<
<
<
<
|







644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666


667
668
669







670
671
672
673
674
675
676
677
  int *pnShort                 /* Number of bytes without the primary key */
){
  int i;
  int rc = SQLITE_OK;
  KeyEncoder x;
  u8 *so;
  int iShort;

  CollSeq **aColl;
  CollSeq *xColl;
  static const CollSeq defaultColl;

  assert( pKeyInfo );
  assert( nIn<=pKeyInfo->nField );

  x.db = db;
  x.aOut = 0;
  x.nOut = 0;
  x.nAlloc = 0;
  *paOut = 0;
  *pnOut = 0;

  if( enlargeEncoderAllocation(&x, (nIn+1)*10) ) return SQLITE_NOMEM;
  x.nOut = sqlite4PutVarint64(x.aOut, iTabno);


  iShort = pKeyInfo->nField - pKeyInfo->nPK;
  aColl = pKeyInfo->aColl;
  so = pKeyInfo->aSortOrder;







  for(i=0; i<nIn && rc==SQLITE_OK; i++){
    rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE_SO_ASC, aColl[i]);
    if( pnShort && i+1==iShort ) *pnShort = x.nOut;
  }
  if( rc ){
    sqlite4DbFree(db, x.aOut);
  }else{
    *paOut = x.aOut;

Changes to test/conflict.test.

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
...
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
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  }
  execsql {
    SELECT count(*), min(a), max(b) FROM t1;
  }
} {50 1 51}
do_test conflict-7.2 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE OR IGNORE t1 SET a=1000;
  }
} {1}
do_test conflict-7.2.1 {
  db changes
} {1}
do_test conflict-7.3 {
  execsql {
    SELECT b FROM t1 WHERE +a=1000;
  }
................................................................................
do_test conflict-7.4 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {50}
do_test conflict-7.5 {
  execsql {
    PRAGMA count_changes=on;
    UPDATE OR REPLACE t1 SET a=1001;
  }
} {50}
do_test conflict-7.5.1 {
  db changes
} {50}
do_test conflict-7.6 {
  execsql {
    SELECT b FROM t1 WHERE +a=1001;
  }
................................................................................
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2);
  }
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,3);
  }
} {1}
do_test conflict-8.1.1 {
  db changes
} {1}
do_test conflict-8.2 {
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,4);
  }
} {0}
do_test conflict-8.2.1 {
  db changes
} {0}
do_test conflict-8.3 {
  execsql {
    INSERT OR REPLACE INTO t1 VALUES(2,4);
  }
} {1}
do_test conflict-8.3.1 {
  db changes
} {1}
do_test conflict-8.4 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT * FROM t1;
  }
} {0}
do_test conflict-8.4.1 {
  db changes
} {0}
do_test conflict-8.5 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
  }
} {2}
do_test conflict-8.5.1 {
  db changes
} {2}
do_test conflict-8.6 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
  }
} {3}
do_test conflict-8.6.1 {
  db changes
} {3}

integrity_check conflict-8.99

do_test conflict-9.1 {
  execsql {
    PRAGMA count_changes=0;
    CREATE TABLE t2(
      a INTEGER UNIQUE ON CONFLICT IGNORE,
      b INTEGER UNIQUE ON CONFLICT FAIL,
      c INTEGER UNIQUE ON CONFLICT REPLACE,
      d INTEGER UNIQUE ON CONFLICT ABORT,
      e INTEGER UNIQUE ON CONFLICT ROLLBACK
    );







<


|







 







<


|







 







|







|







|







|







|







|








<







356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
...
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388
389
390
...
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
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
  }
  execsql {
    SELECT count(*), min(a), max(b) FROM t1;
  }
} {50 1 51}
do_test conflict-7.2 {
  execsql {

    UPDATE OR IGNORE t1 SET a=1000;
  }
} {}
do_test conflict-7.2.1 {
  db changes
} {1}
do_test conflict-7.3 {
  execsql {
    SELECT b FROM t1 WHERE +a=1000;
  }
................................................................................
do_test conflict-7.4 {
  execsql {
    SELECT count(*) FROM t1;
  }
} {50}
do_test conflict-7.5 {
  execsql {

    UPDATE OR REPLACE t1 SET a=1001;
  }
} {}
do_test conflict-7.5.1 {
  db changes
} {50}
do_test conflict-7.6 {
  execsql {
    SELECT b FROM t1 WHERE +a=1001;
  }
................................................................................
  execsql {
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,2);
  }
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,3);
  }
} {}
do_test conflict-8.1.1 {
  db changes
} {1}
do_test conflict-8.2 {
  execsql {
    INSERT OR IGNORE INTO t1 VALUES(2,4);
  }
} {}
do_test conflict-8.2.1 {
  db changes
} {0}
do_test conflict-8.3 {
  execsql {
    INSERT OR REPLACE INTO t1 VALUES(2,4);
  }
} {}
do_test conflict-8.3.1 {
  db changes
} {1}
do_test conflict-8.4 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT * FROM t1;
  }
} {}
do_test conflict-8.4.1 {
  db changes
} {0}
do_test conflict-8.5 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
  }
} {}
do_test conflict-8.5.1 {
  db changes
} {2}
do_test conflict-8.6 {
  execsql {
    INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
  }
} {}
do_test conflict-8.6.1 {
  db changes
} {3}

integrity_check conflict-8.99

do_test conflict-9.1 {
  execsql {

    CREATE TABLE t2(
      a INTEGER UNIQUE ON CONFLICT IGNORE,
      b INTEGER UNIQUE ON CONFLICT FAIL,
      c INTEGER UNIQUE ON CONFLICT REPLACE,
      d INTEGER UNIQUE ON CONFLICT ABORT,
      e INTEGER UNIQUE ON CONFLICT ROLLBACK
    );

Changes to test/fkey2.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
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
189
190
...
212
213
214
215
216
217
218

219
220
221
222
223
224
225
...
274
275
276
277
278
279
280

281
282
283
284
285
286
287
}

#-------------------------------------------------------------------------
# Test structure:
#
# fkey2-1.*: Simple tests to check that immediate and deferred foreign key 
#            constraints work when not inside a transaction.
#            
# fkey2-2.*: Tests to verify that deferred foreign keys work inside
#            explicit transactions (i.e that processing really is deferred).
#
# fkey2-3.*: Tests that a statement transaction is rolled back if an
#            immediate foreign key constraint is violated.
#
# fkey2-4.*: Test that FK actions may recurse even when recursive triggers
#            are disabled.
................................................................................
  4.9  "UPDATE t8 SET c=1 WHERE d=4"      {0 {}}
  4.10 "UPDATE t8 SET c=NULL WHERE d=4"   {0 {}}
  4.11 "DELETE FROM t7 WHERE b=1"         {1 {foreign key constraint failed}}
  4.12 "UPDATE t7 SET b = 2"              {1 {foreign key constraint failed}}
  4.13 "UPDATE t7 SET b = 1"              {0 {}}
  4.14 "INSERT INTO t8 VALUES('a', 'b')"  {1 {foreign key constraint failed}}
  4.15 "UPDATE t7 SET b = 5"              {1 {foreign key constraint failed}}
  4.16 "UPDATE t7 SET rowid = 5"          {1 {foreign key constraint failed}}
  4.17 "UPDATE t7 SET a = 10"             {0 {}}

  5.1  "INSERT INTO t9 VALUES(1, 3)"      {1 {no such table: main.nosuchtable}}
  5.2  "INSERT INTO t10 VALUES(1, 3)"     {1 {foreign key mismatch}}
}



do_test fkey2-1.1.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]
} {}
foreach {tn zSql res} $FkeySimpleTests {
  do_test fkey2-1.1.$tn { catchsql $zSql } $res
}
drop_all_tables



do_test fkey2-1.2.0 {
  execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema]
} {}
foreach {tn zSql res} $FkeySimpleTests {
  do_test fkey2-1.2.$tn { catchsql $zSql } $res
}
drop_all_tables




do_test fkey2-1.3.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]
  execsql { PRAGMA count_changes = 1 }
} {}
foreach {tn zSql res} $FkeySimpleTests {
  if {$res == "0 {}"} { set res {0 1} }

  do_test fkey2-1.3.$tn { catchsql $zSql } $res

}
execsql { PRAGMA count_changes = 0 }
drop_all_tables




do_test fkey2-1.4.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]
  execsql { PRAGMA count_changes = 1 }
} {}
foreach {tn zSql res} $FkeySimpleTests {
  if {$res == "0 {}"} { set res {0 1} }
  execsql BEGIN
  do_test fkey2-1.4.$tn { catchsql $zSql } $res
  execsql COMMIT

}
execsql { PRAGMA count_changes = 0 }
drop_all_tables


# Special test: When the parent key is an IPK, make sure the affinity of
# the IPK is not applied to the child key value before it is inserted
# into the child table.
do_test fkey2-1.5.1 {
  execsql {
    CREATE TABLE i(i INTEGER PRIMARY KEY);
................................................................................
} {35.0 text 35 integer}
do_test fkey2-1.6.2 {
  catchsql { DELETE FROM i }
} {1 {foreign key constraint failed}}

# Use a collation sequence on the parent key.
drop_all_tables

do_test fkey2-1.7.1 {
  execsql {
    CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY);
    CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i));
    INSERT INTO i VALUES('SQLite');
    INSERT INTO j VALUES('sqlite');
  }
................................................................................
    parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
  );
}

fkey2-2-test 1  0 "INSERT INTO node VALUES(1, 0)"       FKV
fkey2-2-test 2  0 "BEGIN"
fkey2-2-test 3  1   "INSERT INTO node VALUES(1, 0)"

fkey2-2-test 4  0   "UPDATE node SET parent = NULL"
fkey2-2-test 5  0 "COMMIT"
fkey2-2-test 6  0 "SELECT * FROM node" {1 {}}

fkey2-2-test 7  0 "BEGIN"
fkey2-2-test 8  1   "INSERT INTO leaf VALUES('a', 2)"
fkey2-2-test 9  1   "INSERT INTO node VALUES(2, 0)"







<
<







 







<






>
>








>
>








>
>
>


<


<
>

>

<


>
>
>


<


<
<
|
<
>

<

>







 







>







 







>







22
23
24
25
26
27
28


29
30
31
32
33
34
35
...
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
189
190
191
192
193
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
}

#-------------------------------------------------------------------------
# Test structure:
#
# fkey2-1.*: Simple tests to check that immediate and deferred foreign key 
#            constraints work when not inside a transaction.


#            explicit transactions (i.e that processing really is deferred).
#
# fkey2-3.*: Tests that a statement transaction is rolled back if an
#            immediate foreign key constraint is violated.
#
# fkey2-4.*: Test that FK actions may recurse even when recursive triggers
#            are disabled.
................................................................................
  4.9  "UPDATE t8 SET c=1 WHERE d=4"      {0 {}}
  4.10 "UPDATE t8 SET c=NULL WHERE d=4"   {0 {}}
  4.11 "DELETE FROM t7 WHERE b=1"         {1 {foreign key constraint failed}}
  4.12 "UPDATE t7 SET b = 2"              {1 {foreign key constraint failed}}
  4.13 "UPDATE t7 SET b = 1"              {0 {}}
  4.14 "INSERT INTO t8 VALUES('a', 'b')"  {1 {foreign key constraint failed}}
  4.15 "UPDATE t7 SET b = 5"              {1 {foreign key constraint failed}}

  4.17 "UPDATE t7 SET a = 10"             {0 {}}

  5.1  "INSERT INTO t9 VALUES(1, 3)"      {1 {no such table: main.nosuchtable}}
  5.2  "INSERT INTO t10 VALUES(1, 3)"     {1 {foreign key mismatch}}
}

# Run the simple tests with all FK constraints immediate.
#
do_test fkey2-1.1.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]
} {}
foreach {tn zSql res} $FkeySimpleTests {
  do_test fkey2-1.1.$tn { catchsql $zSql } $res
}
drop_all_tables

# Run the simple tests with all FK constraints deferred.
#
do_test fkey2-1.2.0 {
  execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema]
} {}
foreach {tn zSql res} $FkeySimpleTests {
  do_test fkey2-1.2.$tn { catchsql $zSql } $res
}
drop_all_tables

# Run the simple tests with all FK constraints immediate. Put a 
# BEGIN/COMMIT block around each write to the database.
#
do_test fkey2-1.3.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]

} {}
foreach {tn zSql res} $FkeySimpleTests {

  execsql BEGIN
  do_test fkey2-1.3.$tn { catchsql $zSql } $res
  execsql COMMIT
}

drop_all_tables

# Run the simple tests with all FK constraints deferred. Put a 
# BEGIN/COMMIT block around each write to the database.
#
do_test fkey2-1.4.0 {
  execsql [string map {/D/ {}} $FkeySimpleSchema]

} {}
foreach {tn zSql res} $FkeySimpleTests {


  do_test fkey2-1.4.$tn { catchsql "BEGIN; $zSql; COMMIT;" } $res

  catchsql commit
}

drop_all_tables


# Special test: When the parent key is an IPK, make sure the affinity of
# the IPK is not applied to the child key value before it is inserted
# into the child table.
do_test fkey2-1.5.1 {
  execsql {
    CREATE TABLE i(i INTEGER PRIMARY KEY);
................................................................................
} {35.0 text 35 integer}
do_test fkey2-1.6.2 {
  catchsql { DELETE FROM i }
} {1 {foreign key constraint failed}}

# Use a collation sequence on the parent key.
drop_all_tables
puts "src4: the following requires collation support"
do_test fkey2-1.7.1 {
  execsql {
    CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY);
    CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i));
    INSERT INTO i VALUES('SQLite');
    INSERT INTO j VALUES('sqlite');
  }
................................................................................
    parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
  );
}

fkey2-2-test 1  0 "INSERT INTO node VALUES(1, 0)"       FKV
fkey2-2-test 2  0 "BEGIN"
fkey2-2-test 3  1   "INSERT INTO node VALUES(1, 0)"

fkey2-2-test 4  0   "UPDATE node SET parent = NULL"
fkey2-2-test 5  0 "COMMIT"
fkey2-2-test 6  0 "SELECT * FROM node" {1 {}}

fkey2-2-test 7  0 "BEGIN"
fkey2-2-test 8  1   "INSERT INTO leaf VALUES('a', 2)"
fkey2-2-test 9  1   "INSERT INTO node VALUES(2, 0)"

Changes to test/simple.test.

417
418
419
420
421
422
423


424






































































425



















































426
427
428
429
430
431
432

  SELECT count(*) FROM def;
} {32}

do_execsql_test 20.2 { ROLLBACK }
do_execsql_test 20.3 { SELECT count(*) FROM def } 0










































































#execsql {PRAGMA  kvdump }




















































finish_test

#proc populate_t1 {} {
#  db eval {
#    INSERT INTO t1(a, b) VALUES(4, 'four');
#    INSERT INTO t1(a, b) VALUES(9, 'nine');







>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

  SELECT count(*) FROM def;
} {32}

do_execsql_test 20.2 { ROLLBACK }
do_execsql_test 20.3 { SELECT count(*) FROM def } 0

#-------------------------------------------------------------------------
reset_db

do_execsql_test 21.1 {
  PRAGMA foreign_keys = on;
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t2(c REFERENCES t1(a), d);
}

do_execsql_test 21.2 {
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t2 VALUES(1, 3);
  INSERT INTO t2 VALUES(NULL, 4);
}

do_catchsql_test 21.3 {
  UPDATE t2 SET c=2 WHERE d=4;
} {1 {foreign key constraint failed}}


#-------------------------------------------------------------------------
reset_db

do_execsql_test 22.1 {
  CREATE TABLE t1(x PRIMARY KEY);
  INSERT INTO t1 VALUES('abc');
}

do_execsql_test 22.2 { UPDATE t1 SET x = 'abc' }
do_execsql_test 22.3 { SELECT * FROM t1 } {abc}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 23.1 {
  PRAGMA foreign_keys = on;
  CREATE TABLE t1(a PRIMARY KEY, b);
  CREATE TABLE t2(c REFERENCES t1(a), d);
}
proc out {} {
  set t1 [execsql {SELECT a FROM t1}]
  set t2 [execsql {SELECT c FROM t2}]
  puts "t1: $t1       t2: $t2"
}

do_test 23.2 {
  catchsql "BEGIN; INSERT INTO t2 VALUES(1, 3)" ; execsql COMMIT
} {}
do_test 23.3 {
  catchsql "BEGIN; INSERT INTO t1 VALUES(1, 2)" ; execsql COMMIT
} {}
do_test 23.4 {
  catchsql "BEGIN; INSERT INTO t2 VALUES(1, 3)" ; execsql COMMIT
} {}
do_test 23.5 {
  catchsql "BEGIN; INSERT INTO t2 VALUES(2, 4)" ; execsql COMMIT
} {}
do_test 23.6 {
  catchsql "BEGIN; INSERT INTO t2 VALUES(NULL, 4)" ; execsql COMMIT
} {}
do_test 23.7 {
  catchsql "BEGIN; UPDATE t2 SET c=2 WHERE d=4" ; execsql COMMIT
} {}
do_test 23.8 {
  catchsql "BEGIN; UPDATE t2 SET c=1 WHERE d=4" ; execsql COMMIT
} {}
do_test 23.9 {
  catchsql "BEGIN; UPDATE t2 SET c=1 WHERE d=4" ; execsql COMMIT
} {}
do_test 23.10 {
  catchsql "BEGIN; UPDATE t2 SET c=NULL WHERE d=4" ; execsql COMMIT
} {}
do_test 23.11 {
  execsql BEGIN
  catchsql "DELETE FROM t1 WHERE a=1"
  execsql COMMIT
} {}

do_catchsql_test 23.3 {
  BEGIN;
    UPDATE t1 SET a = 2;
  COMMIT;
} {1 {foreign key constraint failed}}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 24.1 {
  CREATE TABLE p(x INTEGER);
  INSERT INTO p VALUES(35.0);
  SELECT typeof(x) FROM p;
} {integer}

do_execsql_test 24.2 {
  CREATE TABLE p2(x INTEGER PRIMARY KEY);
  INSERT INTO p2 VALUES(35.0);
  SELECT typeof(x) FROM p2;
} {integer}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 25.1 {
  PRAGMA foreign_keys = on;
  CREATE TABLE p(x INT PRIMARY KEY);
  CREATE TABLE c(y REFERENCES p);
  INSERT INTO p VALUES(35);
PRAGMA vdbe_trace = 1;
  INSERT INTO c VALUES(35.0);
}
execsql { PRAGMA vdbe_trace = 0; }

explain {
  INSERT INTO c VALUES(35.0);
}
finish_test

#-------------------------------------------------------------------------
reset_db
do_execsql_test 26.1 {
  PRAGMA foreign_keys = on;
  CREATE TABLE p(x INT PRIMARY KEY);
  CREATE TABLE c(y REFERENCES p);
  INSERT INTO p VALUES(35.0);
  INSERT INTO c VALUES(35.0);
}

finish_test

#proc populate_t1 {} {
#  db eval {
#    INSERT INTO t1(a, b) VALUES(4, 'four');
#    INSERT INTO t1(a, b) VALUES(9, 'nine');