public static void DropTriggerPtr(Parse parse, Trigger trigger) { Context ctx = parse.Ctx; int db = Prepare.SchemaToIndex(ctx, trigger.Schema); Debug.Assert(db >= 0 && db < ctx.DBs.length); Table table = TableOfTrigger(trigger); Debug.Assert(table != null); Debug.Assert(table.Schema == trigger.Schema || db == 1); #if !OMIT_AUTHORIZATION { AUTH code = AUTH.DROP_TRIGGER; string dbName = ctx.DBs[db].Name; string tableName = E.SCHEMA_TABLE(db); if (db == 1) { code = AUTH.DROP_TEMP_TRIGGER; } if (Auth.Check(parse, code, trigger.Name, table.Name, dbName) || Auth.Check(parse, AUTH.DELETE, tableName, null, dbName)) { return; } } #endif // Generate code to destroy the database record of the trigger. Debug.Assert(table != null); Vdbe v = parse.GetVdbe(); if (v != null) { parse.BeginWriteOperation(0, db); parse.OpenMasterTable(db); int base_ = v.AddOpList(_dropTrigger.Length, _dropTrigger); v.ChangeP4(base_ + 1, trigger.Name, Vdbe.P4T.TRANSIENT); v.ChangeP4(base_ + 4, "trigger", Vdbe.P4T.STATIC); parse.ChangeCookie(db); v.AddOp2(Core.OP.Close, 0, 0); v.AddOp4(Core.OP.DropTrigger, db, 0, 0, trigger.Name, 0); if (parse.Mems < 3) { parse.Mems = 3; } } }
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); }
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); }
public static void DropTriggerPtr(Parse parse, Trigger trigger) { Context ctx = parse.Ctx; int db = Prepare.SchemaToIndex(ctx, trigger.Schema); Debug.Assert(db >= 0 && db < ctx.DBs.length); Table table = TableOfTrigger(trigger); Debug.Assert(table != null); Debug.Assert(table.Schema == trigger.Schema || db == 1); #if !OMIT_AUTHORIZATION { AUTH code = AUTH.DROP_TRIGGER; string dbName = ctx.DBs[db].Name; string tableName = E.SCHEMA_TABLE(db); if (db == 1) code = AUTH.DROP_TEMP_TRIGGER; if (Auth.Check(parse, code, trigger.Name, table.Name, dbName) || Auth.Check(parse, AUTH.DELETE, tableName, null, dbName)) return; } #endif // Generate code to destroy the database record of the trigger. Debug.Assert(table != null); Vdbe v = parse.GetVdbe(); if (v != null) { parse.BeginWriteOperation(0, db); parse.OpenMasterTable(db); int base_ = v.AddOpList(_dropTrigger.Length, _dropTrigger); v.ChangeP4(base_ + 1, trigger.Name, Vdbe.P4T.TRANSIENT); v.ChangeP4(base_ + 4, "trigger", Vdbe.P4T.STATIC); parse.ChangeCookie(db); v.AddOp2(Core.OP.Close, 0, 0); v.AddOp4(Core.OP.DropTrigger, db, 0, 0, trigger.Name, 0); if (parse.Mems < 3) parse.Mems = 3; } }
public static void FinishParse(Parse parse, Token end) { Table table = parse.NewTable; // The table being constructed Context ctx = parse.Ctx; // The database connection if (table == null) { return; } AddArgumentToVtab(parse); parse.Arg.data = null; if (table.ModuleArgs.length < 1) { return; } // If the CREATE VIRTUAL TABLE statement is being entered for the first time (in other words if the virtual table is actually being // created now instead of just being read out of sqlite_master) then do additional initialization work and store the statement text // in the sqlite_master table. if (!ctx.Init.Busy) { // Compute the complete text of the CREATE VIRTUAL TABLE statement if (end != null) { parse.NameToken.length = (uint)parse.NameToken.data.Length; //: (int)(end->data - parse->NameToken) + end->length; } string stmt = C._mtagprintf(ctx, "CREATE VIRTUAL TABLE %T", parse.NameToken); //.Z.Substring(0, parse.NameToken.length)); // A slot for the record has already been allocated in the SQLITE_MASTER table. We just need to update that slot with all // the information we've collected. // // The VM register number pParse->regRowid holds the rowid of an entry in the sqlite_master table tht was created for this vtab // by sqlite3StartTable(). int db = Prepare.SchemaToIndex(ctx, table.Schema); parse.NestedParse("UPDATE %Q.%s SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q WHERE rowid=#%d", ctx.DBs[db].Name, E.SCHEMA_TABLE(db), table.Name, table.Name, stmt, parse.RegRowid ); C._tagfree(ctx, ref stmt); Vdbe v = parse.GetVdbe(); parse.ChangeCookie(db); v.AddOp2(OP.Expire, 0, 0); string where_ = C._mtagprintf(ctx, "name='%q' AND type='table'", table.Name); v.AddParseSchemaOp(db, where_); v.AddOp4(OP.VCreate, db, 0, 0, table.Name, (Vdbe.P4T)table.Name.Length + 1); } // If we are rereading the sqlite_master table create the in-memory record of the table. The xConnect() method is not called until // the first time the virtual table is used in an SQL statement. This allows a schema that contains virtual tables to be loaded before // the required virtual table implementations are registered. else { Schema schema = table.Schema; string name = table.Name; int nameLength = name.Length; Debug.Assert(Btree.SchemaMutexHeld(ctx, 0, schema)); Table oldTable = schema.TableHash.Insert(name, nameLength, table); if (oldTable != null) { ctx.MallocFailed = true; Debug.Assert(table == oldTable); // Malloc must have failed inside HashInsert() return; } parse.NewTable = null; } }