Beispiel #1
0
        public static TriggerStep TriggerDeleteStep(Context ctx, Token tableName, Expr where_)
        {
            TriggerStep triggerStep = TriggerStepAllocate(ctx, TK.DELETE, tableName);

            if (triggerStep != null)
            {
                triggerStep.Where  = Expr.Dup(ctx, where_, E.EXPRDUP_REDUCE);
                triggerStep.Orconf = OE.Default;
            }
            Expr.Delete(ctx, ref where_);
            return(triggerStep);
        }
Beispiel #2
0
 static void FKTriggerDelete(Context ctx, Trigger p)
 {
     if (p != null)
     {
         TriggerStep step = p.StepList;
         Expr.Delete(ctx, ref step.Where);
         Expr.ListDelete(ctx, ref step.ExprList);
         Select.Delete(ctx, ref step.Select);
         Expr.Delete(ctx, ref p.When);
         C._tagfree(ctx, ref p);
     }
 }
Beispiel #3
0
 public bool FixTriggerStep(TriggerStep step)
 {
     while (step != null)
     {
         if (FixSelect(step.Select) || FixExpr(step.Where) || FixExprList(step.ExprList))
         {
             return(true);
         }
         step = step.Next;
     }
     return(false);
 }
Beispiel #4
0
        static TriggerStep TriggerStepAllocate(Context ctx, TK op, Token name)
        {
            TriggerStep triggerStep = new TriggerStep(); //: _tagalloc(ctx, sizeof(TriggerStep) + name->length, true);

            if (triggerStep != null)
            {
                string z = name.data;
                triggerStep.Target.data   = z;
                triggerStep.Target.length = name.length;
                triggerStep.OP            = op;
            }
            return(triggerStep);
        }
Beispiel #5
0
        public static TriggerStep SelectStep(Context ctx, Select select)
        {
            TriggerStep triggerStep = new TriggerStep(); //: _tagalloc(ctx, sizeof(TriggerStep), true);

            if (triggerStep == null)
            {
                Select.Delete(ctx, ref select);
                return(null);
            }
            triggerStep.OP     = TK.SELECT;
            triggerStep.Select = select;
            triggerStep.Orconf = OE.Default;
            return(triggerStep);
        }
Beispiel #6
0
        public static TriggerStep TriggerUpdateStep(Context ctx, Token tableName, ExprList list, Expr where, OE orconf)
        {
            TriggerStep triggerStep = TriggerStepAllocate(ctx, TK.UPDATE, tableName);

            if (triggerStep != null)
            {
                triggerStep.ExprList = Expr.ListDup(ctx, list, E.EXPRDUP_REDUCE);
                triggerStep.Where    = Expr.Dup(ctx, where, E.EXPRDUP_REDUCE);
                triggerStep.Orconf   = orconf;
            }
            Expr.ListDelete(ctx, ref list);
            Expr.Delete(ctx, ref where);
            return(triggerStep);
        }
        public static PlayerActionEvents ValidateStep(
            this TriggerStep triggerStep,
            PlayerActionEvents currentPlayerActions,
            PlayerActionEvents participatingPlayerActions
            )
        {
            var stepPlayerActions = new PlayerActionEvents();

#pragma warning disable CS0219 // Variable is assigned but its value is never used
            bool contains;
#pragma warning restore CS0219 // Variable is assigned but its value is never used

            foreach (var action in currentPlayerActions)
            {
                foreach (var rule in triggerStep.ActionOccurrenceRules)
                {
                    if (
                        action.OccurredAt != null &&
                        rule.InsideOf.Contains(new Point(
                                                   new Coordinate(
                                                       action.OccurredAt.Coordinate.CoordinateValue.X,
                                                       action.OccurredAt.Coordinate.CoordinateValue.Y
                                                       )
                                                   )))
                    {
                        contains = true;

                        if (!stepPlayerActions.Exists(e => e.ActionRefId.Equals(action.ActionRefId)))
                        {
                            stepPlayerActions.Add(action);
                        }
                    }
                }
            }

            // logic to validate other than geofence

            // add stepPlayerActions to participatingPlayerActions
            foreach (var action in stepPlayerActions)
            {
                action.TriggerStepRefId = triggerStep.TriggerStepRefId;

                if (!participatingPlayerActions.Exists(e => e.ActionRefId.Equals(action.ActionRefId)))
                {
                    participatingPlayerActions.Add(action);
                }
            }

            return(participatingPlayerActions);
        }
Beispiel #8
0
        /*
        ** Turn a SELECT statement (that the pSelect parameter points to) into
        ** a trigger step.  Return a pointer to a TriggerStep structure.
        **
        ** The parser calls this routine when it finds a SELECT statement in
        ** body of a TRIGGER.
        */
        static TriggerStep sqlite3TriggerSelectStep(sqlite3 db, Select pSelect)
        {
            TriggerStep pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof(TriggerStep ))

            if (pTriggerStep == null)
            {
                sqlite3SelectDelete(db, ref pSelect);
                return(null);
            }

            pTriggerStep.op      = TK_SELECT;
            pTriggerStep.pSelect = pSelect;
            pTriggerStep.orconf  = OE_Default;
            return(pTriggerStep);
        }
Beispiel #9
0
        /*
        **
        ** The author disclaims copyright to this source code.  In place of
        ** a legal notice, here is a blessing:
        **
        **    May you do good and not evil.
        **    May you find forgiveness for yourself and forgive others.
        **    May you share freely, never taking more than you give.
        **
        *************************************************************************
        **
        **
        ** $Id: trigger.c,v 1.143 2009/08/10 03:57:58 shane Exp $
        **
        *************************************************************************
        **  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
        **  C#-SQLite is an independent reimplementation of the SQLite software library
        **
        **  $Header$
        *************************************************************************
        */
        //#include "sqliteInt.h"

#if !SQLITE_OMIT_TRIGGER
        /*
        ** Delete a linked list of TriggerStep structures.
        */
        static void sqlite3DeleteTriggerStep(sqlite3 db, ref TriggerStep pTriggerStep)
        {
            while (pTriggerStep != null)
            {
                TriggerStep pTmp = pTriggerStep;
                pTriggerStep = pTriggerStep.pNext;

                sqlite3ExprDelete(db, ref pTmp.pWhere);
                sqlite3ExprListDelete(db, ref pTmp.pExprList);
                sqlite3SelectDelete(db, ref pTmp.pSelect);
                sqlite3IdListDelete(db, ref pTmp.pIdList);

                pTriggerStep = null;//sqlite3DbFree( db, ref pTmp );
            }
        }
    /*
    **
    ** The author disclaims copyright to this source code.  In place of
    ** a legal notice, here is a blessing:
    **
    **    May you do good and not evil.
    **    May you find forgiveness for yourself and forgive others.
    **    May you share freely, never taking more than you give.
    **
    *************************************************************************
    ** This file contains the implementation for TRIGGERs
    *************************************************************************
    **  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
    **  C#-SQLite is an independent reimplementation of the SQLite software library
    **
    **  SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
    **
    **  $Header: Community.CsharpSqlite/src/trigger_c.cs,v 6604176a7dbe 2010/03/12 23:35:36 Noah $
    *************************************************************************
    */
    //#include "sqliteInt.h"

#if !SQLITE_OMIT_TRIGGER
    /*
** Delete a linked list of TriggerStep structures.
*/
    static void sqlite3DeleteTriggerStep( sqlite3 db, ref TriggerStep pTriggerStep )
    {
      while ( pTriggerStep != null )
      {
        TriggerStep pTmp = pTriggerStep;
        pTriggerStep = pTriggerStep.pNext;

        sqlite3ExprDelete( db, ref pTmp.pWhere );
        sqlite3ExprListDelete( db, ref pTmp.pExprList );
        sqlite3SelectDelete( db, ref pTmp.pSelect );
        sqlite3IdListDelete( db, ref pTmp.pIdList );

        pTriggerStep = null;sqlite3DbFree( db, ref pTmp );
      }
    }
Beispiel #11
0
        public static void DeleteTriggerStep(Context ctx, ref TriggerStep triggerStep)
        {
            while (triggerStep != null)
            {
                TriggerStep tmp = triggerStep;
                triggerStep = triggerStep.Next;

                Expr.Delete(ctx, ref tmp.Where);
                Expr.ListDelete(ctx, ref tmp.ExprList);
                Select.Delete(ctx, ref tmp.Select);
                Parse.IdListDelete(ctx, ref tmp.IdList);
                
                C._tagfree(ctx, ref tmp);
                triggerStep = null; //: C#
            }
        }
Beispiel #12
0
        public static void DeleteTriggerStep(Context ctx, ref TriggerStep triggerStep)
        {
            while (triggerStep != null)
            {
                TriggerStep tmp = triggerStep;
                triggerStep = triggerStep.Next;

                Expr.Delete(ctx, ref tmp.Where);
                Expr.ListDelete(ctx, ref tmp.ExprList);
                Select.Delete(ctx, ref tmp.Select);
                Parse.IdListDelete(ctx, ref tmp.IdList);

                C._tagfree(ctx, ref tmp);
                triggerStep = null; //: C#
            }
        }
Beispiel #13
0
        static SrcList TargetSrcList(Parse parse, TriggerStep step)
        {
            Context ctx = parse.Ctx;
            SrcList src = Parse.SrcListAppend(parse.Ctx, null, step.Target, null); // SrcList to be returned

            if (src != null)
            {
                Debug.Assert(src.Srcs > 0);
                Debug.Assert(src.Ids != null);
                int db = Prepare.SchemaToIndex(ctx, step.Trig.Schema); // Index of the database to use
                if (db == 0 || db >= 2)
                {
                    Debug.Assert(db < ctx.DBs.length);
                    src.Ids[src.Srcs - 1].Database = ctx.DBs[db].Name; //: _tagstrdup(ctx, ctx->DBs[db].Name);
                }
            }
            return(src);
        }
Beispiel #14
0
        /*
        ** Allocate space to hold a new trigger step.  The allocated space
        ** holds both the TriggerStep object and the TriggerStep.target.z string.
        **
        ** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
        */
        static TriggerStep triggerStepAllocate(
            sqlite3 db,        /* Database connection */
            u8 op,             /* Trigger opcode */
            Token pName        /* The target name */
            )
        {
            TriggerStep pTriggerStep;

            pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof( TriggerStep ) + pName.n );
            //if ( pTriggerStep != null )
            //{
            string z;    // = (char*)&pTriggerStep[1];

            z = pName.z; // memcpy( z, pName.z, pName.n );
            pTriggerStep.target.z = z;
            pTriggerStep.target.n = pName.n;
            pTriggerStep.op       = op;
            //}
            return(pTriggerStep);
        }
Beispiel #15
0
        public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, ExprList list, Select select, OE orconf)
        {
            Debug.Assert(list == null || select == null);
            Debug.Assert(list != null || select != null || ctx.MallocFailed);
            TriggerStep triggerStep = TriggerStepAllocate(ctx, TK.INSERT, tableName);

            if (triggerStep != null)
            {
                triggerStep.Select   = Select.Dup(ctx, select, E.EXPRDUP_REDUCE);
                triggerStep.IdList   = column;
                triggerStep.ExprList = Expr.ListDup(ctx, list, E.EXPRDUP_REDUCE);
                triggerStep.Orconf   = orconf;
            }
            else
            {
                Expr.IdListDelete(ctx, ref column);
            }
            Expr.ListDelete(ctx, ref list);
            Select.Delete(ctx, ref select);
            return(triggerStep);
        }
Beispiel #16
0
        /*
        ** Convert the pStep.target token into a SrcList and return a pointer
        ** to that SrcList.
        **
        ** This routine adds a specific database name, if needed, to the target when
        ** forming the SrcList.  This prevents a trigger in one database from
        ** referring to a target in another database.  An exception is when the
        ** trigger is in TEMP in which case it can refer to any other database it
        ** wants.
        */
        static SrcList targetSrcList(
            Parse pParse,     /* The parsing context */
            TriggerStep pStep /* The trigger containing the target token */
            )
        {
            int     iDb;   /* Index of the database to use */
            SrcList pSrc;  /* SrcList to be returned */

            pSrc = sqlite3SrcListAppend(pParse.db, 0, pStep.target, 0);
            //if ( pSrc != null )
            //{
            Debug.Assert(pSrc.nSrc > 0);
            Debug.Assert(pSrc.a != null);
            iDb = sqlite3SchemaToIndex(pParse.db, pStep.pTrig.pSchema);
            if (iDb == 0 || iDb >= 2)
            {
                sqlite3 db = pParse.db;
                Debug.Assert(iDb < pParse.db.nDb);
                pSrc.a[pSrc.nSrc - 1].zDatabase = db.aDb[iDb].zName;// sqlite3DbStrDup( db, db.aDb[iDb].zName );
            }
            //}
            return(pSrc);
        }
 static int sqlite3FixTriggerStep(
     DbFixer pFix,     /* Context of the fixation */
     TriggerStep pStep /* The trigger step be fixed to one database */
     )
 {
     while (pStep != null)
     {
         if (sqlite3FixSelect(pFix, pStep.pSelect) != 0)
         {
             return(1);
         }
         if (sqlite3FixExpr(pFix, pStep.pWhere) != 0)
         {
             return(1);
         }
         if (sqlite3FixExprList(pFix, pStep.pExprList) != 0)
         {
             return(1);
         }
         pStep = pStep.pNext;
     }
     return(0);
 }
Beispiel #18
0
 static TriggerStep TriggerStepAllocate(Context ctx, TK op, Token name)
 {
     TriggerStep triggerStep = new TriggerStep(); //: _tagalloc(ctx, sizeof(TriggerStep) + name->length, true);
     if (triggerStep != null)
     {
         string z = name.data;
         triggerStep.Target.data = z;
         triggerStep.Target.length = name.length;
         triggerStep.OP = op;
     }
     return triggerStep;
 }
Beispiel #19
0
        /*
        ** This routine is called after all of the trigger actions have been parsed
        ** in order to complete the process of building the trigger.
        */
        static void sqlite3FinishTrigger(
            Parse pParse,          /* Parser context */
            TriggerStep pStepList, /* The triggered program */
            Token pAll             /* Token that describes the complete CREATE TRIGGER */
            )
        {
            Trigger pTrig = pParse.pNewTrigger; /* Trigger being finished */
            string  zName;                      /* Name of trigger */

            sqlite3 db   = pParse.db;           /* The database */
            DbFixer sFix = new DbFixer();
            int     iDb;                        /* Database containing the trigger */
            Token   nameToken = new Token();    /* Trigger name for error reporting */

            pTrig = pParse.pNewTrigger;
            pParse.pNewTrigger = null;
            if (NEVER(pParse.nErr != 0) || pTrig == null)
            {
                goto triggerfinish_cleanup;
            }
            zName           = pTrig.name;
            iDb             = sqlite3SchemaToIndex(pParse.db, pTrig.pSchema);
            pTrig.step_list = pStepList;
            while (pStepList != null)
            {
                pStepList.pTrig = pTrig;
                pStepList       = pStepList.pNext;
            }
            nameToken.z = pTrig.name;
            nameToken.n = sqlite3Strlen30(nameToken.z);
            if (sqlite3FixInit(sFix, pParse, iDb, "trigger", nameToken) != 0 &&
                sqlite3FixTriggerStep(sFix, pTrig.step_list) != 0)
            {
                goto triggerfinish_cleanup;
            }

            /* if we are not initializing, and this trigger is not on a TEMP table,
            ** build the sqlite_master entry
            */
            if (0 == db.init.busy)
            {
                Vdbe   v;
                string z;

                /* Make an entry in the sqlite_master table */
                v = sqlite3GetVdbe(pParse);
                if (v == null)
                {
                    goto triggerfinish_cleanup;
                }
                sqlite3BeginWriteOperation(pParse, 0, iDb);
                z = pAll.z.Substring(0, pAll.n);//sqlite3DbStrNDup( db, (char*)pAll.z, pAll.n );
                sqlite3NestedParse(pParse,
                                   "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
                                   db.aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
                                   pTrig.table, z);
                //sqlite3DbFree( db, ref z );
                sqlite3ChangeCookie(pParse, iDb);
                sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
                                      db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
                                  );
            }

            if (db.init.busy != 0)
            {
                Trigger pLink = pTrig;
                Hash    pHash = db.aDb[iDb].pSchema.trigHash;
                pTrig = (Trigger)sqlite3HashInsert(ref pHash, zName, sqlite3Strlen30(zName), pTrig);
                if (pTrig != null)
                {
                    //db.mallocFailed = 1;
                }
                else if (pLink.pSchema == pLink.pTabSchema)
                {
                    Table pTab;
                    int   n = sqlite3Strlen30(pLink.table);
                    pTab = (Table)sqlite3HashFind(pLink.pTabSchema.tblHash, pLink.table, n);
                    Debug.Assert(pTab != null);
                    pLink.pNext   = pTab.pTrigger;
                    pTab.pTrigger = pLink;
                }
            }

triggerfinish_cleanup:
            sqlite3DeleteTrigger(db, ref pTrig);
            Debug.Assert(pParse.pNewTrigger == null);
            sqlite3DeleteTriggerStep(db, ref pStepList);
        }
Beispiel #20
0
        static int CodeTriggerProgram(Parse parse, TriggerStep stepList, OE orconf)
        {
            Vdbe    v   = parse.V;
            Context ctx = parse.Ctx;

            Debug.Assert(parse.TriggerTab != null && parse.Toplevel != null);
            Debug.Assert(stepList != null);
            Debug.Assert(v != null);
            for (TriggerStep step = stepList; step != null; step = step.Next)
            {
                // Figure out the ON CONFLICT policy that will be used for this step of the trigger program. If the statement that caused this trigger
                // to fire had an explicit ON CONFLICT, then use it. Otherwise, use the ON CONFLICT policy that was specified as part of the trigger
                // step statement. Example:
                //
                //   CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
                //     INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
                //   END;
                //
                //   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
                //   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
                parse.Orconf = (orconf == OE.Default ? step.Orconf : orconf);

                switch (step.OP)
                {
                case TK.UPDATE:
                    Update(parse,
                           TargetSrcList(parse, step),
                           Expr.ListDup(ctx, step.ExprList, 0),
                           Expr.Dup(ctx, step.Where, 0),
                           parse.Orconf);
                    break;

                case TK.INSERT:
                    Insert(parse,
                           TargetSrcList(parse, step),
                           Expr.ListDup(ctx, step.ExprList, 0),
                           Select.Dup(ctx, step.Select, 0),
                           Expr.IdListDup(ctx, step.IdList),
                           parse.Orconf);
                    break;

                case TK.DELETE:
                    DeleteFrom(parse,
                               TargetSrcList(parse, step),
                               Expr.Dup(ctx, step.Where, 0));
                    break;

                default:
                    Debug.Assert(step.OP == TK.SELECT);
                    SelectDest sDest  = new SelectDest();
                    Select     select = Expr.SelectDup(ctx, step.Select, 0);
                    Select.DestInit(sDest, SRT.Discard, 0);
                    Select.Select_(parse, select, ref sDest);
                    Select.Delete(ctx, ref select);
                    break;
                }
                if (step.OP != TK.SELECT)
                {
                    v.AddOp0(OP.ResetCount);
                }
            }
            return(0);
        }
Beispiel #21
0
        /*
        ** Generate VDBE code for zero or more statements inside the body of a
        ** trigger.
        */
        static int codeTriggerProgram(
            Parse pParse,          /* The parser context */
            TriggerStep pStepList, /* List of statements inside the trigger body */
            int orconfin           /* Conflict algorithm. (OE_Abort, etc) */
            )
        {
            TriggerStep pTriggerStep = pStepList;
            int         orconf;
            Vdbe        v  = pParse.pVdbe;
            sqlite3     db = pParse.db;

            Debug.Assert(pTriggerStep != null);
            Debug.Assert(v != null);
            sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0);
#if SQLITE_DEBUG
            VdbeComment(v, "begin trigger %s", pStepList.pTrig.name);
#endif
            while (pTriggerStep != null)
            {
                sqlite3ExprCacheClear(pParse);
                orconf = (orconfin == OE_Default) ? pTriggerStep.orconf : orconfin;
                pParse.trigStack.orconf = orconf;
                switch (pTriggerStep.op)
                {
                case TK_UPDATE:
                {
                    SrcList pSrc;
                    pSrc = targetSrcList(pParse, pTriggerStep);
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
                    sqlite3Update(pParse, pSrc,
                                  sqlite3ExprListDup(db, pTriggerStep.pExprList, 0),
                                  sqlite3ExprDup(db, pTriggerStep.pWhere, 0), orconf);
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
                    break;
                }

                case TK_INSERT:
                {
                    SrcList pSrc;
                    pSrc = targetSrcList(pParse, pTriggerStep);
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
                    sqlite3Insert(pParse, pSrc,
                                  sqlite3ExprListDup(db, pTriggerStep.pExprList, 0),
                                  sqlite3SelectDup(db, pTriggerStep.pSelect, 0),
                                  sqlite3IdListDup(db, pTriggerStep.pIdList), orconf);
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
                    break;
                }

                case TK_DELETE:
                {
                    SrcList pSrc;
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
                    pSrc = targetSrcList(pParse, pTriggerStep);
                    sqlite3DeleteFrom(pParse, pSrc,
                                      sqlite3ExprDup(db, pTriggerStep.pWhere, 0));
                    sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
                    break;
                }

                default: Debug.Assert(pTriggerStep.op == TK_SELECT);
                    {
                        Select ss = sqlite3SelectDup(db, pTriggerStep.pSelect, 0);
                        if (ss != null)
                        {
                            SelectDest dest = new SelectDest();

                            sqlite3SelectDestInit(dest, SRT_Discard, 0);
                            sqlite3Select(pParse, ss, ref dest);
                            sqlite3SelectDelete(db, ref ss);
                        }
                        break;
                    }
                }
                pTriggerStep = pTriggerStep.pNext;
            }
            sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
#if SQLITE_DEBUG
            VdbeComment(v, "end trigger %s", pStepList.pTrig.name);
#endif
            return(0);
        }
Beispiel #22
0
        static Trigger FKActionTrigger(Parse parse, Table table, FKey fkey, ExprList changes)
        {
            Context ctx      = parse.Ctx;                 // Database handle
            int     actionId = (changes != null ? 1 : 0); // 1 for UPDATE, 0 for DELETE
            OE      action   = fkey.Actions[actionId];    // One of OE_None, OE_Cascade etc.
            Trigger trigger  = fkey.Triggers[actionId];   // Trigger definition to return

            if (action != OE.None && trigger == null)
            {
                Index index = null; // Parent key index for this FK
                int[] cols  = null; // child table cols . parent key cols
                if (LocateFkeyIndex(parse, table, fkey, out index, out cols) != 0)
                {
                    return(null);
                }
                Debug.Assert(cols != null || fkey.Cols.length == 1);

                Expr     where_ = null; // WHERE clause of trigger step
                Expr     when   = null; // WHEN clause for the trigger
                ExprList list   = null; // Changes list if ON UPDATE CASCADE
                for (int i = 0; i < fkey.Cols.length; i++)
                {
                    Token oldToken = new Token("old", 3);                         // Literal "old" token
                    Token newToken = new Token("new", 3);                         // Literal "new" token

                    int fromColId = (cols != null ? cols[i] : fkey.Cols[0].From); // Idx of column in child table
                    Debug.Assert(fromColId >= 0);
                    Token fromCol = new Token();                                  // Name of column in child table
                    Token toCol   = new Token();                                  // Name of column in parent table
                    toCol.data     = (index != null ? table.Cols[index.Columns[i]].Name : "oid");
                    fromCol.data   = fkey.From.Cols[fromColId].Name;
                    toCol.length   = (uint)toCol.data.Length;
                    fromCol.length = (uint)fromCol.data.Length;

                    // Create the expression "OLD.zToCol = zFromCol". It is important that the "OLD.zToCol" term is on the LHS of the = operator, so
                    // that the affinity and collation sequence associated with the parent table are used for the comparison.
                    Expr eq = Expr.PExpr(parse, TK.EQ,
                                         Expr.PExpr(parse, TK.DOT,
                                                    Expr.PExpr(parse, TK.ID, null, null, oldToken),
                                                    Expr.PExpr(parse, TK.ID, null, null, toCol)
                                                    , 0),
                                         Expr.PExpr(parse, TK.ID, null, null, fromCol)
                                         , 0); // tFromCol = OLD.tToCol
                    where_ = Expr.And(ctx, where_, eq);

                    // For ON UPDATE, construct the next term of the WHEN clause. The final WHEN clause will be like this:
                    //
                    //    WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
                    if (changes != null)
                    {
                        eq = Expr.PExpr(parse, TK.IS,
                                        Expr.PExpr(parse, TK.DOT,
                                                   Expr.PExpr(parse, TK.ID, null, null, oldToken),
                                                   Expr.PExpr(parse, TK.ID, null, null, toCol),
                                                   0),
                                        Expr.PExpr(parse, TK.DOT,
                                                   Expr.PExpr(parse, TK.ID, null, null, newToken),
                                                   Expr.PExpr(parse, TK.ID, null, null, toCol),
                                                   0),
                                        0);
                        when = Expr.And(ctx, when, eq);
                    }

                    if (action != OE.Restrict && (action != OE.Cascade || changes != null))
                    {
                        Expr newExpr;
                        if (action == OE.Cascade)
                        {
                            newExpr = Expr.PExpr(parse, TK.DOT,
                                                 Expr.PExpr(parse, TK.ID, null, null, newToken),
                                                 Expr.PExpr(parse, TK.ID, null, null, toCol)
                                                 , 0);
                        }
                        else if (action == OE.SetDflt)
                        {
                            Expr dfltExpr = fkey.From.Cols[fromColId].Dflt;
                            if (dfltExpr != null)
                            {
                                newExpr = Expr.Dup(ctx, dfltExpr, 0);
                            }
                            else
                            {
                                newExpr = Expr.PExpr(parse, TK.NULL, 0, 0, 0);
                            }
                        }
                        else
                        {
                            newExpr = Expr.PExpr(parse, TK.NULL, 0, 0, 0);
                        }
                        list = Expr.ListAppend(parse, list, newExpr);
                        Expr.ListSetName(parse, list, fromCol, 0);
                    }
                }
                C._tagfree(ctx, ref cols);

                string fromName       = fkey.From.Name;  // Name of child table
                int    fromNameLength = fromName.Length; // Length in bytes of zFrom

                Select select = null;                    // If RESTRICT, "SELECT RAISE(...)"
                if (action == OE.Restrict)
                {
                    Token from = new Token();
                    from.data   = fromName;
                    from.length = fromNameLength;
                    Expr raise = Expr.Expr(ctx, TK.RAISE, "foreign key constraint failed");
                    if (raise != null)
                    {
                        raise.Affinity = OE.Abort;
                    }
                    select = Select.New(parse,
                                        Expr.ListAppend(parse, 0, raise),
                                        SrcListAppend(ctx, 0, from, null),
                                        where_,
                                        null, null, null, 0, null, null);
                    where_ = null;
                }

                // Disable lookaside memory allocation
                bool enableLookaside = ctx.Lookaside.Enabled; // Copy of ctx->lookaside.bEnabled
                ctx.Lookaside.Enabled = false;

                trigger = new Trigger();
                //: trigger = (Trigger *)_tagalloc(ctx,
                //:    sizeof(Trigger) + // Trigger
                //:    sizeof(TriggerStep) + // Single step in trigger program
                //:    fromNameLength + 1 // Space for pStep->target.z
                //:    , true);
                TriggerStep step = null; // First (only) step of trigger program
                if (trigger != null)
                {
                    step               = trigger.StepList = new TriggerStep(); //: (TriggerStep)trigger[1];
                    step.Target.data   = fromName;                             //: (char *)&step[1];
                    step.Target.length = fromNameLength;
                    //: _memcpy((const char *)step->Target.data, fromName, fromNameLength);

                    step.Where    = Expr.Dup(ctx, where_, EXPRDUP_REDUCE);
                    step.ExprList = Expr.ListDup(ctx, list, EXPRDUP_REDUCE);
                    step.Select   = Select.Dup(ctx, select, EXPRDUP_REDUCE);
                    if (when != null)
                    {
                        when         = Expr.PExpr(parse, TK.NOT, when, 0, 0);
                        trigger.When = Expr.Dup(ctx, when, EXPRDUP_REDUCE);
                    }
                }

                // Re-enable the lookaside buffer, if it was disabled earlier.
                ctx.Lookaside.Enabled = enableLookaside;

                Expr.Delete(ctx, ref where_);
                Expr.Delete(ctx, ref when);
                Expr.ListDelete(ctx, ref list);
                Select.Delete(ctx, ref select);
                if (ctx.MallocFailed)
                {
                    FKTriggerDelete(ctx, trigger);
                    return(null);
                }

                switch (action)
                {
                case OE.Restrict:
                    step.OP = TK.SELECT;
                    break;

                case OE.Cascade:
                    if (changes == null)
                    {
                        step.OP = TK.DELETE;
                        break;
                    }
                    goto default;

                default:
                    step.OP = TK.UPDATE;
                    break;
                }
                step.Trigger            = trigger;
                trigger.Schema          = table.Schema;
                trigger.TabSchema       = table.Schema;
                fkey.Triggers[actionId] = trigger;
                trigger.OP = (TK)(changes != null ? TK.UPDATE : TK.DELETE);
            }

            return(trigger);
        }
Beispiel #23
0
 public bool FixTriggerStep(TriggerStep step)
 {
     while (step != null)
     {
         if (FixSelect(step.Select) || FixExpr(step.Where) || FixExprList(step.ExprList))
             return true;
         step = step.Next;
     }
     return false;
 }
Beispiel #24
0
    /*
    ** Convert the pStep.target token into a SrcList and return a pointer
    ** to that SrcList.
    **
    ** This routine adds a specific database name, if needed, to the target when
    ** forming the SrcList.  This prevents a trigger in one database from
    ** referring to a target in another database.  An exception is when the
    ** trigger is in TEMP in which case it can refer to any other database it
    ** wants.
    */
    static SrcList targetSrcList(
    Parse pParse,       /* The parsing context */
    TriggerStep pStep   /* The trigger containing the target token */
    )
    {
      int iDb;             /* Index of the database to use */
      SrcList pSrc;        /* SrcList to be returned */

      pSrc = sqlite3SrcListAppend( pParse.db, 0, pStep.target, 0 );
      //if ( pSrc != null )
      //{
      Debug.Assert( pSrc.nSrc > 0 );
      Debug.Assert( pSrc.a != null );
      iDb = sqlite3SchemaToIndex( pParse.db, pStep.pTrig.pSchema );
      if ( iDb == 0 || iDb >= 2 )
      {
        sqlite3 db = pParse.db;
        Debug.Assert( iDb < pParse.db.nDb );
        pSrc.a[pSrc.nSrc - 1].zDatabase = db.aDb[iDb].zName;// sqlite3DbStrDup( db, db.aDb[iDb].zName );
      }
      //}
      return pSrc;
    }
Beispiel #25
0
    /*
    ** Turn a SELECT statement (that the pSelect parameter points to) into
    ** a trigger step.  Return a pointer to a TriggerStep structure.
    **
    ** The parser calls this routine when it finds a SELECT statement in
    ** body of a TRIGGER.
    */
    static TriggerStep sqlite3TriggerSelectStep( sqlite3 db, Select pSelect )
    {
      TriggerStep pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof(TriggerStep ))
      if ( pTriggerStep == null )
      {
        sqlite3SelectDelete( db, ref pSelect );
        return null;
      }

      pTriggerStep.op = TK_SELECT;
      pTriggerStep.pSelect = pSelect;
      pTriggerStep.orconf = OE_Default;
      return pTriggerStep;
    }
Beispiel #26
0
        public static void FinishTrigger(Parse parse, TriggerStep stepList, Token all)
        {
            Trigger trig = parse.NewTrigger; // Trigger being finished
            Context ctx = parse.Ctx; // The database
            Token nameToken = new Token(); // Trigger name for error reporting

            parse.NewTrigger = null;
            if (C._NEVER(parse.Errs != 0) || trig == null) goto triggerfinish_cleanup;
            string name = trig.Name; // Name of trigger
            int db = Prepare.SchemaToIndex(parse.Ctx, trig.Schema); // Database containing the trigger
            trig.StepList = stepList;
            while (stepList != null)
            {
                stepList.Trig = trig;
                stepList = stepList.Next;
            }
            nameToken.data = trig.Name;
            nameToken.length = (uint)nameToken.data.Length;
            DbFixer sFix = new DbFixer(); // Fixer object
            if (sFix.FixInit(parse, db, "trigger", nameToken) && sFix.FixTriggerStep(trig.StepList))
                goto triggerfinish_cleanup;

            // if we are not initializing, build the sqlite_master entry
            if (ctx.Init.Busy)
            {
                // Make an entry in the sqlite_master table
                Vdbe v = parse.GetVdbe();
                if (v == null) goto triggerfinish_cleanup;
                parse.BeginWriteOperation(0, db);
                string z = all.data.Substring(0, (int)all.length); //: _tagstrndup(ctx, (char *)all->data, all->length);
                parse.NestedParse("INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", ctx.DBs[db].Name, E.SCHEMA_TABLE(db), name, trig.Table, z);
                C._tagfree(ctx, ref z);
                parse.ChangeCookie(db);
                v.AddParseSchemaOp(db, C._mtagprintf(ctx, "type='trigger' AND name='%q'", name));
            }

            if (!ctx.Init.Busy)
            {
                Trigger link = trig;
                Debug.Assert(Btree.SchemaMutexHeld(ctx, db, null));
                trig = ctx.DBs[db].Schema.TriggerHash.Insert(name, name.Length, trig);
                if (trig != null)
                    ctx.MallocFailed = true;
                else if (link.Schema == link.TabSchema)
                {
                    int tableLength = link.Table.Length;
                    Table table = (Table)link.TabSchema.TableHash.Find(link.Table, tableLength, (Table)null);
                    Debug.Assert(table != null);
                    link.Next = table.Triggers;
                    table.Triggers = link;
                }
            }

        triggerfinish_cleanup:
            DeleteTrigger(ctx, ref trig);
            Debug.Assert(parse.NewTrigger == null);
            DeleteTriggerStep(ctx, ref stepList);
        }
Beispiel #27
0
 public static TriggerStep SelectStep(Context ctx, Select select)
 {
     TriggerStep triggerStep = new TriggerStep(); //: _tagalloc(ctx, sizeof(TriggerStep), true);
     if (triggerStep == null)
     {
         Select.Delete(ctx, ref select);
         return null;
     }
     triggerStep.OP = TK.SELECT;
     triggerStep.Select = select;
     triggerStep.Orconf = OE.Default;
     return triggerStep;
 }
Beispiel #28
0
static int sqlite3FixTriggerStep(
DbFixer pFix,     /* Context of the fixation */
TriggerStep pStep /* The trigger step be fixed to one database */
)
{
  while ( pStep != null )
  {
    if ( sqlite3FixSelect( pFix, pStep.pSelect ) != 0 )
    {
      return 1;
    }
    if ( sqlite3FixExpr( pFix, pStep.pWhere ) != 0 )
    {
      return 1;
    }
    if ( sqlite3FixExprList( pFix, pStep.pExprList ) != 0 )
    {
      return 1;
    }
    pStep = pStep.pNext;
  }
  return 0;
}
Beispiel #29
0
 static SrcList TargetSrcList(Parse parse, TriggerStep step)
 {
     Context ctx = parse.Ctx;
     SrcList src = Parse.SrcListAppend(parse.Ctx, null, step.Target, null); // SrcList to be returned
     if (src != null)
     {
         Debug.Assert(src.Srcs > 0);
         Debug.Assert(src.Ids != null);
         int db = Prepare.SchemaToIndex(ctx, step.Trig.Schema); // Index of the database to use
         if (db == 0 || db >= 2)
         {
             Debug.Assert(db < ctx.DBs.length);
             src.Ids[src.Srcs - 1].Database = ctx.DBs[db].Name; //: _tagstrdup(ctx, ctx->DBs[db].Name);
         }
     }
     return src;
 }
Beispiel #30
0
    /*
    ** This routine is called after all of the trigger actions have been parsed
    ** in order to complete the process of building the trigger.
    */
    static void sqlite3FinishTrigger(
    Parse pParse,          /* Parser context */
    TriggerStep pStepList, /* The triggered program */
    Token pAll             /* Token that describes the complete CREATE TRIGGER */
    )
    {
      Trigger pTrig = pParse.pNewTrigger; /* Trigger being finished */
      string zName;                       /* Name of trigger */

      sqlite3 db = pParse.db;             /* The database */
      DbFixer sFix = new DbFixer();       /* Fixer object */
      int iDb;                            /* Database containing the trigger */
      Token nameToken = new Token();      /* Trigger name for error reporting */

      pParse.pNewTrigger = null;
      if ( NEVER( pParse.nErr != 0 ) || pTrig == null )
        goto triggerfinish_cleanup;
      zName = pTrig.zName;
      iDb = sqlite3SchemaToIndex( pParse.db, pTrig.pSchema );
      pTrig.step_list = pStepList;
      while ( pStepList != null )
      {
        pStepList.pTrig = pTrig;
        pStepList = pStepList.pNext;
      }
      nameToken.z = pTrig.zName;
      nameToken.n = sqlite3Strlen30( nameToken.z );
      if ( sqlite3FixInit( sFix, pParse, iDb, "trigger", nameToken ) != 0
      && sqlite3FixTriggerStep( sFix, pTrig.step_list ) != 0 )
      {
        goto triggerfinish_cleanup;
      }

      /* if we are not initializing,
      ** build the sqlite_master entry
      */
      if ( 0 == db.init.busy )
      {
        Vdbe v;
        string z;

        /* Make an entry in the sqlite_master table */
        v = sqlite3GetVdbe( pParse );
        if ( v == null )
          goto triggerfinish_cleanup;
        sqlite3BeginWriteOperation( pParse, 0, iDb );
        z = pAll.z.Substring( 0, pAll.n );//sqlite3DbStrNDup( db, (char*)pAll.z, pAll.n );
        sqlite3NestedParse( pParse,
        "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
        db.aDb[iDb].zName, SCHEMA_TABLE( iDb ), zName,
        pTrig.table, z );
        sqlite3DbFree( db, ref z );
        sqlite3ChangeCookie( pParse, iDb );
        sqlite3VdbeAddParseSchemaOp( v, iDb,
            sqlite3MPrintf( db, "type='trigger' AND name='%q'", zName ) );
      }

      if ( db.init.busy != 0 )
      {
        Trigger pLink = pTrig;
        Hash pHash = db.aDb[iDb].pSchema.trigHash;
        Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
        pTrig = sqlite3HashInsert( ref pHash, zName, sqlite3Strlen30( zName ), pTrig );
        if ( pTrig != null )
        {
          //db.mallocFailed = 1;
        }
        else if ( pLink.pSchema == pLink.pTabSchema )
        {
          Table pTab;
          int n = sqlite3Strlen30( pLink.table );
          pTab = sqlite3HashFind( pLink.pTabSchema.tblHash, pLink.table, n, (Table)null );
          Debug.Assert( pTab != null );
          pLink.pNext = pTab.pTrigger;
          pTab.pTrigger = pLink;
        }
      }

triggerfinish_cleanup:
      sqlite3DeleteTrigger( db, ref pTrig );
      Debug.Assert( pParse.pNewTrigger == null );
      sqlite3DeleteTriggerStep( db, ref pStepList );
    }
Beispiel #31
0
        static int CodeTriggerProgram(Parse parse, TriggerStep stepList, OE orconf)
        {
            Vdbe v = parse.V;
            Context ctx = parse.Ctx;
            Debug.Assert(parse.TriggerTab != null && parse.Toplevel != null);
            Debug.Assert(stepList != null);
            Debug.Assert(v != null);
            for (TriggerStep step = stepList; step != null; step = step.Next)
            {
                // Figure out the ON CONFLICT policy that will be used for this step of the trigger program. If the statement that caused this trigger
                // to fire had an explicit ON CONFLICT, then use it. Otherwise, use the ON CONFLICT policy that was specified as part of the trigger
                // step statement. Example:
                //
                //   CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
                //     INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
                //   END;
                //
                //   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
                //   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
                parse.Orconf = (orconf == OE.Default ? step.Orconf : orconf);

                switch (step.OP)
                {
                    case TK.UPDATE:
                        Update(parse,
                          TargetSrcList(parse, step),
                          Expr.ListDup(ctx, step.ExprList, 0),
                          Expr.Dup(ctx, step.Where, 0),
                          parse.Orconf);
                        break;
                    case TK.INSERT:
                        Insert(parse,
                          TargetSrcList(parse, step),
                          Expr.ListDup(ctx, step.ExprList, 0),
                          Select.Dup(ctx, step.Select, 0),
                          Expr.IdListDup(ctx, step.IdList),
                          parse.Orconf);
                        break;
                    case TK.DELETE:
                        DeleteFrom(parse,
                          TargetSrcList(parse, step),
                          Expr.Dup(ctx, step.Where, 0));
                        break;
                    default:
                        Debug.Assert(step.OP == TK.SELECT);
                        SelectDest sDest = new SelectDest();
                        Select select = Expr.SelectDup(ctx, step.Select, 0);
                        Select.DestInit(sDest, SRT.Discard, 0);
                        Select.Select_(parse, select, ref sDest);
                        Select.Delete(ctx, ref select);
                        break;
                }
                if (step.OP != TK.SELECT)
                    v.AddOp0(OP.ResetCount);
            }
            return 0;
        }
Beispiel #32
0
    /*
    ** Allocate space to hold a new trigger step.  The allocated space
    ** holds both the TriggerStep object and the TriggerStep.target.z string.
    **
    ** If an OOM error occurs, NULL is returned and db.mallocFailed is set.
    */
    static TriggerStep triggerStepAllocate(
    sqlite3 db,                /* Database connection */
    u8 op,                     /* Trigger opcode */
    Token pName                /* The target name */
    )
    {
      TriggerStep pTriggerStep;

      pTriggerStep = new TriggerStep();// sqlite3DbMallocZero( db, sizeof( TriggerStep ) + pName.n );
      //if ( pTriggerStep != null )
      //{
      string z;// = (char*)&pTriggerStep[1];
      z = pName.z;// memcpy( z, pName.z, pName.n );
      pTriggerStep.target.z = z;
      pTriggerStep.target.n = pName.n;
      pTriggerStep.op = op;
      //}
      return pTriggerStep;
    }
Beispiel #33
0
        public static void FinishTrigger(Parse parse, TriggerStep stepList, Token all)
        {
            Trigger trig      = parse.NewTrigger; // Trigger being finished
            Context ctx       = parse.Ctx;        // The database
            Token   nameToken = new Token();      // Trigger name for error reporting

            parse.NewTrigger = null;
            if (C._NEVER(parse.Errs != 0) || trig == null)
            {
                goto triggerfinish_cleanup;
            }
            string name = trig.Name;                                     // Name of trigger
            int    db   = Prepare.SchemaToIndex(parse.Ctx, trig.Schema); // Database containing the trigger

            trig.StepList = stepList;
            while (stepList != null)
            {
                stepList.Trig = trig;
                stepList      = stepList.Next;
            }
            nameToken.data   = trig.Name;
            nameToken.length = (uint)nameToken.data.Length;
            DbFixer sFix = new DbFixer(); // Fixer object

            if (sFix.FixInit(parse, db, "trigger", nameToken) && sFix.FixTriggerStep(trig.StepList))
            {
                goto triggerfinish_cleanup;
            }

            // if we are not initializing, build the sqlite_master entry
            if (ctx.Init.Busy)
            {
                // Make an entry in the sqlite_master table
                Vdbe v = parse.GetVdbe();
                if (v == null)
                {
                    goto triggerfinish_cleanup;
                }
                parse.BeginWriteOperation(0, db);
                string z = all.data.Substring(0, (int)all.length); //: _tagstrndup(ctx, (char *)all->data, all->length);
                parse.NestedParse("INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", ctx.DBs[db].Name, E.SCHEMA_TABLE(db), name, trig.Table, z);
                C._tagfree(ctx, ref z);
                parse.ChangeCookie(db);
                v.AddParseSchemaOp(db, C._mtagprintf(ctx, "type='trigger' AND name='%q'", name));
            }

            if (!ctx.Init.Busy)
            {
                Trigger link = trig;
                Debug.Assert(Btree.SchemaMutexHeld(ctx, db, null));
                trig = ctx.DBs[db].Schema.TriggerHash.Insert(name, name.Length, trig);
                if (trig != null)
                {
                    ctx.MallocFailed = true;
                }
                else if (link.Schema == link.TabSchema)
                {
                    int   tableLength = link.Table.Length;
                    Table table       = (Table)link.TabSchema.TableHash.Find(link.Table, tableLength, (Table)null);
                    Debug.Assert(table != null);
                    link.Next      = table.Triggers;
                    table.Triggers = link;
                }
            }

triggerfinish_cleanup:
            DeleteTrigger(ctx, ref trig);
            Debug.Assert(parse.NewTrigger == null);
            DeleteTriggerStep(ctx, ref stepList);
        }
Beispiel #34
0
    /*
    ** Generate VDBE code for the statements inside the body of a single 
    ** trigger.
    */
    static int codeTriggerProgram(
    Parse pParse,            /* The parser context */
    TriggerStep pStepList,   /* List of statements inside the trigger body */
    int orconf               /* Conflict algorithm. (OE_Abort, etc) */
    )
    {
      TriggerStep pStep;
      Vdbe v = pParse.pVdbe;
      sqlite3 db = pParse.db;

      Debug.Assert( pParse.pTriggerTab != null && pParse.pToplevel != null );
      Debug.Assert( pStepList != null );
      Debug.Assert( v != null );
      for ( pStep = pStepList; pStep != null; pStep = pStep.pNext )
      {
        /* Figure out the ON CONFLICT policy that will be used for this step
        ** of the trigger program. If the statement that caused this trigger
        ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
        ** the ON CONFLICT policy that was specified as part of the trigger
        ** step statement. Example:
        **
        **   CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
        **     INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
        **   END;
        **
        **   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
        **   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
        */
        pParse.eOrconf = ( orconf == OE_Default ) ? pStep.orconf : (u8)orconf;

        switch ( pStep.op )
        {
          case TK_UPDATE:
            {
              sqlite3Update( pParse,
                targetSrcList( pParse, pStep ),
                sqlite3ExprListDup( db, pStep.pExprList, 0 ),
                sqlite3ExprDup( db, pStep.pWhere, 0 ),
                pParse.eOrconf
              );
              break;
            }
          case TK_INSERT:
            {
              sqlite3Insert( pParse,
                targetSrcList( pParse, pStep ),
                sqlite3ExprListDup( db, pStep.pExprList, 0 ),
                sqlite3SelectDup( db, pStep.pSelect, 0 ),
                sqlite3IdListDup( db, pStep.pIdList ),
                pParse.eOrconf
              );
              break;
            }
          case TK_DELETE:
            {
              sqlite3DeleteFrom( pParse,
                targetSrcList( pParse, pStep ),
                sqlite3ExprDup( db, pStep.pWhere, 0 )
              );
              break;
            }
          default:
            Debug.Assert( pStep.op == TK_SELECT );
            {
              SelectDest sDest = new SelectDest();
              Select pSelect = sqlite3SelectDup( db, pStep.pSelect, 0 );
              sqlite3SelectDestInit( sDest, SRT_Discard, 0 );
              sqlite3Select( pParse, pSelect, ref sDest );
              sqlite3SelectDelete( db, ref pSelect );
              break;
            }
        }
        if ( pStep.op != TK_SELECT )
        {
          sqlite3VdbeAddOp0( v, OP_ResetCount );
        }
      }

      return 0;
    }
Beispiel #35
0
    /*
    ** Generate VDBE code for zero or more statements inside the body of a
    ** trigger.
    */
    static int codeTriggerProgram(
    Parse pParse,            /* The parser context */
    TriggerStep pStepList,   /* List of statements inside the trigger body */
    int orconfin              /* Conflict algorithm. (OE_Abort, etc) */
    )
    {
      TriggerStep pTriggerStep = pStepList;
      int orconf;
      Vdbe v = pParse.pVdbe;
      sqlite3 db = pParse.db;

      Debug.Assert( pTriggerStep != null );
      Debug.Assert( v != null );
      sqlite3VdbeAddOp2( v, OP_ContextPush, 0, 0 );
#if SQLITE_DEBUG
      VdbeComment( v, "begin trigger %s", pStepList.pTrig.name );
#endif
      while ( pTriggerStep != null )
      {
        sqlite3ExprCacheClear( pParse );
        orconf = ( orconfin == OE_Default ) ? pTriggerStep.orconf : orconfin;
        pParse.trigStack.orconf = orconf;
        switch ( pTriggerStep.op )
        {
          case TK_UPDATE:
            {
              SrcList pSrc;
              pSrc = targetSrcList( pParse, pTriggerStep );
              sqlite3VdbeAddOp2( v, OP_ResetCount, 0, 0 );
              sqlite3Update( pParse, pSrc,
              sqlite3ExprListDup( db, pTriggerStep.pExprList, 0 ),
              sqlite3ExprDup( db, pTriggerStep.pWhere, 0 ), orconf );
              sqlite3VdbeAddOp2( v, OP_ResetCount, 1, 0 );
              break;
            }
          case TK_INSERT:
            {
              SrcList pSrc;
              pSrc = targetSrcList( pParse, pTriggerStep );
              sqlite3VdbeAddOp2( v, OP_ResetCount, 0, 0 );
              sqlite3Insert( pParse, pSrc,
              sqlite3ExprListDup( db, pTriggerStep.pExprList, 0 ),
              sqlite3SelectDup( db, pTriggerStep.pSelect, 0 ),
              sqlite3IdListDup( db, pTriggerStep.pIdList ), orconf );
              sqlite3VdbeAddOp2( v, OP_ResetCount, 1, 0 );
              break;
            }
          case TK_DELETE:
            {
              SrcList pSrc;
              sqlite3VdbeAddOp2( v, OP_ResetCount, 0, 0 );
              pSrc = targetSrcList( pParse, pTriggerStep );
              sqlite3DeleteFrom( pParse, pSrc,
              sqlite3ExprDup( db, pTriggerStep.pWhere, 0 ) );
              sqlite3VdbeAddOp2( v, OP_ResetCount, 1, 0 );
              break;
            }
          default: Debug.Assert( pTriggerStep.op == TK_SELECT );
            {
              Select ss = sqlite3SelectDup( db, pTriggerStep.pSelect, 0 );
              if ( ss != null )
              {
                SelectDest dest = new SelectDest();

                sqlite3SelectDestInit( dest, SRT_Discard, 0 );
                sqlite3Select( pParse, ss, ref dest );
                sqlite3SelectDelete( db, ref ss );
              }
              break;
            }
        }
        pTriggerStep = pTriggerStep.pNext;
      }
      sqlite3VdbeAddOp2( v, OP_ContextPop, 0, 0 );
#if SQLITE_DEBUG
      VdbeComment( v, "end trigger %s", pStepList.pTrig.name );
#endif
      return 0;
    }