private void cb_NifEmpresa_SelectedIndexChanged(object sender, EventArgs e)
        {
            RE = RD.ProcuraEmpresa(Convert.ToInt32(cb_NifEmpresa.SelectedItem));

            foreach (OrientadorEmpresa OE in RE.GetListaOrientadoresEmpresa())
            {
                cb_Orientador.Items.Add(OE.GetNumOrientador());
            }
        }
Пример #2
0
        private void button1_Click_1(object sender, EventArgs e)
        {
            switch (cb_tipoUtilizador.Text)
            {
            case "Aluno":
                foreach (Aluno A in RD.GetListaPessoa().OfType <Aluno>())
                {
                    if (A.GetUser() == txt_username.Text && A.GetPass() == txt_Password.Text)
                    {
                        RD.SetLogin(A.GetNome());
                        this.DialogResult = DialogResult.Yes;
                    }
                }
                break;

            case "Docente":
                foreach (Docente D in RD.GetListaPessoa().OfType <Docente>())
                {
                    if (D.GetUser() == txt_username.Text && D.GetPass() == txt_Password.Text)
                    {
                        RD.SetLogin(D.GetNome());
                        this.DialogResult = DialogResult.Yes;
                    }
                }
                break;

            case "Orientador":
                foreach (OrientadorEmpresa OE in RD.GetListaPessoa().OfType <OrientadorEmpresa>())
                {
                    if (OE.GetUser() == txt_username.Text && OE.GetPass() == txt_Password.Text)
                    {
                        RD.SetLogin(OE.GetNome());
                        this.DialogResult = DialogResult.Yes;
                    }
                }
                break;

            case "Empresa":
                foreach (Empresa EM in RD.GetListaEmpresa())
                {
                    if (EM.GetUser() == txt_username.Text && EM.GetPass() == txt_Password.Text)
                    {
                        RD.SetLogin(EM.GetNome());
                        this.DialogResult = DialogResult.Yes;
                    }
                }
                break;
            }
        }
Пример #3
0
        private static string GetTextContents(OE oe)
        {
            var t = oe.Items.OfType <TextRange>().FirstOrDefault()?.Value ?? "[No text]";

            if (t.StartsWith("<"))
            {
                var m = _simpleTagStripper.Match(t);

                if (m.Success)
                {
                    t = m.Groups[1].Value;
                }
            }

            return(t);
        }
Пример #4
0
        static string OnErrorText(OE onError)
        {
            switch (onError)
            {
            case OE.Abort: return("abort");

            case OE.Rollback: return("rollback");

            case OE.Fail: return("fail");

            case OE.Replace: return("replace");

            case OE.Ignore: return("ignore");

            case OE.Default: return("default");
            }
            return("n/a");
        }
Пример #5
0
        static TriggerPrg GetRowTrigger(Parse parse, Trigger trigger, Table table, OE orconf)
        {
            Parse root = E.Parse_Toplevel(parse);

            Debug.Assert(trigger.Name == null || table == TableOfTrigger(trigger));

            // It may be that this trigger has already been coded (or is in the process of being coded). If this is the case, then an entry with
            // a matching TriggerPrg.pTrigger field will be present somewhere in the Parse.pTriggerPrg list. Search for such an entry.
            TriggerPrg prg;

            for (prg = root.TriggerPrg; prg != null && (prg.Trigger != trigger || prg.Orconf != orconf); prg = prg.Next)
            {
                ;
            }
            // If an existing TriggerPrg could not be located, create a new one.
            if (prg == null)
            {
                prg = CodeRowTrigger(parse, trigger, table, orconf);
            }
            return(prg);
        }
Пример #6
0
        public void CodeRowTriggerDirect(Parse parse, Table table, int reg, OE orconf, int ignoreJump)
        {
            Vdbe       v   = parse.GetVdbe(); // Main VM
            TriggerPrg prg = GetRowTrigger(parse, this, table, orconf);

            Debug.Assert(prg != null || parse.Errs != 0 || parse.Ctx.MallocFailed);

            // Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program is a pointer to the sub-vdbe containing the trigger program.
            if (prg != null)
            {
                bool recursive = (Name != null && (parse.Ctx.Flags & Context.FLAG.RecTriggers) == 0);
                v.AddOp3(Core.OP.Program, reg, ignoreJump, ++parse.Mems);
                v.ChangeP4(-1, prg.Program, Vdbe.P4T.SUBPROGRAM);
#if DEBUG
                v.Comment("Call: %s.%s", (!string.IsNullOrEmpty(p.Name) ? p.Name : "fkey"), OnErrorText(orconf));
#endif
                // Set the P5 operand of the OP_Program instruction to non-zero if recursive invocation of this trigger program is disallowed. Recursive
                // invocation is disallowed if (a) the sub-program is really a trigger, not a foreign key action, and (b) the flag to enable recursive triggers is clear.
                v.ChangeP5((int)(recursive ? 1 : 0));
            }
        }
Пример #7
0
        public HeadingTreeItem(int index, IDictionary <string, QuickStyleDef> styleDefs, OE element) : base(element.objectID, index)
        {
            _styleDefs = styleDefs;
            _element   = element;

            Title = element.Items.OfType <TextRange>().FirstOrDefault()?.Value ?? "[Unknown title]";

            var qsd = styleDefs[element.quickStyleIndex];

            if (qsd.name.StartsWith("h"))
            {
                HeadingLevel = int.Parse(qsd.name.Substring(1));
            }


            this.WhenAnyValue(x => x.HeadingLevel)
            .Select(x => x > 1)
            .ToProperty(this, x => x.CanPromote, out _canPromote);

            this.WhenAnyValue(x => x.HeadingLevel).Select(x => x < 6)
            .ToProperty(this, x => x.CanDemote, out _canDemote);

            _canCreateChild = _canDemote;
        }
Пример #8
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);
        }
Пример #9
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);
        }
Пример #10
0
 public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, int null_4, Select select, OE orconf)
 {
     return(TriggerInsertStep(ctx, tableName, column, null, select, orconf));
 }
Пример #11
0
 public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, ExprList list, int null_5, OE orconf)
 {
     return(TriggerInsertStep(ctx, tableName, column, list, null, orconf));
 }
Пример #12
0
 public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, int null_4, Select select, OE orconf) { return TriggerInsertStep(ctx, tableName, column, null, select, orconf); }
Пример #13
0
        static TriggerPrg CodeRowTrigger(Parse parse, Trigger trigger, Table table, OE orconf)
        {
            Parse   top = E.Parse_Toplevel(parse);
            Context ctx = parse.Ctx; // Database handle

            Debug.Assert(trigger.Name == null || table == TableOfTrigger(trigger));
            Debug.Assert(top.V != null);

            // Allocate the TriggerPrg and SubProgram objects. To ensure that they are freed if an error occurs, link them into the Parse.pTriggerPrg
            // list of the top-level Parse object sooner rather than later.
            TriggerPrg prg = new TriggerPrg(); // Value to return //: _tagalloc(ctx, sizeof(TriggerPrg), true);

            if (prg == null)
            {
                return(null);
            }
            prg.Next       = top.TriggerPrg;
            top.TriggerPrg = prg;
            Vdbe.SubProgram program;                       // Sub-vdbe for trigger program
            prg.Program = program = new Vdbe.SubProgram(); // sqlite3DbMallocZero( db, sizeof( SubProgram ) );
            if (program == null)
            {
                return(null);
            }
            top.V.LinkSubProgram(program);
            prg.Trigger     = trigger;
            prg.Orconf      = orconf;
            prg.Colmasks[0] = 0xffffffff;
            prg.Colmasks[1] = 0xffffffff;

            // Allocate and populate a new Parse context to use for coding the trigger sub-program.
            Parse subParse = new Parse(); // Parse context for sub-vdbe //: _stackalloc(ctx, sizeof(Parse), true);

            if (subParse == null)
            {
                return(null);
            }
            NameContext sNC = new NameContext(); // Name context for sub-vdbe

            sNC.Parse            = subParse;
            subParse.Ctx         = ctx;
            subParse.TriggerTab  = table;
            subParse.Toplevel    = top;
            subParse.AuthContext = trigger.Name;
            subParse.TriggerOp   = trigger.OP;
            subParse.QueryLoops  = parse.QueryLoops;

            int  endTrigger = 0;                  // Label to jump to if WHEN is false
            Vdbe v          = subParse.GetVdbe(); // Temporary VM

            if (v != null)
            {
#if DEBUG
                v.Comment("Start: %s.%s (%s %s%s%s ON %s)",
                          trigger.Name, OnErrorText(orconf),
                          (trigger.TRtm == TRIGGER.BEFORE ? "BEFORE" : "AFTER"),
                          (trigger.OP == TK.UPDATE ? "UPDATE" : string.Empty),
                          (trigger.OP == TK.INSERT ? "INSERT" : string.Empty),
                          (trigger.OP == TK.DELETE ? "DELETE" : string.Empty),
                          table.Name);
#endif
#if !OMIT_TRACE
                v.ChangeP4(-1, C._mtagprintf(ctx, "-- TRIGGER %s", trigger.Name), Vdbe.P4T.DYNAMIC);
#endif

                // If one was specified, code the WHEN clause. If it evaluates to false (or NULL) the sub-vdbe is immediately halted by jumping to the
                // OP_Halt inserted at the end of the program.
                if (trigger.When != null)
                {
                    Expr when = Expr.Dup(ctx, trigger.When, 0); // Duplicate of trigger WHEN expression
                    if (ResolveExprNames(sNC, ref when) == RC.OK && !ctx.MallocFailed)
                    {
                        endTrigger = v.MakeLabel();
                        subParse.IfFalse(when, endTrigger, RC_JUMPIFNULL);
                    }
                    Expr.Delete(ctx, ref when);
                }

                // Code the trigger program into the sub-vdbe.
                CodeTriggerProgram(subParse, trigger.StepList, orconf);

                // Insert an OP_Halt at the end of the sub-program.
                if (endTrigger != 0)
                {
                    v.ResolveLabel(endTrigger);
                }
                v.AddOp0(Core.OP.Halt);
#if DEBUG
                v.Comment("End: %s.%s", trigger.Name, OnErrorText(orconf));
#endif
                TransferParseError(parse, subParse);
                if (!ctx.MallocFailed)
                {
                    program.Ops.data = v.TakeOpArray(ref program.Ops.length, ref top.MaxArgs);
                }
                program.Mems    = subParse.Mems;
                program.Csrs    = subParse.Tabs;
                program.Token   = trigger.GetHashCode();
                prg.Colmasks[0] = subParse.Oldmask;
                prg.Colmasks[1] = subParse.Newmask;
                Vdbe.Delete(v);
            }

            Debug.Assert(subParse.Ainc == null && subParse.ZombieTab == null);
            Debug.Assert(subParse.TriggerPrg == null && subParse.MaxArgs == 0);
            C._stackfree(ctx, ref subParse);

            return(prg);
        }
Пример #14
0
 static string OnErrorText(OE onError)
 {
     switch (onError)
     {
         case OE.Abort: return "abort";
         case OE.Rollback: return "rollback";
         case OE.Fail: return "fail";
         case OE.Replace: return "replace";
         case OE.Ignore: return "ignore";
         case OE.Default: return "default";
     }
     return "n/a";
 }
Пример #15
0
        static TriggerPrg CodeRowTrigger(Parse parse, Trigger trigger, Table table, OE orconf)
        {
            Parse top = E.Parse_Toplevel(parse);
            Context ctx = parse.Ctx; // Database handle

            Debug.Assert(trigger.Name == null || table == TableOfTrigger(trigger));
            Debug.Assert(top.V != null);

            // Allocate the TriggerPrg and SubProgram objects. To ensure that they are freed if an error occurs, link them into the Parse.pTriggerPrg 
            // list of the top-level Parse object sooner rather than later.
            TriggerPrg prg = new TriggerPrg(); // Value to return //: _tagalloc(ctx, sizeof(TriggerPrg), true);
            if (prg == null) return null;
            prg.Next = top.TriggerPrg;
            top.TriggerPrg = prg;
            Vdbe.SubProgram program; // Sub-vdbe for trigger program
            prg.Program = program = new Vdbe.SubProgram();// sqlite3DbMallocZero( db, sizeof( SubProgram ) );
            if (program == null) return null;
            top.V.LinkSubProgram(program);
            prg.Trigger = trigger;
            prg.Orconf = orconf;
            prg.Colmasks[0] = 0xffffffff;
            prg.Colmasks[1] = 0xffffffff;

            // Allocate and populate a new Parse context to use for coding the trigger sub-program.
            Parse subParse = new Parse(); // Parse context for sub-vdbe //: _stackalloc(ctx, sizeof(Parse), true);
            if (subParse == null) return null;
            NameContext sNC = new NameContext(); // Name context for sub-vdbe
            sNC.Parse = subParse;
            subParse.Ctx = ctx;
            subParse.TriggerTab = table;
            subParse.Toplevel = top;
            subParse.AuthContext = trigger.Name;
            subParse.TriggerOp = trigger.OP;
            subParse.QueryLoops = parse.QueryLoops;

            int endTrigger = 0; // Label to jump to if WHEN is false
            Vdbe v = subParse.GetVdbe(); // Temporary VM
            if (v != null)
            {
#if DEBUG
                v.Comment("Start: %s.%s (%s %s%s%s ON %s)",
                    trigger.Name, OnErrorText(orconf),
                    (trigger.TRtm == TRIGGER.BEFORE ? "BEFORE" : "AFTER"),
                    (trigger.OP == TK.UPDATE ? "UPDATE" : string.Empty),
                    (trigger.OP == TK.INSERT ? "INSERT" : string.Empty),
                    (trigger.OP == TK.DELETE ? "DELETE" : string.Empty),
                    table.Name);
#endif
#if !OMIT_TRACE
                v.ChangeP4(-1, C._mtagprintf(ctx, "-- TRIGGER %s", trigger.Name), Vdbe.P4T.DYNAMIC);
#endif

                // If one was specified, code the WHEN clause. If it evaluates to false (or NULL) the sub-vdbe is immediately halted by jumping to the 
                // OP_Halt inserted at the end of the program.
                if (trigger.When != null)
                {
                    Expr when = Expr.Dup(ctx, trigger.When, 0); // Duplicate of trigger WHEN expression
                    if (ResolveExprNames(sNC, ref when) == RC.OK && !ctx.MallocFailed)
                    {
                        endTrigger = v.MakeLabel();
                        subParse.IfFalse(when, endTrigger, RC_JUMPIFNULL);
                    }
                    Expr.Delete(ctx, ref when);
                }

                // Code the trigger program into the sub-vdbe.
                CodeTriggerProgram(subParse, trigger.StepList, orconf);

                // Insert an OP_Halt at the end of the sub-program.
                if (endTrigger != 0)
                    v.ResolveLabel(endTrigger);
                v.AddOp0(Core.OP.Halt);
#if DEBUG
                v.Comment("End: %s.%s", trigger.Name, OnErrorText(orconf));
#endif
                TransferParseError(parse, subParse);
                if (!ctx.MallocFailed)
                    program.Ops.data = v.TakeOpArray(ref program.Ops.length, ref top.MaxArgs);
                program.Mems = subParse.Mems;
                program.Csrs = subParse.Tabs;
                program.Token = trigger.GetHashCode();
                prg.Colmasks[0] = subParse.Oldmask;
                prg.Colmasks[1] = subParse.Newmask;
                Vdbe.Delete(v);
            }

            Debug.Assert(subParse.Ainc == null && subParse.ZombieTab == null);
            Debug.Assert(subParse.TriggerPrg == null && subParse.MaxArgs == 0);
            C._stackfree(ctx, ref subParse);

            return prg;
        }
Пример #16
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;
        }
Пример #17
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;
 }
Пример #18
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;
 }
Пример #19
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);
        }
Пример #20
0
        public uint TriggerColmask(Parse parse, ExprList changes, bool isNew, TRIGGER trtm, Table table, OE orconf)
        {
            TK   op      = (changes != null ? TK.UPDATE : TK.DELETE);
            int  isNewId = (isNew ? 1 : 0);
            uint mask    = 0;

            for (Trigger p = this; p != null; p = p.Next)
            {
                if (p.OP == op && (trtm & p.TRtm) != 0 && CheckColumnOverlap(p.Columns, changes))
                {
                    TriggerPrg prg = GetRowTrigger(parse, p, table, orconf);
                    if (prg != null)
                    {
                        mask |= prg.Colmasks[isNewId];
                    }
                }
            }
            return(mask);
        }
Пример #21
0
        public static void sqlite3Update(Parse parse, SrcList tabList, ExprList changes, Expr where_, OE onError)
        {
            int i, j;                                 // Loop counters

            AuthContext sContext = new AuthContext(); // The authorization context
            Context     ctx      = parse.Ctx;         // The database structure

            if (parse.Errs != 0 || ctx.MallocFailed)
            {
                goto update_cleanup;
            }
            Debug.Assert(tabList.Srcs == 1);

            // Locate the table which we want to update.
            Table table = sqlite3SrcListLookup(parse, tabList); // The table to be updated

            if (table == null)
            {
                goto update_cleanup;
            }
            int db = sqlite3SchemaToIndex(ctx, table.Schema); // Database containing the table being updated

            // Figure out if we have any triggers and if the table being updated is a view.
#if !OMIT_TRIGGER
            int     tmask   = 0;                                                                 // Mask of TRIGGER_BEFORE|TRIGGER_AFTER
            Trigger trigger = sqlite3TriggersExist(parse, table, TK.UPDATE, changes, out tmask); // List of triggers on pTab, if required
#if OMIT_VIEW
            const bool isView = false;
#else
            bool isView = (table.Select != null); // True when updating a view (INSTEAD OF trigger)
#endif
            Debug.Assert(trigger != null || tmask == 0);
#else
            const Trigger trigger = null;
            const int     tmask   = 0;
            const bool    isView  = false;
#endif

            if (sqlite3ViewGetColumnNames(parse, table) != 0 || sqlite3IsReadOnly(parse, table, tmask))
            {
                goto update_cleanup;
            }

            int[] xrefs = new int[table.Cols.length]; // xrefs[i] is the index in pChanges->a[] of the an expression for the i-th column of the table. xrefs[i]==-1 if the i-th column is not changed.
            if (xrefs == null)
            {
                goto update_cleanup;
            }
            for (i = 0; i < table.Cols.length; i++)
            {
                xrefs[i] = -1;
            }

            // Allocate a cursors for the main database table and for all indices. The index cursors might not be used, but if they are used they
            // need to occur right after the database cursor.  So go ahead and allocate enough space, just in case.
            int curId; // VDBE Cursor number of pTab
            tabList.Ids[0].Cursor = curId = parse.Tabs++;
            Index idx; // For looping over indices
            for (idx = table.Index; idx != null; idx = idx.Next)
            {
                parse.Tabs++;
            }

            // Initialize the name-context
            NameContext sNC = new NameContext(); // The name-context to resolve expressions in
            sNC.Parse   = parse;
            sNC.SrcList = tabList;

            // Resolve the column names in all the expressions of the of the UPDATE statement.  Also find the column index
            // for each column to be updated in the pChanges array.  For each column to be updated, make sure we have authorization to change that column.
            bool chngRowid = false; // True if the record number is being changed
            Expr rowidExpr = null;  // Expression defining the new record number
            for (i = 0; i < changes.Exprs; i++)
            {
                if (sqlite3ResolveExprNames(sNC, ref changes.Ids[i].Expr) != 0)
                {
                    goto update_cleanup;
                }
                for (j = 0; j < table.Cols.length; j++)
                {
                    if (string.Equals(table.Cols[j].Name, changes.Ids[i].Name, StringComparison.OrdinalIgnoreCase))
                    {
                        if (j == table.PKey)
                        {
                            chngRowid = true;
                            rowidExpr = changes.Ids[i].Expr;
                        }
                        xrefs[j] = i;
                        break;
                    }
                }
                if (j >= table.Cols.length)
                {
                    if (Expr::IsRowid(changes.Ids[i].Name))
                    {
                        chngRowid = true;
                        rowidExpr = changes.Ids[i].Expr;
                    }
                    else
                    {
                        parse.ErrorMsg("no such column: %s", changes.Ids[i].Name);
                        parse.CheckSchema = 1;
                        goto update_cleanup;
                    }
                }
#if !OMIT_AUTHORIZATION
                {
                    ARC rc = Auth.Check(parse, AUTH.UPDATE, table.Name, table.Cols[j].Name, ctx.DBs[db].Name);
                    if (rc == ARC.DENY)
                    {
                        goto update_cleanup;
                    }
                    else if (rc == ARC.IGNORE)
                    {
                        xrefs[j] = -1;
                    }
                }
#endif
            }

            bool hasFK = sqlite3FkRequired(parse, table, xrefs, chngRowid ? 1 : 0); // True if foreign key processing is required

            // 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.
            int idxLength;                   // Number of indices that need updating
            for (idxLength = 0, idx = table.Index; idx != null; idx = idx.Next, idxLength++)
            {
                ;
            }
            int[] regIdxs = null; // One register assigned to each index to be updated
            if (idxLength > 0)
            {
                regIdxs = new int[idxLength];
                if (regIdxs == null)
                {
                    goto update_cleanup;
                }
            }
            for (j = 0, idx = table.Index; idx != null; idx = idx.Next, j++)
            {
                int regId;
                if (hasFK || chngRowid)
                {
                    regId = ++parse.Mems;
                }
                else
                {
                    regId = 0;
                    for (i = 0; i < idx.Columns.length; i++)
                    {
                        if (xrefs[idx.Columns[i]] >= 0)
                        {
                            regId = ++parse.Mems;
                            break;
                        }
                    }
                }
                regIdxs[j] = regId;
            }

            // Begin generating code.
            Vdbe v = parse.GetVdbe(); // The virtual database engine
            if (v == null)
            {
                goto update_cleanup;
            }
            if (parse.Nested == 0)
            {
                v.CountChanges();
            }
            parse.BeginWriteOperation(1, db);

#if !OMIT_VIRTUALTABLE
            // Virtual tables must be handled separately
            if (IsVirtual(table))
            {
                UpdateVirtualTable(parse, tabList, table, changes, rowidExpr, xrefs, where_, onError);
                where_  = null;
                tabList = null;
                goto update_cleanup;
            }
#endif

            // Register Allocations
            int regRowCount = 0;         // A count of rows changed
            int regOldRowid;             // The old rowid
            int regNewRowid;             // The new rowid
            int regNew;
            int regOld    = 0;
            int regRowSet = 0;           // Rowset of rows to be updated

            // Allocate required registers.
            regOldRowid = regNewRowid = ++parse.Mems;
            if (trigger != null || hasFK)
            {
                regOld      = parse.Mems + 1;
                parse.Mems += table.Cols.length;
            }
            if (chngRowid || trigger != null || hasFK)
            {
                regNewRowid = ++parse.Mems;
            }
            regNew      = parse.Mems + 1;
            parse.Mems += table.Cols.length;

            // Start the view context.
            if (isView)
            {
                Auth.ContextPush(parse, sContext, table.Name);
            }

            // If we are trying to update a view, realize that view into a ephemeral table.
#if !OMIT_VIEW && !OMIT_TRIGGER
            if (isView)
            {
                sqlite3MaterializeView(parse, table, where_, curId);
            }
#endif

            // Resolve the column names in all the expressions in the WHERE clause.
            if (sqlite3ResolveExprNames(sNC, ref where_) != 0)
            {
                goto update_cleanup;
            }

            // Begin the database scan
            v.AddOp2(OP.Null, 0, regOldRowid);
            ExprList  dummy = null;
            WhereInfo winfo = Where.Begin(parse, tabList, where_, ref dummy, WHERE.ONEPASS_DESIRED); // Information about the WHERE clause
            if (winfo == null)
            {
                goto update_cleanup;
            }
            bool okOnePass = winfo.OkOnePass; // True for one-pass algorithm without the FIFO

            // Remember the rowid of every item to be updated.
            v.AddOp2(OP.Rowid, curId, regOldRowid);
            if (!okOnePass)
            {
                v.AddOp2(OP.RowSetAdd, regRowSet, regOldRowid);
            }

            // End the database scan loop.
            Where.End(winfo);

            // Initialize the count of updated rows
            if ((ctx.Flags & Context.FLAG.CountRows) != 0 && parse.TriggerTab == null)
            {
                regRowCount = ++parse.Mems;
                v.AddOp2(OP.Integer, 0, regRowCount);
            }

            bool openAll = false; // True if all indices need to be opened
            if (!isView)
            {
                // Open every index that needs updating.  Note that if any index could potentially invoke a REPLACE conflict resolution
                // action, then we need to open all indices because we might need to be deleting some records.
                if (!okOnePass)
                {
                    sqlite3OpenTable(parse, curId, db, table, OP.OpenWrite);
                }
                if (onError == OE.Replace)
                {
                    openAll = true;
                }
                else
                {
                    openAll = false;
                    for (idx = table.Index; idx != null; idx = idx.Next)
                    {
                        if (idx.OnError == OE.Replace)
                        {
                            openAll = true;
                            break;
                        }
                    }
                }
                for (i = 0, idx = table.Index; idx != null; idx = idx.Next, i++)
                {
                    if (openAll || regIdxs[i] > 0)
                    {
                        KeyInfo key = sqlite3IndexKeyinfo(parse, idx);
                        v.AddOp4(OP.OpenWrite, curId + i + 1, idx.Id, db, key, Vdbe.P4T.KEYINFO_HANDOFF);
                        Debug.Assert(parse.Tabs > curId + i + 1);
                    }
                }
            }

            // Top of the update loop
            int addr = 0; // VDBE instruction address of the start of the loop
            if (okOnePass)
            {
                int a1 = v.AddOp1(OP.NotNull, regOldRowid);
                addr = v.AddOp0(OP.Goto);
                v.JumpHere(a1);
            }
            else
            {
                addr = v.AddOp3(OP.RowSetRead, regRowSet, 0, regOldRowid);
            }

            // Make cursor iCur point to the record that is being updated. If this record does not exist for some reason (deleted by a trigger,
            // for example, then jump to the next iteration of the RowSet loop.
            v.AddOp3(OP.NotExists, curId, addr, regOldRowid);

            // If the record number will change, set register regNewRowid to contain the new value. If the record number is not being modified,
            // then regNewRowid is the same register as regOldRowid, which is already populated.
            Debug.Assert(chngRowid || trigger != null || hasFK || regOldRowid == regNewRowid);
            if (chngRowid)
            {
                Expr.Code(parse, rowidExpr, regNewRowid);
                v.AddOp1(OP.MustBeInt, regNewRowid);
            }

            // If there are triggers on this table, populate an array of registers with the required old.* column data.
            if (hasFK || trigger != null)
            {
                uint oldmask = (hasFK ? sqlite3FkOldmask(parse, table) : 0);
                oldmask |= sqlite3TriggerColmask(parse, trigger, changes, 0, TRIGGER_BEFORE | TRIGGER_AFTER, table, onError);
                for (i = 0; i < table.Cols.length; i++)
                {
                    if (xrefs[i] < 0 || oldmask == 0xffffffff || (i < 32 && 0 != (oldmask & (1 << i))))
                    {
                        Expr.CodeGetColumnOfTable(v, table, curId, i, regOld + i);
                    }
                    else
                    {
                        v.AddOp2(OP.Null, 0, regOld + i);
                    }
                }
                if (!chngRowid)
                {
                    v.AddOp2(OP.Copy, regOldRowid, 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 there are one or more BEFORE triggers, then do not populate the registers associated with columns that are (a) not modified by
            // this UPDATE statement and (b) not accessed by new.* references. The values for registers not modified by the UPDATE must be reloaded from
            // the database after the BEFORE triggers are fired anyway (as the trigger may have modified them). So not loading those that are not going to
            // be used eliminates some redundant opcodes.
            int newmask = (int)sqlite3TriggerColmask(parse, trigger, changes, 1, TRIGGER_BEFORE, table, onError); // Mask of NEW.* columns accessed by BEFORE triggers
            for (i = 0; i < table.Cols.length; i++)
            {
                if (i == table.PKey)
                {
                    //v.AddOp2(OP.Null, 0, regNew + i);
                }
                else
                {
                    j = xrefs[i];
                    if (j >= 0)
                    {
                        Expr.Code(parse, changes.Ids[j].Expr, regNew + i);
                    }
                    else if ((tmask & TRIGGER_BEFORE) == 0 || i > 31 || (newmask & (1 << i)) != 0)
                    {
                        // This branch loads the value of a column that will not be changed into a register. This is done if there are no BEFORE triggers, or
                        // if there are one or more BEFORE triggers that use this value via a new.* reference in a trigger program.
                        C.ASSERTCOVERAGE(i == 31);
                        C.ASSERTCOVERAGE(i == 32);
                        v.AddOp3(OP.Column, curId, i, regNew + i);
                        v.ColumnDefault(table, i, regNew + i);
                    }
                }
            }

            // Fire any BEFORE UPDATE triggers. This happens before constraints are verified. One could argue that this is wrong.
            if ((tmask & TRIGGER_BEFORE) != 0)
            {
                v.AddOp2(OP.Affinity, regNew, table.Cols.length);
                sqlite3TableAffinityStr(v, table);
                sqlite3CodeRowTrigger(parse, trigger, TK.UPDATE, changes, TRIGGER_BEFORE, table, regOldRowid, onError, addr);

                // The row-trigger may have deleted the row being updated. In this case, jump to the next row. No updates or AFTER triggers are
                // required. This behavior - what happens when the row being updated is deleted or renamed by a BEFORE trigger - is left undefined in the documentation.
                v.AddOp3(OP.NotExists, curId, addr, regOldRowid);

                // If it did not delete it, the row-trigger may still have modified some of the columns of the row being updated. Load the values for
                // all columns not modified by the update statement into their registers in case this has happened.
                for (i = 0; i < table.Cols.length; i++)
                {
                    if (xrefs[i] < 0 && i != table.PKey)
                    {
                        v.AddOp3(OP.Column, curId, i, regNew + i);
                        v.ColumnDefault(table, i, regNew + i);
                    }
                }
            }

            if (!isView)
            {
                // Do constraint checks.
                int dummy2;
                sqlite3GenerateConstraintChecks(parse, table, curId, regNewRowid, regIdxs, (chngRowid ? regOldRowid : 0), true, onError, addr, out dummy2);

                // Do FK constraint checks.
                if (hasFK)
                {
                    sqlite3FkCheck(parse, table, regOldRowid, 0);
                }

                // Delete the index entries associated with the current record.
                int j1 = v.AddOp3(OP.NotExists, curId, 0, regOldRowid); // Address of jump instruction
                sqlite3GenerateRowIndexDelete(parse, table, curId, regIdxs);

                // If changing the record number, delete the old record.
                if (hasFK || chngRowid)
                {
                    v.AddOp2(OP.Delete, curId, 0);
                }
                v.JumpHere(j1);

                if (hasFK)
                {
                    sqlite3FkCheck(parse, table, 0, regNewRowid);
                }

                // Insert the new index entries and the new record.
                sqlite3CompleteInsertion(parse, table, curId, regNewRowid, regIdxs, true, false, false);

                // 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 updated.
                if (hasFK)
                {
                    sqlite3FkActions(parse, table, changes, regOldRowid);
                }
            }

            // Increment the row counter
            if ((ctx.Flags & Context.FLAG.CountRows) != 0 && parse.TriggerTab == null)
            {
                v.AddOp2(OP.AddImm, regRowCount, 1);
            }

            sqlite3CodeRowTrigger(parse, trigger, TK.UPDATE, changes, TRIGGER_AFTER, table, regOldRowid, onError, addr);

            // Repeat the above with the next record to be updated, until all record selected by the WHERE clause have been updated.
            v.AddOp2(OP.Goto, 0, addr);
            v.JumpHere(addr);

            // Close all tables
            Debug.Assert(regIdxs != null);
            for (i = 0, idx = table.Index; idx != null; idx = idx.Next, i++)
            {
                if (openAll || regIdxs[i] > 0)
                {
                    v.AddOp2(OP.Close, curId + i + 1, 0);
                }
            }
            v.AddOp2(OP.Close, curId, 0);

            // Update the sqlite_sequence table by storing the content of the maximum rowid counter values recorded while inserting into
            // autoincrement tables.
            if (parse.Nested == 0 && parse.TriggerTab == null)
            {
                sqlite3AutoincrementEnd(parse);
            }

            // Return the number of rows that were changed. If this routine is generating code because of a call to sqlite3NestedParse(), do not
            // invoke the callback function.
            if ((ctx.Flags & Context.FLAG.CountRows) != 0 && parse.TriggerTab == null && parse.Nested == 0)
            {
                v.AddOp2(OP.ResultRow, regRowCount, 1);
                v.SetNumCols(1);
                v.SetColName(0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
            }

update_cleanup:
#if !OMIT_AUTHORIZATION
            Auth.ContextPop(sContext);
#endif
            C._tagfree(ctx, ref regIdxs);
            C._tagfree(ctx, ref xrefs);
            SrcList.Delete(ctx, ref tabList);
            ExprList.Delete(ctx, ref changes);
            Expr.Delete(ctx, ref where_);
            return;
        }
Пример #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);
        }
Пример #23
0
        static TriggerPrg GetRowTrigger(Parse parse, Trigger trigger, Table table, OE orconf)
        {
            Parse root = E.Parse_Toplevel(parse);
            Debug.Assert(trigger.Name == null || table == TableOfTrigger(trigger));

            // It may be that this trigger has already been coded (or is in the process of being coded). If this is the case, then an entry with
            // a matching TriggerPrg.pTrigger field will be present somewhere in the Parse.pTriggerPrg list. Search for such an entry.
            TriggerPrg prg;
            for (prg = root.TriggerPrg; prg != null && (prg.Trigger != trigger || prg.Orconf != orconf); prg = prg.Next) ;
            // If an existing TriggerPrg could not be located, create a new one.
            if (prg == null)
                prg = CodeRowTrigger(parse, trigger, table, orconf);
            return prg;
        }
Пример #24
0
 public static TriggerStep TriggerInsertStep(Context ctx, Token tableName, IdList column, ExprList list, int null_5, OE orconf) { return TriggerInsertStep(ctx, tableName, column, list, null, orconf); }
Пример #25
0
        public void CodeRowTrigger(Parse parse, TK op, ExprList changes, TRIGGER trtm, Table table, int reg, OE orconf, int ignoreJump)
        {
            Debug.Assert(op == TK.UPDATE || op == TK.INSERT || op == TK.DELETE);
            Debug.Assert(trtm == TRIGGER.BEFORE || trtm == TRIGGER.AFTER);
            Debug.Assert((op == TK.UPDATE) == (changes != null));

            for (Trigger p = this; p != null; p = p.Next)
            {
                // Sanity checking:  The schema for the trigger and for the table are always defined.  The trigger must be in the same schema as the table or else it must be a TEMP trigger.
                Debug.Assert(p.Schema != null);
                Debug.Assert(p.TabSchema != null);
                Debug.Assert(p.Schema == p.TabSchema || p.Schema == parse.Ctx.DBs[1].Schema);

                // Determine whether we should code this trigger
                if (p.OP == op && p.TRtm == trtm && CheckColumnOverlap(p.Columns, changes))
                {
                    p.CodeRowTriggerDirect(parse, table, reg, orconf, ignoreJump);
                }
            }
        }
Пример #26
0
        public void CodeRowTriggerDirect(Parse parse, Table table, int reg, OE orconf, int ignoreJump)
        {
            Vdbe v = parse.GetVdbe(); // Main VM
            TriggerPrg prg = GetRowTrigger(parse, this, table, orconf);
            Debug.Assert(prg != null || parse.Errs != 0 || parse.Ctx.MallocFailed);

            // Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program is a pointer to the sub-vdbe containing the trigger program.
            if (prg != null)
            {
                bool recursive = (Name != null && (parse.Ctx.Flags & Context.FLAG.RecTriggers) == 0);
                v.AddOp3(Core.OP.Program, reg, ignoreJump, ++parse.Mems);
                v.ChangeP4(-1, prg.Program, Vdbe.P4T.SUBPROGRAM);
#if DEBUG
                v.Comment("Call: %s.%s", (!string.IsNullOrEmpty(p.Name) ? p.Name : "fkey"), OnErrorText(orconf));
#endif
                // Set the P5 operand of the OP_Program instruction to non-zero if recursive invocation of this trigger program is disallowed. Recursive
                // invocation is disallowed if (a) the sub-program is really a trigger, not a foreign key action, and (b) the flag to enable recursive triggers is clear.
                v.ChangeP5((int)(recursive ? 1 : 0));
            }
        }
Пример #27
0
    protected void Page_Load(object sender, EventArgs e)
    {
        Label2.Text  = DateTime.Now.ToString("D");
        Label14.Text = "";
        Label16.Text = "";
        Label33.Text = "";
        Label34.Text = "";
        Label35.Text = "";
        Label36.Text = "";
        Label24.Text = "";
        Label47.Text = "";
        DataView dv = (DataView)SqlDataSource1.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv.Table.Rows)
        {
            Cname        = (string)dv.Table.Rows[x][0];
            Cadd         = (string)dv.Table.Rows[x][1];
            Ccomp        = (string)dv.Table.Rows[x][2];
            Label14.Text = Label14.Text + Cname;
            Label33.Text = Label33.Text + Cadd;
            Label34.Text = Label34.Text + Ccomp;
            Label16.Text = Label16.Text + Cname;
            Label35.Text = Label35.Text + Cadd;
            Label36.Text = Label36.Text + Ccomp;
            Label24.Text = Label24.Text + Cname;
        }
        Venue.Text   = "";
        VAdd.Text    = "";
        N.Text       = "";
        Label37.Text = "";
        DataView dv1 = (DataView)SqlDataSource2.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv1.Table.Rows)
        {
            Vname = (string)dv1.Table.Rows[x][0];
            Vadd  = (string)dv1.Table.Rows[x][1];
            Ename = (string)dv1.Table.Rows[x][2];
            Edate = (DateTime)dv1.Table.Rows[x][3];

            Venue.Text   = Venue.Text + Vname;
            VAdd.Text    = VAdd.Text + Vadd;
            N.Text       = N.Text + Ename;
            Label37.Text = Edate.ToString("D");
        }
        Label40.Text = "";
        Label41.Text = "";
        Label43.Text = "";
        Label44.Text = "";
        Label42.Text = "";
        Label1.Text  = "";
        DataView dv2 = (DataView)SqlDataSource3.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv2.Table.Rows)
        {
            RF           = (double)dv2.Table.Rows[x][0];
            Total        = (double)dv2.Table.Rows[x][4];
            OE           = (double)dv2.Table.Rows[x][1];
            PB           = (double)dv2.Table.Rows[x][2];
            RPH          = (double)dv2.Table.Rows[x][3];
            DL           = (DateTime)dv2.Table.Rows[x][5];
            Label40.Text = Label40.Text + RF.ToString("n2");
            Label41.Text = Label41.Text + Total.ToString("n2");
            Label43.Text = Label43.Text + OE.ToString("n2");
            Label44.Text = Label44.Text + PB.ToString("n2");
            Label42.Text = Label42.Text + RPH.ToString("n2");
            Label1.Text  = DL.ToString("D");
        }
        Label45.Text = "";
        DataView dv3 = (DataView)SqlDataSource4.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv3.Table.Rows)
        {
            Edate  = (DateTime)dv3.Table.Rows[x][0];
            Estime = (TimeSpan)dv3.Table.Rows[x][1];
            Eetime = (TimeSpan)dv3.Table.Rows[x][2];

            Label45.Text = Edate.ToString("D") + ' ' + ConvertMode(Estime.ToString()) + ' ' + '-' + ' ' + ConvertMode(Eetime.ToString());
        }
        Label46.Text = "";
        DataView dv4 = (DataView)SqlDataSource5.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv4.Table.Rows)
        {
            Aname        = (string)dv4.Table.Rows[x][0];
            Ades         = (string)dv4.Table.Rows[x][3];
            qty          = (int)dv4.Table.Rows[x][1];
            Label46.Text = Label46.Text + ' ' + Ades + ' ' + qty.ToString() + ' ' + "pcs" + ", ";
            x++;
        }
        Label3.Text = "";
        Label4.Text = "";
        string check = Label46.Text;
        int    lg    = check.Length;

        if (x > 0)
        {
            Label3.Text  = "<li> Amenity- ";
            check        = check.Substring(0, lg - 2);
            Label46.Text = check + ";";
            Label4.Text  = "</li>";
        }
        Label47.Text = "";
        DataView dv5 = (DataView)SqlDataSource6.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv5.Table.Rows)
        {
            Fname        = (string)dv5.Table.Rows[y][0];
            Fdes         = (string)dv5.Table.Rows[y][1];
            Label47.Text = Label47.Text + Fname + ' ' + Fdes + ", ";
            y++;
        }
        string check2 = Label47.Text;
        int    lg2    = check2.Length;

        Label5.Text = "";
        Label6.Text = "";
        if (y > 0)
        {
            Label5.Text  = "<li> Facility- ";
            check2       = check2.Substring(0, lg2 - 2);
            Label47.Text = check2 + ";";
            Label6.Text  = "</li>";
        }

        Label48.Text = "";
        DataView dv6 = (DataView)SqlDataSource7.Select(DataSourceSelectArguments.Empty);

        foreach (DataRow dr in dv6.Table.Rows)
        {
            Fname        = (string)dv6.Table.Rows[z][0];
            Fdes         = (string)dv6.Table.Rows[z][1];
            Label48.Text = Label48.Text + Mname + ' ' + Mdes + ", ";
            z++;
        }

        string check3 = Label48.Text;
        int    lg3    = check3.Length;

        if (lg3 != 0)
        {
            check3       = check3.Substring(0, lg3 - 2);
            Label48.Text = check3 + ";";
        }
    }
Пример #28
0
        public void CodeRowTrigger(Parse parse, TK op, ExprList changes, TRIGGER trtm, Table table, int reg, OE orconf, int ignoreJump)
        {
            Debug.Assert(op == TK.UPDATE || op == TK.INSERT || op == TK.DELETE);
            Debug.Assert(trtm == TRIGGER.BEFORE || trtm == TRIGGER.AFTER);
            Debug.Assert((op == TK.UPDATE) == (changes != null));

            for (Trigger p = this; p != null; p = p.Next)
            {
                // Sanity checking:  The schema for the trigger and for the table are always defined.  The trigger must be in the same schema as the table or else it must be a TEMP trigger.
                Debug.Assert(p.Schema != null);
                Debug.Assert(p.TabSchema != null);
                Debug.Assert(p.Schema == p.TabSchema || p.Schema == parse.Ctx.DBs[1].Schema);

                // Determine whether we should code this trigger
                if (p.OP == op && p.TRtm == trtm && CheckColumnOverlap(p.Columns, changes))
                    p.CodeRowTriggerDirect(parse, table, reg, orconf, ignoreJump);
            }
        }
Пример #29
0
 public uint TriggerColmask(Parse parse, ExprList changes, bool isNew, TRIGGER trtm, Table table, OE orconf)
 {
     TK op = (changes != null ? TK.UPDATE : TK.DELETE);
     int isNewId = (isNew ? 1 : 0);
     uint mask = 0;
     for (Trigger p = this; p != null; p = p.Next)
         if (p.OP == op && (trtm & p.TRtm) != 0 && CheckColumnOverlap(p.Columns, changes))
         {
             TriggerPrg prg = GetRowTrigger(parse, p, table, orconf);
             if (prg != null)
                 mask |= prg.Colmasks[isNewId];
         }
     return mask;
 }
Пример #30
0
        public static void GenerateRowDelete(Parse parse, Table table, int curId, int rowid, int count, Trigger trigger, OE onconf)
        {
            // Vdbe is guaranteed to have been allocated by this stage.
            Vdbe v = parse.V;
            Debug.Assert(v != null);

            // 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.
            int label = v.MakeLabel(); // Label resolved to end of generated code
            v.AddOp3(OP.NotExists, curId, label, rowid);

            // If there are any triggers to fire, allocate a range of registers to use for the old.* references in the triggers.
            if (FKey.FkRequired(parse, table, null, 0) != 0 || trigger != null)
            {
                // TODO: Could use temporary registers here. Also could attempt to avoid copying the contents of the rowid register.
                uint mask = sqlite3TriggerColmask(parse, trigger, null, 0, TRIGGER.BEFORE | TRIGGER.AFTER, table, onconf); // Mask of OLD.* columns in use
                mask |= sqlite3FkOldmask(parse, table);
                int oldId = parse.Mems + 1; // First register in OLD.* array
                parse.Mems += (1 + table.Cols.length);

                // Populate the OLD.* pseudo-table register array. These values will be used by any BEFORE and AFTER triggers that exist.
                v.AddOp2(OP.Copy, rowid, oldId);
                for (int col = 0; col < table.Cols.length; col++) // Iterator used while populating OLD.*
                    if (mask == 0xffffffff || (mask & (1 << col)) != 0)
                        Expr.CodeGetColumnOfTable(v, table, curId, col, oldId + col + 1);

                // Invoke BEFORE DELETE trigger programs.
                sqlite3CodeRowTrigger(parse, trigger, TK.DELETE, null, TRIGGER.BEFORE, table, oldId, onconf, label);

                // 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.
                v.AddOp3(OP.NotExists, curId, label, rowid);

                // 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.
                FKey.FkCheck(parse, table, oldId, 0);
            }

            // Delete the index and table entries. Skip this step if table is really a view (in which case the only effect of the DELETE statement is to fire the INSTEAD OF triggers).
            if (table.Select == null)
            {
                GenerateRowIndexDelete(parse, table, curId, null);
                v.AddOp2(OP.Delete, curId, (count != 0 ? (int)OPFLAG.NCHANGE : 0));
                if (count != 0)
                    v.ChangeP4(-1, table.Name, Vdbe.P4T.TRANSIENT);
            }

            // 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.
            FKey.FkActions(parse, table, null, oldId);

            // Invoke AFTER DELETE trigger programs.
            sqlite3CodeRowTrigger(parse, trigger, TK.DELETE, null, TRIGGER.AFTER, table, oldId, onconf, label);

            // 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.
            v.ResolveLabel(label);
        }