public static void Disconnect(Context ctx, Table table) { Debug.Assert(E.IsVirtual(table)); Debug.Assert(Btree.HoldsAllMutexes(ctx)); Debug.Assert(MutexEx.Held(ctx.Mutex)); for (VTable pvtable = table.VTables; pvtable != null; pvtable = pvtable.Next) { if (pvtable.Ctx == ctx) { VTable vtable = pvtable; vtable = vtable.Next; vtable.Unlock(); break; } } }
public static void UnlockList(Context ctx) { Debug.Assert(Btree.HoldsAllMutexes(ctx)); Debug.Assert(MutexEx.Held(ctx.Mutex)); VTable vtable = ctx.Disconnect; ctx.Disconnect = null; if (vtable != null) { Vdbe.ExpirePreparedStatements(ctx); do { VTable next = vtable.Next; vtable.Unlock(); vtable = next; } while (vtable != null); } }
public static RC CallDestroy(Context ctx, int db, string tableName) { RC rc = RC.OK; Table table = Parse.FindTable(ctx, tableName, ctx.DBs[db].Name); if (C._ALWAYS(table != null && table.VTables != null)) { VTable vtable = VTableDisconnectAll(ctx, table); Debug.Assert(rc == RC.OK); rc = vtable.Module.IModule.Destroy(vtable.IVTable); // Remove the sqlite3_vtab* from the aVTrans[] array, if applicable if (rc == RC.OK) { Debug.Assert(table.VTables == vtable && vtable.Next == null); vtable.IVTable = null; table.VTables = null; vtable.Unlock(); } } return(rc); }
static void CallFinaliser(Context ctx, int offset) { if (ctx.VTrans.data != null) { for (int i = 0; i < ctx.VTrans.length; i++) { VTable vtable = ctx.VTrans[i]; IVTable ivtable = vtable.IVTable; if (ivtable != null) { Func <IVTable, int> x = null; if (offset == 0) { x = ivtable.IModule.Rollback; } else if (offset == 1) { x = ivtable.IModule.Commit; } else { throw new InvalidOperationException(); } if (x != null) { x(ivtable); } } vtable.Savepoints = 0; vtable.Unlock(); } C._tagfree(ctx, ref ctx.VTrans.data); ctx.VTrans.length = 0; ctx.VTrans.data = null; } }
static RC VTableCallConstructor(Context ctx, Table table, TableModule module, Construct_t construct, ref string errorOut) { string moduleName = table.Name; if (moduleName == null) { return(RC.NOMEM); } VTable vtable = new VTable(); if (vtable == null) { C._tagfree(ctx, ref moduleName); return(RC.NOMEM); } vtable.Ctx = ctx; vtable.Module = module; int db = sqlite3SchemaToIndex(ctx, table.Schema); table.ModuleArgs[1] = ctx.DBs[db].Name; // Invoke the virtual table constructor Debug.Assert(ctx.VTableCtx != null); Debug.Assert(construct != null); VTableContext sVtableCtx = new VTableContext(); sVtableCtx.Table = table; sVtableCtx.VTable = vtable; VTableContext priorCtx = ctx.VTableCtx; ctx.VTableCtx = sVtableCtx; string[] args = table.ModuleArgs.data; int argsLength = table.ModuleArgs.length; string error = null; RC rc = construct(ctx, module.Aux, argsLength, args, out vtable.IVTable, out error); ctx.VTableCtx = null; if (rc == RC.NOMEM) { ctx.MallocFailed = true; } if (rc != RC.OK) { if (error == null) { errorOut = C._mtagprintf(ctx, "vtable constructor failed: %s", moduleName); } else { errorOut = error; error = null; //: _free(error); } C._tagfree(ctx, ref vtable); } else if (C._ALWAYS(vtable.IVTable != null)) { // Justification of ALWAYS(): A correct vtab constructor must allocate the sqlite3_vtab object if successful. vtable.IVTable.IModule = module.IModule; vtable.Refs = 1; if (sVtableCtx.Table != null) { errorOut = C._mtagprintf(ctx, "vtable constructor did not declare schema: %s", table.Name); vtable.Unlock(); rc = RC.ERROR; } else { // If everything went according to plan, link the new VTable structure into the linked list headed by pTab->pVTable. Then loop through the // columns of the table to see if any of them contain the token "hidden". If so, set the Column COLFLAG_HIDDEN flag and remove the token from // the type string. vtable.Next = table.VTables; table.VTables = vtable; for (int col = 0; col < table.Cols.length; col++) { string type = table.Cols[col].Type; if (type == null) { continue; } int typeLength = type.Length; int i = 0; if (string.Compare("hidden", 0, type, 0, 6, StringComparison.OrdinalIgnoreCase) == 0 || (type.Length > 6 && type[6] != ' ')) { for (i = 0; i < typeLength; i++) { if (string.Compare(" hidden", 0, type, i, 7, StringComparison.OrdinalIgnoreCase) == 0 && (i + 7 == type.Length || (type[i + 7] == '\0' || type[i + 7] == ' '))) { i++; break; } } } if (i < typeLength) { StringBuilder type2 = new StringBuilder(type); int del = 6 + (type2.Length > i + 6 ? 1 : 0); int j; for (j = i; (j + del) < typeLength; j++) { type2[j] = type2[j + del]; } if (type2[i] == '\0' && i > 0) { Debug.Assert(type[i - 1] == ' '); type2.Length = i; //: type[i - 1] = '\0'; } table.Cols[col].ColFlags |= COLFLAG.HIDDEN; table.Cols[col].Type = type.ToString().Substring(0, j); } } } } C._tagfree(ctx, ref moduleName); return(rc); }