SQLite

Check-in [9fa904d94e]
Login

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

Overview
Comment:Simplification of the trigger code. (CVS 1976)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9fa904d94ec1787bc8b97ec06a5423248fcb67fb
User & Date: drh 2004-09-24 12:24:36.000
Context
2004-09-24
12:48
Avoid a segfault in sqlite3_bind_parameter_index when there are unnamed parameters. Ticket #918. (CVS 1977) (check-in: 49f25ddf83 user: drh tags: trunk)
12:24
Simplification of the trigger code. (CVS 1976) (check-in: 9fa904d94e user: drh tags: trunk)
12:24
Fix for tickets #912 and #922. Problem introduced by check-in (1973). (CVS 1975) (check-in: 9001e2220d user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/trigger.c.
646
647
648
649
650
651
652

653
654
655
656
657
658
659
  TriggerStep * pTriggerStep = pStepList;
  int orconf;
  Vdbe *v = pParse->pVdbe;

  assert( pTriggerStep!=0 );
  assert( v!=0 );
  sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);

  while( pTriggerStep ){
    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
    pParse->trigStack->orconf = orconf;
    switch( pTriggerStep->op ){
      case TK_SELECT: {
	Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);		  
	assert(ss);







>







646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
  TriggerStep * pTriggerStep = pStepList;
  int orconf;
  Vdbe *v = pParse->pVdbe;

  assert( pTriggerStep!=0 );
  assert( v!=0 );
  sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);
  VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name));
  while( pTriggerStep ){
    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
    pParse->trigStack->orconf = orconf;
    switch( pTriggerStep->op ){
      case TK_SELECT: {
	Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);		  
	assert(ss);
693
694
695
696
697
698
699

700
701
702
703
704
705
706
      }
      default:
        assert(0);
    } 
    pTriggerStep = pTriggerStep->pNext;
  }
  sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);


  return 0;
}

/*
** This is called to code FOR EACH ROW triggers.
**







>







694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
      }
      default:
        assert(0);
    } 
    pTriggerStep = pTriggerStep->pNext;
  }
  sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
  VdbeComment((v, "# end trigger %s", pStepList->pTrig->name));

  return 0;
}

/*
** This is called to code FOR EACH ROW triggers.
**
728
729
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  int tr_tm,           /* One of TK_BEFORE, TK_AFTER */
  Table *pTab,         /* The table to code triggers from */
  int newIdx,          /* The indice of the "new" row to access */
  int oldIdx,          /* The indice of the "old" row to access */
  int orconf,          /* ON CONFLICT policy */
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
){
  Trigger * pTrigger;
  TriggerStack * pTriggerStack;


  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );

  assert(newIdx != -1 || oldIdx != -1);

  pTrigger = pTab->pTrigger;
  while( pTrigger ){
    int fire_this = 0;

    /* determine whether we should code this trigger */
    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && 
        pTrigger->foreach == TK_ROW ){
      fire_this = 1;
      pTriggerStack = pParse->trigStack;
      while( pTriggerStack ){
        if( pTriggerStack->pTrigger == pTrigger ){
	  fire_this = 0;
	}
        pTriggerStack = pTriggerStack->pNext;
      }
      if( op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
        fire_this = 0;
      }
    }
 
    /* FIX ME:  Can we not omit the sqliteMalloc() and make pTriggerStack
    ** point to a stack variable?
    */
    if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
      int endTrigger;
      SrcList dummyTablist;
      Expr * whenExpr;
      AuthContext sContext;

      dummyTablist.nSrc = 0;

      /* Push an entry on to the trigger stack */
      pTriggerStack->pTrigger = pTrigger;
      pTriggerStack->newIdx = newIdx;
      pTriggerStack->oldIdx = oldIdx;
      pTriggerStack->pTab = pTab;
      pTriggerStack->pNext = pParse->trigStack;
      pTriggerStack->ignoreJump = ignoreJump;
      pParse->trigStack = pTriggerStack;
      sqlite3AuthContextPush(pParse, &sContext, pTrigger->name);

      /* code the WHEN clause */
      endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
      whenExpr = sqlite3ExprDup(pTrigger->pWhen);
      if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
        pParse->trigStack = pParse->trigStack->pNext;
        sqliteFree(pTriggerStack);
        sqlite3ExprDelete(whenExpr);
        return 1;
      }
      sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
      sqlite3ExprDelete(whenExpr);

      codeTriggerProgram(pParse, pTrigger->step_list, orconf); 

      /* Pop the entry off the trigger stack */
      pParse->trigStack = pParse->trigStack->pNext;
      sqlite3AuthContextPop(&sContext);
      sqliteFree(pTriggerStack);

      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
    }
    pTrigger = pTrigger->pNext;
  }
  return 0;
}







|
|
>














|
<
|


<







<
<
<
|








|
|
|
|
|
|
|






|
<









|

<







730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754

755
756
757

758
759
760
761
762
763
764



765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805
  int tr_tm,           /* One of TK_BEFORE, TK_AFTER */
  Table *pTab,         /* The table to code triggers from */
  int newIdx,          /* The indice of the "new" row to access */
  int oldIdx,          /* The indice of the "old" row to access */
  int orconf,          /* ON CONFLICT policy */
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
){
  Trigger *pTrigger;
  TriggerStack *pStack;
  TriggerStack trigStackEntry;

  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );

  assert(newIdx != -1 || oldIdx != -1);

  pTrigger = pTab->pTrigger;
  while( pTrigger ){
    int fire_this = 0;

    /* determine whether we should code this trigger */
    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && 
        pTrigger->foreach == TK_ROW ){
      fire_this = 1;
      for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){

        if( pStack->pTrigger==pTrigger ){
	  fire_this = 0;
	}

      }
      if( op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
        fire_this = 0;
      }
    }
 



    if( fire_this ){
      int endTrigger;
      SrcList dummyTablist;
      Expr * whenExpr;
      AuthContext sContext;

      dummyTablist.nSrc = 0;

      /* Push an entry on to the trigger stack */
      trigStackEntry.pTrigger = pTrigger;
      trigStackEntry.newIdx = newIdx;
      trigStackEntry.oldIdx = oldIdx;
      trigStackEntry.pTab = pTab;
      trigStackEntry.pNext = pParse->trigStack;
      trigStackEntry.ignoreJump = ignoreJump;
      pParse->trigStack = &trigStackEntry;
      sqlite3AuthContextPush(pParse, &sContext, pTrigger->name);

      /* code the WHEN clause */
      endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
      whenExpr = sqlite3ExprDup(pTrigger->pWhen);
      if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
        pParse->trigStack = trigStackEntry.pNext;

        sqlite3ExprDelete(whenExpr);
        return 1;
      }
      sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
      sqlite3ExprDelete(whenExpr);

      codeTriggerProgram(pParse, pTrigger->step_list, orconf); 

      /* Pop the entry off the trigger stack */
      pParse->trigStack = trigStackEntry.pNext;
      sqlite3AuthContextPop(&sContext);


      sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
    }
    pTrigger = pTrigger->pNext;
  }
  return 0;
}