コード例 #1
0
ファイル: VTable.cs プロジェクト: BclEx/GpuStructs
        public static RC Config(Context ctx, VTABLECONFIG op, object arg1)
        {
            RC rc = RC.OK;

            MutexEx.Enter(ctx.Mutex);
            switch (op)
            {
            case VTABLECONFIG.CONSTRAINT:
            {
                VTableContext p = ctx.VTableCtx;
                if (p == null)
                {
                    rc = SysEx.MISUSE_BKPT();
                }
                else
                {
                    Debug.Assert(p.Table == null || (p.Table.TabFlags & TF.Virtual) != 0);
                    p.VTable.Constraint = (bool)arg1;
                }
                break;
            }

            default:
                rc = SysEx.MISUSE_BKPT();
                break;
            }
            if (rc != RC.OK)
            {
                Main.Error(ctx, rc, null);
            }
            MutexEx.Leave(ctx.Mutex);
            return(rc);
        }
コード例 #2
0
ファイル: Prepare.cs プロジェクト: BclEx/GpuStructs
        public static RC Prepare16(Context ctx, string sql, int bytes, bool isPrepareV2, out Vdbe stmtOut, out string tailOut)
        {
            // This function currently works by first transforming the UTF-16 encoded string to UTF-8, then invoking sqlite3_prepare(). The
            // tricky bit is figuring out the pointer to return in *pzTail.
            stmtOut = null;
            if (!sqlite3SafetyCheckOk(ctx))
            {
                return(SysEx.MISUSE_BKPT());
            }
            MutexEx.Enter(ctx.Mutex);
            RC     rc    = RC.OK;
            string tail8 = null;
            string sql8  = Vdbe.Utf16to8(ctx, sql, bytes, TEXTENCODE.UTF16NATIVE);

            if (sql8 != null)
            {
                rc = LockAndPrepare(ctx, sql8, -1, isPrepareV2, null, ref stmtOut, ref tail8);
            }
            if (tail8 != null && tailOut != null)
            {
                // If sqlite3_prepare returns a tail pointer, we calculate the equivalent pointer into the UTF-16 string by counting the unicode
                // characters between zSql8 and zTail8, and then returning a pointer the same number of characters into the UTF-16 string.
                Debugger.Break();
                //: int charsParsed = Vdbe::Utf8CharLen(sql8, (int)(tail8 - sql8));
                //: *tailOut = (uint8 *)sql + Vdbe::Utf16ByteLen(sql, charsParsed);
            }
            C._tagfree(ctx, ref sql8);
            rc = SysEx.ApiExit(ctx, rc);
            MutexEx.Leave(ctx.Mutex);
            return(rc);
        }
コード例 #3
0
ファイル: VTable.cs プロジェクト: BclEx/GpuStructs
        public static RC DeclareVTable(Context ctx, string createTableName)
        {
            MutexEx.Enter(ctx.Mutex);
            Table table;

            if (ctx.VTableCtx == null || (table = ctx.VTableCtx.Table) == null)
            {
                sqlite3Error(ctx, RC.MISUSE, null);
                MutexEx.Leave(ctx.Mutex);
                return(SysEx.MISUSE_BKPT());
            }
            Debug.Assert((table.TabFlags & TF.Virtual) != 0);

            RC    rc    = RC.OK;
            Parse parse = new Parse(); //: _stackalloc(ctx, sizeof(Parse));

            if (parse == null)
            {
                rc = RC.NOMEM;
            }
            else
            {
                parse.DeclareVTable = true;
                parse.Ctx           = ctx;
                parse.QueryLoops    = 1;

                string error = null;
                if (sqlite3RunParser(parse, createTableName, ref error) == RC.OK && parse.NewTable != null && !ctx.MallocFailed && parse.NewTable.Select == null && (parse.NewTable.TabFlags & TF.Virtual) == 0)
                {
                    if (table.Cols.data == null)
                    {
                        table.Cols.data            = parse.NewTable.Cols.data;
                        table.Cols.length          = parse.NewTable.Cols.length;
                        parse.NewTable.Cols.length = 0;
                        parse.NewTable.Cols.data   = null;
                    }
                    ctx.VTableCtx.Table = null;
                }
                else
                {
                    sqlite3Error(ctx, RC.ERROR, (error != null ? "%s" : null), error);
                    C._tagfree(ctx, ref error);
                    rc = RC.ERROR;
                }
                parse.DeclareVTable = false;

                if (parse.V != null)
                {
                    parse.V.Finalize();
                }
                Parse.DeleteTable(ctx, ref parse.NewTable);
                parse = null; //: C._stackfree(ctx, parse);
            }

            Debug.Assert(((int)rc & 0xff) == (int)rc);
            rc = SysEx.ApiExit(ctx, rc);
            MutexEx.Leave(ctx.Mutex);
            return(rc);
        }
コード例 #4
0
 public static RC Status(STATUS op, ref int current, ref int highwater, int resetFlag)
 {
     if (op < 0 || (int)op >= _stat.NowValue.Length)
     {
         return(SysEx.MISUSE_BKPT());
     }
     current   = _stat.NowValue[(int)op];
     highwater = _stat.MaxValue[(int)op];
     if (resetFlag != 0)
     {
         _stat.MaxValue[(int)op] = _stat.NowValue[(int)op];
     }
     return(RC.OK);
 }
コード例 #5
0
        public static RC Finalize(Vdbe p)
        {
            if (p == null)
            {
                return(RC.OK); // IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
            }
            Context ctx = p.Ctx;

            if (VdbeSafety(p))
            {
                return(SysEx.MISUSE_BKPT());
            }
            MutexEx.Enter(ctx.Mutex);
            RC rc = p.Finalize();

            rc = SysEx.ApiExit(ctx, rc);
            DataEx.LeaveMutexAndCloseZombie(ctx);
            return(rc);
        }
コード例 #6
0
ファイル: Prepare.cs プロジェクト: BclEx/GpuStructs
        public static RC LockAndPrepare(Context ctx, string sql, int bytes, bool isPrepareV2, Vdbe reprepare, ref Vdbe stmtOut, ref string tailOut)
        {
            if (!sqlite3SafetyCheckOk(ctx))
            {
                stmtOut = null;
                tailOut = null;
                return(SysEx.MISUSE_BKPT());
            }
            MutexEx.Enter(ctx.Mutex);
            Btree.EnterAll(ctx);
            RC rc = Prepare_(ctx, sql, bytes, isPrepareV2, reprepare, ref stmtOut, ref tailOut);

            if (rc == RC.SCHEMA)
            {
                stmtOut.Finalize();
                rc = Prepare_(ctx, sql, bytes, isPrepareV2, reprepare, ref stmtOut, ref tailOut);
            }
            Btree.LeaveAll(ctx);
            MutexEx.Leave(ctx.Mutex);
            Debug.Assert(rc == RC.OK || stmtOut == null);
            return(rc);
        }
コード例 #7
0
ファイル: VTable.cs プロジェクト: BclEx/GpuStructs
        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);
        }
コード例 #8
0
        // Routines used to attach values to wildcards in a compiled SQL statement.

        static RC VdbeUnbind(Vdbe p, int i)
        {
            if (VdbeSafetyNotNull(p))
            {
                return(SysEx.MISUSE_BKPT());
            }
            MutexEx.Enter(p.Ctx.Mutex);
            if (p.Magic != VDBE_MAGIC_RUN || p.PC >= 0)
            {
                SysEx.Error(p.Ctx, RC.MISUSE, 0);
                MutexEx.Leave(p.Ctx.Mutex);
                SysEx.LOG(RC.MISUSE, "bind on a busy prepared statement: [%s]", p.Sql);
                return(SysEx.MISUSE_BKPT());
            }
            if (i < 1 || i > p.Vars)
            {
                SysEx.Error(p.Ctx, RC.RANGE, 0);
                MutexEx.Leave(p.Ctx.Mutex);
                return(RC.RANGE);
            }
            i--;
            Mem var = p.Vars[i];

            MemRelease(var);
            var.Flags = MEM.Null;
            SysEx.Error(p.Ctx, RC.OK, 0);

            // If the bit corresponding to this variable in Vdbe.expmask is set, then binding a new value to this variable invalidates the current query plan.
            //
            // IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host parameter in the WHERE clause might influence the choice of query plan
            // for a statement, then the statement will be automatically recompiled, as if there had been a schema change, on the first sqlite3_step() call
            // following any change to the bindings of that parameter.
            if (p.IsPrepareV2 && ((i < 32 && p.Expmask != 0 & ((uint)1 << i) != 0) || p.Expmask == 0xffffffff))
            {
                p.Expired = true;
            }
            return(RC.OK);
        }
コード例 #9
0
ファイル: Main+Legacy.cs プロジェクト: BclEx/GpuStructs
        public static RC Exec(Context ctx, string sql, Func <object, int, string[], string[], bool> callback, object arg, ref string errmsg)
        {
            RC rc = RC.OK; // Return code

            if (!SafetyCheckOk(ctx))
            {
                return(SysEx.MISUSE_BKPT());
            }
            if (sql == null)
            {
                sql = string.Empty;
            }

            MutexEx.Enter(ctx.Mutex);
            Error(ctx, RC.OK, null);
            Vdbe stmt   = null;        // The current SQL statement
            int  retrys = 0;           // Number of retry attempts

            string[] colsNames = null; // Names of result columns

            while ((rc == RC.OK || (rc == RC.SCHEMA && (++retrys) < 2)) && sql.Length > 0)
            {
                stmt = null;
                string leftover = null; // Tail of unprocessed SQL
                rc = Prepare.Prepare_(ctx, sql, -1, ref stmt, ref leftover);
                Debug.Assert(rc == RC.OK || stmt == null);
                if (rc != RC.OK)
                {
                    continue;
                }
                if (stmt == null)
                {
                    sql = leftover; // this happens for a comment or white-space
                    continue;
                }

                bool callbackIsInit = false; // True if callback data is initialized
                int  cols           = Vdbe.Column_Count(stmt);

                while (true)
                {
                    rc = stmt.Step();

                    // Invoke the callback function if required
                    int i;
                    if (callback != null && (rc == RC.ROW || (rc == RC.DONE && !callbackIsInit && (ctx.Flags & Context.FLAG.NullCallback) != 0)))
                    {
                        if (!callbackIsInit)
                        {
                            colsNames = new string[cols];
                            if (colsNames == null)
                            {
                                goto exec_out;
                            }
                            for (i = 0; i < cols; i++)
                            {
                                colsNames[i] = Vdbe.Column_Name(stmt, i);
                                // Vdbe::SetColName() installs column names as UTF8 strings so there is no way for sqlite3_column_name() to fail.
                                Debug.Assert(colsNames[i] != null);
                            }
                            callbackIsInit = true;
                        }
                        string[] colsValues = null;
                        if (rc == RC.ROW)
                        {
                            colsValues = new string[cols];
                            for (i = 0; i < cols; i++)
                            {
                                colsValues[i] = Vdbe.Column_Text(stmt, i);
                                if (colsValues[i] == null && Vdbe.Column_Type(stmt, i) != TYPE.NULL)
                                {
                                    ctx.MallocFailed = true;
                                    goto exec_out;
                                }
                            }
                        }
                        if (callback(arg, cols, colsValues, colsNames))
                        {
                            rc = RC.ABORT;
                            stmt.Finalize();
                            stmt = null;
                            Error(ctx, RC.ABORT, null);
                            goto exec_out;
                        }
                    }

                    if (rc != RC.ROW)
                    {
                        rc   = stmt.Finalize();
                        stmt = null;
                        if (rc != RC.SCHEMA)
                        {
                            retrys = 0;
                            if ((sql = leftover) != string.Empty)
                            {
                                int idx = 0;
                                while (idx < sql.Length && char.IsWhiteSpace(sql[idx]))
                                {
                                    idx++;
                                }
                                if (idx != 0)
                                {
                                    sql = (idx < sql.Length ? sql.Substring(idx) : string.Empty);
                                }
                            }
                        }
                        break;
                    }
                }

                C._tagfree(ctx, ref colsNames);
                colsNames = null;
            }

exec_out:
            if (stmt != null)
            {
                stmt.Finalize();
            }
            C._tagfree(ctx, ref colsNames);

            rc = ApiExit(ctx, rc);
            if (rc != RC.OK && C._ALWAYS(rc == ErrCode(ctx)) && errmsg != null)
            {
                errmsg = ErrMsg(ctx);
            }
            else if (errmsg != null)
            {
                errmsg = null;
            }

            Debug.Assert((rc & (RC)ctx.ErrMask) == rc);
            MutexEx.Leave(ctx.Mutex);
            return(rc);
        }
コード例 #10
0
ファイル: SysEx.cs プロジェクト: BclEx/GpuEx
        public static RC Config(CONFIG op, params object[] args)
        {
            // sqlite3_config() shall return SQLITE_MISUSE if it is invoked while the SQLite library is in use.
            if (_GlobalStatics.IsInit)
            {
                return(SysEx.MISUSE_BKPT());
            }
            RC rc = RC.OK;

            switch (op)
            {
#if THREADSAFE
            // Mutex configuration options are only available in a threadsafe compile.
            case CONFIG.SINGLETHREAD:
            {         // Disable all mutexing
                _GlobalStatics.CoreMutex = false;
                _GlobalStatics.FullMutex = false;
                break;
            }

            case CONFIG.MULTITHREAD:
            {         // Disable mutexing of database connections, Enable mutexing of core data structures
                _GlobalStatics.CoreMutex = true;
                _GlobalStatics.FullMutex = false;
                break;
            }

            case CONFIG.SERIALIZED:
            {         // Enable all mutexing
                _GlobalStatics.CoreMutex = true;
                _GlobalStatics.FullMutex = true;
                break;
            }

            case CONFIG.MUTEX:
            {         // Specify an alternative mutex implementation
                //_GlobalStatics.Mutex = (sqlite3_mutex_methods)args[0];
                break;
            }

            case CONFIG.GETMUTEX:
            {         // Retrieve the current mutex implementation
                //args[0] = _GlobalStatics.Mutex;
                break;
            }
#endif
            case CONFIG.MALLOC:
            {         // Specify an alternative malloc implementation
                //_GlobalStatics.m = *va_arg(args, sqlite3_mem_methods*);
                break;
            }

            case CONFIG.GETMALLOC:
            {         // Retrieve the current malloc() implementation
                //if (_GlobalStatics.m.xMalloc==0) sqlite3MemSetDefault();
                //args[0]= _GlobalStatics.m;
                break;
            }

            case CONFIG.MEMSTATUS:
            {         // Enable or disable the malloc status collection
                _GlobalStatics.Memstat = (bool)args[0];
                break;
            }

            case CONFIG.SCRATCH:
            {         // Designate a buffer for scratch memory space
                _GlobalStatics.Scratch     = (byte[][])args[0];
                _GlobalStatics.ScratchSize = (int)args[1];
                _GlobalStatics.Scratchs    = (int)args[2];
                break;
            }

#if ENABLE_MEMSYS3 || ENABLE_MEMSYS5
            case CONFIG_HEAP: {
                // Designate a buffer for heap memory space
                _GlobalStatics.Heap.data   = va_arg(args, void *);
                _GlobalStatics.Heap.length = va_arg(args, int);
                _GlobalStatics.MinReq      = va_arg(ap, int);
                if (_GlobalStatics.MinReq < 1)
                {
                    _GlobalStatics.MinReq = 1;
                }
                else if (SysEx_GlobalStatics.MinReq > (1 << 12))       // cap min request size at 2^12
                {
                    _GlobalStatics.MinReq = (1 << 12);
                }
                if (!_GlobalStatics.Heap.data)
                {
                    // If the heap pointer is NULL, then restore the malloc implementation back to NULL pointers too.  This will cause the malloc to go back to its default implementation when sqlite3_initialize() is run.
                    memset(&_GlobalStatics.m, 0, sizeof(_GlobalStatics.m));
                }
                else
                // The heap pointer is not NULL, then install one of the mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor ENABLE_MEMSYS5 is defined, return an error.
#if ENABLE_MEMSYS3
                { _GlobalStatics.m = sqlite3MemGetMemsys3(); }
#endif
#if ENABLE_MEMSYS5
                { _GlobalStatics.m = sqlite3MemGetMemsys5(); }
#endif
                { break; }
            }
#endif
            case CONFIG.LOOKASIDE:
            {
                _GlobalStatics.LookasideSize = (int)args[0];
                _GlobalStatics.Lookasides    = (int)args[1];
                break;
            }

            case CONFIG.LOG:
            {         // Record a pointer to the logger function and its first argument. The default is NULL.  Logging is disabled if the function pointer is NULL.
                // MSVC is picky about pulling func ptrs from va lists.
                // http://support.microsoft.com/kb/47961
                _GlobalStatics.Log    = (Action <object, int, string>)args[0];
                _GlobalStatics.LogArg = (object)args[1];
                break;
            }

            case CONFIG.URI:
            {
                _GlobalStatics.OpenUri = (bool)args[0];
                break;
            }

#if ENABLE_SQLLOG
            case CONFIG.SQLLOG: {
                _GlobalStatics.Sqllog    = (Action <object, TagBase, int, string>)args[0];;
                _GlobalStatics.SqllogArg = (object)args[1];
                break;
            }
#endif
            default:
            {
                rc = RC.ERROR;
                break;
            }
            }
            return(rc);
        }
コード例 #11
0
        public RC Step2()
        {
            if (Magic != VDBE_MAGIC_RUN)
            {
                // We used to require that sqlite3_reset() be called before retrying sqlite3_step() after any error or after SQLITE_DONE.  But beginning
                // with version 3.7.0, we changed this so that sqlite3_reset() would be called automatically instead of throwing the SQLITE_MISUSE error.
                // This "automatic-reset" change is not technically an incompatibility, since any application that receives an SQLITE_MISUSE is broken by
                // definition.
                //
                // Nevertheless, some published applications that were originally written for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
                // returns, and those were broken by the automatic-reset change.  As a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
                // legacy behavior of returning SQLITE_MISUSE for cases where the previous sqlite3_step() returned something other than a SQLITE_LOCKED
                // or SQLITE_BUSY error.
#if OMIT_AUTORESET
                if (RC == RC.BUSY || RC == RC.LOCKED)
                {
                    Reset(this);
                }
                else
                {
                    return(SysEx.MISUSE_BKPT());
                }
#else
                Reset(this);
#endif
            }

            // Check that malloc() has not failed. If it has, return early.
            RC      rc;
            Context ctx = Ctx;
            if (ctx.MallocFailed)
            {
                RC_ = RC.NOMEM;
                return(RC.NOMEM);
            }

            if (PC <= 0 && Expired)
            {
                RC_ = RC.SCHEMA;
                rc  = RC.ERROR;
                goto end_of_step;
            }
            if (PC < 0)
            {
                // If there are no other statements currently running, then reset the interrupt flag.  This prevents a call to sqlite3_interrupt
                // from interrupting a statement that has not yet started.
                if (ctx.ActiveVdbeCnt == 0)
                {
                    ctx.u1.IsInterrupted = false;
                }
                Debug.Assert(ctx.WriteVdbeCnt > 0 || ctx.AutoCommit == 0 || ctx.DeferredCons == 0);
#if  !OMIT_TRACE
                if (ctx.Profile != null && !ctx.Init.Busy)
                {
                    ctx.Vfs.CurrentTimeInt64(ref StartTime);
                }
#endif
                ctx.ActiveVdbeCnt++;
                if (!ReadOnly)
                {
                    ctx.WriteVdbeCnt++;
                }
                PC = 0;
            }

#if  !OMIT_EXPLAIN
            if (_explain)
            {
                rc = List();
            }
            else
#endif
            {
                ctx.VdbeExecCnt++;
                rc = Exec();
                ctx.VdbeExecCnt--;
            }

#if !OMIT_TRACE
            // Invoke the profile callback if there is one
            if (rc != RC.ROW && ctx.Profile != null && !ctx.Init.Busy && Sql != null)
            {
                long now = 0;
                ctx.Vfs.CurrentTimeInt64(ref now);
                ctx.Profile(ctx.ProfileArg, Sql, (now - StartTime) * 1000000);
            }
#endif

            if (rc == RC.DONE)
            {
                Debug.Assert(RC_ == RC.OK);
                RC_ = DoWalCallbacks(ctx);
                if (RC_ != RC.OK)
                {
                    rc = RC.ERROR;
                }
            }

            ctx.ErrCode = rc;
            if (SysEx.ApiExit(Ctx, RC_) == RC.NOMEM)
            {
                RC_ = RC.NOMEM;
            }

end_of_step:
            // At this point local variable rc holds the value that should be returned if this statement was compiled using the legacy
            // sqlite3_prepare() interface. According to the docs, this can only be one of the values in the first assert() below. Variable p->rc
            // contains the value that would be returned if sqlite3_finalize() were called on statement p.
            Debug.Assert(rc == RC.ROW || rc == RC.DONE || rc == RC.ERROR || rc == RC.BUSY || rc == RC.MISUSE);
            Debug.Assert(RC_ != RC.ROW && RC_ != RC.DONE);
            // If this statement was prepared using sqlite3_prepare_v2(), and an error has occurred, then return the error code in p->rc to the
            // caller. Set the error code in the database handle to the same value.
            if (IsPrepareV2 && rc != RC.ROW && rc != RC.DONE)
            {
                rc = TransferError();
            }
            return(rc & (RC)ctx.ErrMask);
        }