Exemplo n.º 1
0
        public static RC CallCreate(Context ctx, int db, string tableName, ref string errorOut)
        {
            Table table = Parse.FindTable(ctx, tableName, ctx.DBs[db].Name);

            Debug.Assert(table != null && (table.TabFlags & TF.Virtual) != 0 && table.VTables == null);

            // Locate the required virtual table module
            string      moduleName = table.ModuleArgs[0];
            TableModule module     = (TableModule)ctx.Modules.Find(moduleName, moduleName.Length, (TableModule)null);

            // If the module has been registered and includes a Create method, invoke it now. If the module has not been registered, return an
            // error. Otherwise, do nothing.
            RC rc = RC.OK;

            if (module == null)
            {
                errorOut = C._mtagprintf(ctx, "no such module: %s", moduleName);
                rc       = RC.ERROR;
            }
            else
            {
                rc = VTableCallConstructor(ctx, table, module, module.IModule.Create, ref errorOut);
            }

            // Justification of ALWAYS():  The xConstructor method is required to create a valid sqlite3_vtab if it returns SQLITE_OK.
            if (rc == RC.OK && C._ALWAYS(GetVTable(ctx, table) != null))
            {
                rc = GrowVTrans(ctx);
                if (rc == RC.OK)
                {
                    AddToVTrans(ctx, GetVTable(ctx, table));
                }
            }
            return(rc);
        }
Exemplo n.º 2
0
        public static RC CallConnect(Parse parse, Table table)
        {
            Debug.Assert(table != null);
            Context ctx = parse.Ctx;

            if ((table.TabFlags & TF.Virtual) == 0 || GetVTable(ctx, table) != null)
            {
                return(RC.OK);
            }

            // Locate the required virtual table module
            string      moduleName = table.ModuleArgs[0];
            TableModule module     = (TableModule)ctx.Modules.Find(moduleName, moduleName.Length, (TableModule)null);

            if (module == null)
            {
                parse.ErrorMsg("no such module: %s", moduleName);
                return(RC.ERROR);
            }

            string error = null;
            RC     rc    = VTableCallConstructor(ctx, table, module, module.IModule.Connect, ref error);

            if (rc != RC.OK)
            {
                parse.ErrorMsg("%s", error);
            }
            C._tagfree(ctx, ref error);
            return(rc);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }