public static RC Savepoint(Context ctx, IPager.SAVEPOINT op, int savepoint) { Debug.Assert(op == IPager.SAVEPOINT.RELEASE || op == IPager.SAVEPOINT.ROLLBACK || op == IPager.SAVEPOINT.BEGIN); Debug.Assert(savepoint >= 0); RC rc = RC.OK; if (ctx.VTrans.data != null) { for (int i = 0; rc == RC.OK && i < ctx.VTrans.length; i++) { VTable vtable = ctx.VTrans[i]; ITableModule itablemodule = vtable.Module.IModule; if (vtable.IVTable != null && itablemodule.Version >= 2) { Func <VTable, int, int> method = null; switch (op) { case IPager.SAVEPOINT.BEGIN: method = itablemodule.Savepoint; vtable.Savepoints = savepoint + 1; break; case IPager.SAVEPOINT.ROLLBACK: method = itablemodule.RollbackTo; break; default: method = itablemodule.Release; break; } if (method != null && vtable.Savepoints > savepoint) { rc = (RC)method(vtable.IVTable, savepoint); } } } } return(rc); }
public static RC Begin(Context ctx, VTable vtable) { // Special case: If ctx->aVTrans is NULL and ctx->nVTrans is greater than zero, then this function is being called from within a // virtual module xSync() callback. It is illegal to write to virtual module tables in this case, so return SQLITE_LOCKED. if (InSync(ctx)) { return(RC.LOCKED); } if (vtable == null) { return(RC.OK); } RC rc = RC.OK; ITableModule imodule = vtable.IVTable.IModule; if (imodule.Begin != null) { // If pVtab is already in the aVTrans array, return early for (int i = 0; i < ctx.VTrans.length; i++) { if (ctx.VTrans[i] == vtable) { return(RC.OK); } } // Invoke the xBegin method. If successful, add the vtab to the sqlite3.aVTrans[] array. rc = GrowVTrans(ctx); if (rc == RC.OK) { rc = imodule.Begin(vtable.IVTable); if (rc == RC.OK) { AddToVTrans(ctx, vtable); } } } return(rc); }
public static RC CreateModule(Context ctx, string name, ITableModule imodule, object aux, Action <object> destroy) { RC rc = RC.OK; MutexEx.Enter(ctx.Mutex); int nameLength = name.Length; if (ctx.Modules.Find(name, nameLength, (TableModule)null) != null) { rc = SysEx.MISUSE_BKPT(); } else { TableModule module = new TableModule(); //: _tagalloc(ctx, sizeof(TableModule) + nameLength + 1) if (module != null) { var nameCopy = name; module.Name = nameCopy; module.IModule = imodule; module.Aux = aux; module.Destroy = destroy; TableModule del = (TableModule)ctx.Modules.Insert(nameCopy, nameLength, module); Debug.Assert(del == null && del == module); if (del != null) { ctx.MallocFailed = true; C._tagfree(ctx, ref del); } } } rc = SysEx.ApiExit(ctx, rc); if (rc != RC.OK && destroy != null) { destroy(aux); } MutexEx.Leave(ctx.Mutex); return(rc); }
public static FuncDef OverloadFunction(Context ctx, FuncDef def, int argsLength, Expr expr) { // Check to see the left operand is a column in a virtual table if (C._NEVER(expr == null)) { return(def); } if (expr.OP != TK.COLUMN) { return(def); } Table table = expr.Table; if (C._NEVER(table == null)) { return(def); } if ((table.TabFlags & TF.Virtual) == 0) { return(def); } IVTable ivtable = GetVTable(ctx, table).IVTable; Debug.Assert(ivtable != null); Debug.Assert(ivtable.IModule != null); ITableModule imodule = (ITableModule)ivtable.IModule; if (imodule.FindFunction == null) { return(def); } // Call the xFindFunction method on the virtual table implementation to see if the implementation wants to overload this function string lowerName = def.Name; RC rc = RC.OK; Action <FuncContext, int, Mem[]> func = null; object[] args = null; if (lowerName != null) { lowerName = lowerName.ToLowerInvariant(); rc = imodule.FindFunction(ivtable, argsLength, lowerName, func, args); C._tagfree(ctx, ref lowerName); } if (rc == RC.OK) { return(def); } // Create a new ephemeral function definition for the overloaded function FuncDef newFunc = new FuncDef();//: (FuncDef*)_tagalloc(ctx, sizeof(FuncDef) + _strlen30(def->Name) + 1, true); if (newFunc == null) { return(def); } newFunc = def._memcpy(); newFunc.Name = def.Name; newFunc.Func = func; newFunc.UserData = args; newFunc.Flags |= FUNC.EPHEM; return(newFunc); }