Example #1
0
 public static void MemReleaseExternal(Mem mem)
 {
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     if ((mem.Flags & MEM.Agg) != 0)
     {
         MemFinalize(mem, mem.u.Def);
         Debug.Assert((mem.Flags & MEM.Agg) == 0);
         MemRelease(mem);
     }
     else if ((mem.Flags & MEM.Dyn) != 0 && mem.Del != null)
     {
         Debug.Assert((mem.Flags & MEM.RowSet) == 0);
         mem.Del(mem.Z);
         mem.Del = null;
     }
     else if ((mem.Flags & MEM.RowSet) != 0)
     {
         RowSet_Clear(mem.u.RowSet);
     }
     else if ((mem.Flags & MEM.Frame) != 0)
     {
         MemSetNull(mem);
     }
     mem.N  = 0;
     mem.Z  = null;
     mem.Z_ = null;
 }
Example #2
0
 public static double RealValue(Mem mem)
 {
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     //Debug.Assert(C._HASALIGNMENT8(mem));
     if ((mem.Flags & MEM.Real) != 0)
     {
         return(mem.R);
     }
     else if ((mem.Flags & MEM.Int) != 0)
     {
         return((double)mem.u.I);
     }
     else if ((mem.Flags & (MEM.Str)) != 0)
     {
         double val = (double)0;
         ConvertEx.Atof(mem.Z, ref val, mem.N, mem.Encode);
         return(val);
     }
     else if ((mem.Flags & (MEM.Blob)) != 0)
     {
         double val = (double)0;
         Debug.Assert(mem.Z_ != null || mem.N == 0);
         ConvertEx.Atof(Encoding.UTF8.GetString(mem.Z_, 0, mem.N), ref val, mem.N, mem.Encode);
         return(val);
     }
     return((double)0);
 }
Example #3
0
        public static long IntValue(Mem mem)
        {
            Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
            // assert( EIGHT_BYTE_ALIGNMENT(pMem) );
            MEM flags = mem.Flags;

            if ((flags & MEM.Int) != 0)
            {
                return(mem.u.I);
            }
            else if ((flags & MEM.Real) != 0)
            {
                return(DoubleToInt64(mem.R));
            }
            else if ((flags & (MEM.Str)) != 0)
            {
                Debug.Assert(mem.Z != null || mem.N == 0);
                C.ASSERTCOVERAGE(mem.Z == null);
                long value;
                ConvertEx.Atoi64(mem.Z, out value, mem.N, mem.Encode);
                return(value);
            }
            else if ((flags & (MEM.Blob)) != 0)
            {
                Debug.Assert(mem.Z_ != null || mem.N == 0);
                C.ASSERTCOVERAGE(mem.Z_ == null);
                long value;
                ConvertEx.Atoi64(Encoding.UTF8.GetString(mem.Z_, 0, mem.N), out value, mem.N, mem.Encode);
                return(value);
            }
            return(0);
        }
Example #4
0
 public static RC MemNumerify(Mem mem)
 {
     if ((mem.Flags & (MEM.Int | MEM.Real | MEM.Null)) == 0)
     {
         Debug.Assert((mem.Flags & (MEM.Blob | MEM.Str)) != 0);
         Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
         if ((mem.Flags & MEM.Blob) != 0 && mem.Z == null)
         {
             if (ConvertEx.Atoi64(Encoding.UTF8.GetString(mem.Z_, 0, mem.Z_.Length), out mem.u.I, mem.N, mem.Encode) == 0)
             {
                 E.MemSetTypeFlag(mem, MEM.Int);
             }
             else
             {
                 mem.R = RealValue(mem);
                 E.MemSetTypeFlag(mem, MEM.Real);
                 IntegerAffinity(mem);
             }
         }
         else if (ConvertEx.Atoi64(mem.Z, out mem.u.I, mem.N, mem.Encode) == 0)
         {
             E.MemSetTypeFlag(mem, MEM.Int);
         }
         else
         {
             mem.R = RealValue(mem);
             E.MemSetTypeFlag(mem, MEM.Real);
             IntegerAffinity(mem);
         }
     }
     Debug.Assert((mem.Flags & (MEM.Int | MEM.Real | MEM.Null)) != 0);
     mem.Flags &= ~(MEM.Str | MEM.Blob);
     return(RC.OK);
 }
Example #5
0
        public static RC Reprepare(Vdbe p)
        {
            Context ctx = p.Ctx;

            Debug.Assert(MutexEx.Held(ctx.Mutex));
            string sql = Vdbe.Sql(p);

            Debug.Assert(sql != null); // Reprepare only called for prepare_v2() statements
            Vdbe newVdbe = new Vdbe();
            RC   rc      = LockAndPrepare(ctx, sql, -1, false, p, ref newVdbe, null);

            if (rc != 0)
            {
                if (rc == RC.NOMEM)
                {
                    ctx.MallocFailed = true;
                }
                Debug.Assert(newVdbe == null);
                return(rc);
            }
            else
            {
                Debug.Assert(newVdbe != null);
            }
            Vdbe.Swap((Vdbe)newVdbe, p);
            Vdbe.TransferBindings(newVdbe, (Vdbe)p);
            newVdbe.ResetStepResult();
            newVdbe.Finalize();
            return(RC.OK);
        }
Example #6
0
 public static RC MemExpandBlob(Mem mem)
 {
     if ((mem.Flags & MEM.Zero) != 0)
     {
         Debug.Assert((mem.Flags & MEM.Blob) != 0);
         Debug.Assert((mem.Flags & MEM.RowSet) == 0);
         Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
         // Set nByte to the number of bytes required to store the expanded blob.
         int bytes = mem.N + mem.u.Zeros;
         if (bytes <= 0)
         {
             bytes = 1;
         }
         if (MemGrow(mem, bytes, true) != 0)
         {
             return(RC.NOMEM);
         }
         //: _memset(&mem->Z[mem->N], 0, mem->u.Zeros);
         mem.Z_     = Encoding.UTF8.GetBytes(mem.Z);
         mem.Z      = null;
         mem.N     += (int)mem.u.Zeros;
         mem.u.I    = 0;
         mem.Flags &= ~(MEM.Zero | MEM.Static | MEM.Ephem | MEM.Term);
         mem.Flags |= MEM.Dyn;
     }
     return(RC.OK);
 }
Example #7
0
 public static void Result_ErrorNoMem(FuncContext fctx)
 {
     Debug.Assert(MutexEx.Held(fctx.S.Ctx.Mutex));
     MemSetNull(fctx.S);
     fctx.IsError            = RC.NOMEM;
     fctx.S.Ctx.MallocFailed = true;
 }
Example #8
0
 public static RC MemRealify(Mem mem)
 {
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     //Debug.Assert(C._HASALIGNMENT8(mem));
     mem.R = RealValue(mem);
     E.MemSetTypeFlag(mem, MEM.Real);
     return(RC.OK);
 }
Example #9
0
 public static void CloseExtensions(Context ctx)
 {
     Debug.Assert(MutexEx.Held(ctx.Mutex));
     for (int i = 0; i < ctx.Extensions.length; i++)
     {
         ctx.Vfs.DlClose((HANDLE)ctx.Extensions[i]);
     }
     C._tagfree(ctx, ref ctx.Extensions.data);
 }
Example #10
0
 public static RC MemIntegerify(Mem mem)
 {
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     Debug.Assert((mem.Flags & MEM.RowSet) == 0);
     //Debug.Assert(C._HASALIGNMENT8(mem));
     mem.u.I = IntValue(mem);
     E.MemSetTypeFlag(mem, MEM.Int);
     return(RC.OK);
 }
Example #11
0
        public static RC MemStringify(Mem mem, TEXTENCODE encode)
        {
            MEM f = mem.Flags;

            Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
            Debug.Assert((f & MEM.Zero) == 0);
            Debug.Assert((f & (MEM.Str | MEM.Blob)) == 0);
            Debug.Assert((f & (MEM.Int | MEM.Real)) != 0);
            Debug.Assert((mem.Flags & MEM.RowSet) == 0);
            //: Debug.Assert(C._HASALIGNMENT8(mem));

            const int bytes = 32;

            if (MemGrow(mem, bytes, false) != 0)
            {
                return(RC.NOMEM);
            }

            // For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 string representation of the value. Then, if the required encoding
            // is UTF-16le or UTF-16be do a translation.
            // FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
            if ((f & MEM.Int) != 0)
            {
                mem.Z = mem.u.I.ToString(); //: __snprintf(mem->Z, bytes, "%lld", mem->u.I);
            }
            else
            {
                Debug.Assert((f & MEM.Real) != 0);
                if (double.IsNegativeInfinity(mem.R))
                {
                    mem.Z = "-Inf";
                }
                else if (double.IsInfinity(mem.R))
                {
                    mem.Z = "Inf";
                }
                else if (double.IsPositiveInfinity(mem.R))
                {
                    mem.Z = "+Inf";
                }
                else if (mem.R.ToString(CultureInfo.InvariantCulture).Contains("."))
                {
                    mem.Z = mem.R.ToString(CultureInfo.InvariantCulture).ToLower();                                                                  //: __snprintf(mem->Z, bytes, "%!.15g", mem->R);
                }
                else
                {
                    mem.Z = mem.R.ToString(CultureInfo.InvariantCulture) + ".0";
                }
            }
            mem.N      = mem.Z.Length;
            mem.Encode = TEXTENCODE.UTF8;
            mem.Flags |= MEM.Str | MEM.Term;
            ChangeEncoding(mem, encode);
            return(RC.OK);
        }
Example #12
0
        public static object get_Auxdata(FuncContext fctx, int arg)
        {
            Debug.Assert(MutexEx.Held(fctx.S.Ctx.Mutex));
            VdbeFunc vdbeFunc = fctx.VdbeFunc;

            if (vdbeFunc == null || arg >= vdbeFunc.AuxsLength || arg < 0)
            {
                return(null);
            }
            return(vdbeFunc.Auxs[arg].Aux);
        }
Example #13
0
        public static RC MemSetStr(Mem mem, byte[] z, int offset, int n, TEXTENCODE encode, Action <object> del)
        {
            Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
            Debug.Assert((mem.Flags & MEM.RowSet) == 0);
            // If z is a NULL pointer, set pMem to contain an SQL NULL.
            if (z == null || z.Length < offset)
            {
                MemSetNull(mem);
                return(RC.OK);
            }

            int limit = (mem.Ctx != null ? mem.Ctx.Limits[(int)LIMIT.LENGTH] : CORE_MAX_LENGTH); // Maximum allowed string or blob size
            MEM flags = (encode == 0 ? MEM.Blob : MEM.Str);                                      // New value for pMem->flags
            int bytes = n;                                                                       // New value for pMem->n

            if (bytes < 0)
            {
                Debug.Assert(encode != 0);
                if (encode == TEXTENCODE.UTF8)
                {
                    for (bytes = 0; bytes <= limit && bytes < z.Length - offset && z[offset + bytes] != 0; bytes++)
                    {
                    }
                }
                else
                {
                    for (bytes = 0; bytes <= limit && z[bytes + offset] != 0 || z[offset + bytes + 1] != 0; bytes += 2)
                    {
                    }
                }
            }

            // The following block sets the new values of Mem.z and Mem.xDel. It also sets a flag in local variable "flags" to indicate the memory
            // management (one of MEM_Dyn or MEM_Static).
            Debug.Assert(encode == 0);
            {
                mem.Z  = null;
                mem.Z_ = C._alloc(n);
                Buffer.BlockCopy(z, offset, mem.Z_, 0, n);
            }
            mem.N      = bytes;
            mem.Flags  = MEM.Blob | MEM.Term;
            mem.Encode = (encode == 0 ? TEXTENCODE.UTF8 : encode);
            mem.Type   = (encode == 0 ? TYPE.BLOB : TYPE.TEXT);

#if !OMIT_UTF16
            if (mem.Encode != TEXTENCODE.UTF8 && MemHandleBom(mem) != 0)
            {
                return(RC.NOMEM);
            }
#endif
            return(bytes > limit ? RC.TOOBIG : RC.OK);
        }
Example #14
0
 public static void MemMove(Mem to, Mem from)
 {
     Debug.Assert(from.Ctx == null || MutexEx.Held(from.Ctx.Mutex));
     Debug.Assert(to.Ctx == null || MutexEx.Held(to.Ctx.Mutex));
     Debug.Assert(from.Ctx == null || to.Ctx == null || from.Ctx == to.Ctx);
     MemRelease(to);
     from._memcpy(ref to);
     from.Flags = MEM.Null;
     from.Del   = null;
     from.Z     = null;
     from.Z_    = null;
 }
Example #15
0
        static void SchemaIsValid(Parse parse)
        {
            Context ctx = parse.Ctx;

            Debug.Assert(parse.CheckSchema != 0);
            Debug.Assert(MutexEx.Held(ctx.Mutex));
            for (int db = 0; db < ctx.DBs.length; db++)
            {
                bool  openedTransaction = false; // True if a transaction is opened
                Btree bt = ctx.DBs[db].Bt;       // Btree database to read cookie from
                if (bt == null)
                {
                    continue;
                }

                // If there is not already a read-only (or read-write) transaction opened on the b-tree database, open one now. If a transaction is opened, it
                // will be closed immediately after reading the meta-value.
                if (!bt.IsInReadTrans())
                {
                    RC rc = bt.BeginTrans(0);
                    if (rc == RC.NOMEM || rc == RC.IOERR_NOMEM)
                    {
                        ctx.MallocFailed = true;
                    }
                    if (rc != RC.OK)
                    {
                        return;
                    }
                    openedTransaction = true;
                }

                // Read the schema cookie from the database. If it does not match the value stored as part of the in-memory schema representation,
                // set Parse.rc to SQLITE_SCHEMA.
                uint cookie;
                bt.GetMeta(Btree.META.SCHEMA_VERSION, ref cookie);
                Debug.Assert(Btree.SchemaMutexHeld(ctx, db, null));
                if (cookie != ctx.DBs[db].Schema.SchemaCookie)
                {
                    ResetOneSchema(ctx, db);
                    parse.RC = RC.SCHEMA;
                }

                // Close the transaction, if one was opened.
                if (openedTransaction)
                {
                    bt.Commit();
                }
            }
        }
Example #16
0
 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;
         }
     }
 }
Example #17
0
        public static RC ReadSchema(Parse parse)
        {
            RC      rc  = RC.OK;
            Context ctx = parse.Ctx;

            Debug.Assert(MutexEx.Held(ctx.Mutex));
            if (!ctx.Init.Busy)
            {
                rc = Init(ctx, ref parse.ErrMsg);
            }
            if (rc != RC.OK)
            {
                parse.RC = rc;
                parse.Errs++;
            }
            return(rc);
        }
Example #18
0
        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);
            }
        }
Example #19
0
 public static void IntegerAffinity(Mem mem)
 {
     Debug.Assert((mem.Flags & MEM.Real) != 0);
     Debug.Assert((mem.Flags & MEM.RowSet) == 0);
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     //Debug.Assert(C._HASALIGNMENT8(mem));
     mem.u.I = DoubleToInt64(mem.R);
     // Only mark the value as an integer if
     //    (1) the round-trip conversion real->int->real is a no-op, and
     //    (2) The integer is neither the largest nor the smallest possible integer (ticket #3922)
     // The second and third terms in the following conditional enforces the second condition under the assumption that addition overflow causes
     // values to wrap around.  On x86 hardware, the third term is always true and could be omitted.  But we leave it in because other
     // architectures might behave differently.
     if (mem.R == (double)mem.u.I && mem.u.I > long.MinValue && C._ALWAYS(mem.u.I < long.MaxValue))
     {
         mem.Flags |= MEM.Int;
     }
 }
Example #20
0
 public static RC MemNulTerminate(Mem mem)
 {
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     if ((mem.Flags & MEM.Term) != 0 || (mem.Flags & MEM.Str) == 0)
     {
         return(RC.OK); // Nothing to do
     }
     if (MemGrow(mem, mem.N + 2, true) != 0)
     {
         return(RC.NOMEM);
     }
     //mem.Z[mem.N] = 0;
     //mem.Z[mem.N + 1] = 0;
     if (mem.Z != null && mem.N < mem.Z.Length)
     {
         mem.Z = mem.Z.Substring(0, mem.N);
     }
     mem.Flags |= MEM.Term;
     return(RC.OK);
 }
Example #21
0
        public static RC Init(Context ctx, ref string errMsg)
        {
            Debug.Assert(MutexEx.Held(ctx.Mutex));
            RC rc = RC.OK;

            ctx.Init.Busy = true;
            for (int i = 0; rc == RC.OK && i < ctx.DBs.length; i++)
            {
                if (E.DbHasProperty(ctx, i, SCHEMA.SchemaLoaded) || i == 1)
                {
                    continue;
                }
                rc = InitOne(ctx, i, ref errMsg);
                if (rc != 0)
                {
                    ResetOneSchema(ctx, i);
                }
            }

            // Once all the other databases have been initialized, load the schema for the TEMP database. This is loaded last, as the TEMP database
            // schema may contain references to objects in other databases.
#if !OMIT_TEMPDB
            if (rc == RC.OK && C._ALWAYS(ctx.DBs.length > 1) && !E.DbHasProperty(ctx, 1, SCHEMA.SchemaLoaded))
            {
                rc = InitOne(ctx, 1, ref errMsg);
                if (rc != 0)
                {
                    ResetOneSchema(ctx, 1);
                }
            }
#endif

            bool commitInternal = !((ctx.Flags & Context.FLAG.InternChanges) != 0);
            ctx.Init.Busy = false;
            if (rc == RC.OK && commitInternal)
            {
                CommitInternalChanges(ctx);
            }
            return(rc);
        }
Example #22
0
        public static RC MemFinalize(Mem mem, FuncDef func)
        {
            RC rc = RC.OK;

            if (C._ALWAYS(func != null && func.Finalize != null))
            {
                Debug.Assert((mem.Flags & MEM.Null) != 0 || func == mem.u.Def);
                Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
                //memset(&ctx, 0, sizeof(ctx));
                FuncContext ctx = new FuncContext();
                ctx.S.Flags = MEM.Null;
                ctx.S.Ctx   = mem.Ctx;
                ctx.Mem     = mem;
                ctx.Func    = func;
                func.Finalize(ctx);              // IMP: R-24505-23230
                Debug.Assert((mem.Flags & MEM.Dyn) == 0 && mem.Del == null);
                C._tagfree(mem.Ctx, ref mem.Z_); //: mem->Malloc);
                ctx.S._memcpy(ref mem);
                rc = ctx.IsError;
            }
            return(rc);
        }
Example #23
0
        public static RC MemMakeWriteable(Mem mem)
        {
            Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
            Debug.Assert((mem.Flags & MEM.RowSet) == 0);
            E.ExpandBlob(mem);
            MEM f = mem.Flags;

            if ((f & (MEM.Str | MEM.Blob)) != 0) //: mem->Z != mem->Malloc)
            {
                if (MemGrow(mem, mem.N + 2, true) != 0)
                {
                    return(RC.NOMEM);
                }
                //: mem.Z[mem.N] = 0;
                //: mem.Z[mem.N + 1] = 0;
                mem.Flags |= MEM.Term;
#if DEBUG
                mem.ScopyFrom = null;
#endif
            }
            return(RC.OK);
        }
Example #24
0
 public static string ValueText(Mem mem, TEXTENCODE encode)
 {
     if (mem == null)
     {
         return(null);
     }
     Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
     Debug.Assert((encode & (TEXTENCODE)3) == (encode & ~TEXTENCODE.UTF16_ALIGNED));
     Debug.Assert((mem.Flags & MEM.RowSet) == 0);
     if ((mem.Flags & MEM.Null) != 0)
     {
         return(null);
     }
     Debug.Assert(((int)MEM.Blob >> 3) == (int)MEM.Str);
     mem.Flags |= (MEM)((int)(mem.Flags & MEM.Blob) >> 3);
     E.ExpandBlob(mem);
     if ((mem.Flags & MEM.Str) != 0)
     {
         ChangeEncoding(mem, encode & ~TEXTENCODE.UTF16_ALIGNED);
         if ((encode & TEXTENCODE.UTF16_ALIGNED) != 0 && (1 & (mem.Z[0])) == 1)
         {
             Debug.Assert((mem.Flags & (MEM.Ephem | MEM.Static)) != 0);
             if (MemMakeWriteable(mem) != RC.OK)
             {
                 return(null);
             }
         }
         MemNulTerminate(mem); // IMP: R-31275-44060
     }
     else
     {
         Debug.Assert((mem.Flags & MEM.Blob) == 0);
         MemStringify(mem, encode);
         Debug.Assert((1 & (mem.Z[0])) == 0);
     }
     Debug.Assert(mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) || mem.Ctx == null || mem.Ctx.MallocFailed);
     return(mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) ? mem.Z : null);
 }
Example #25
0
        public static int SchemaToIndex(Context ctx, Schema schema)
        {
            // If pSchema is NULL, then return -1000000. This happens when code in expr.c is trying to resolve a reference to a transient table (i.e. one
            // created by a sub-select). In this case the return value of this function should never be used.
            //
            // We return -1000000 instead of the more usual -1 simply because using -1000000 as the incorrect index into ctx->aDb[] is much
            // more likely to cause a segfault than -1 (of course there are assert() statements too, but it never hurts to play the odds).
            Debug.Assert(MutexEx.Held(ctx.Mutex));
            int i = -1000000;

            if (schema != null)
            {
                for (i = 0; C._ALWAYS(i < ctx.DBs.length); i++)
                {
                    if (ctx.DBs[i].Schema == schema)
                    {
                        break;
                    }
                }
                Debug.Assert(i >= 0 && i < ctx.DBs.length);
            }
            return(i);
        }
Example #26
0
 internal static void UnlinkVfs(VSystem vfs)
 {
     Debug.Assert(MutexEx.Held(MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER)));
     if (vfs == null)
     {
     }
     else if (_vfsList == vfs)
     {
         _vfsList = vfs.Next;
     }
     else if (_vfsList != null)
     {
         var p = _vfsList;
         while (p.Next != null && p.Next != vfs)
         {
             p = p.Next;
         }
         if (p.Next == vfs)
         {
             p.Next = vfs.Next;
         }
     }
 }
Example #27
0
        public static void set_Auxdata(FuncContext fctx, int args, object aux, Action delete)
        {
            if (args < 0)
            {
                goto failed;
            }
            Debug.Assert(MutexEx.Held(fctx.S.Ctx.Mutex));
            VdbeFunc vdbeFunc = fctx.VdbeFunc;

            if (vdbeFunc == null || vdbeFunc.AuxsLength <= args)
            {
                int auxLength = (vdbeFunc != null ? vdbeFunc.AuxsLength : 0);
                int newSize   = args;
                vdbeFunc = new VdbeFunc();
                if (vdbeFunc == null)
                {
                    goto failed;
                }
                fctx.VdbeFunc            = vdbeFunc;
                vdbeFunc.Auxs[auxLength] = new VdbeFunc.AuxData();
                vdbeFunc.AuxsLength      = args + 1;
                vdbeFunc.Func            = fctx.Func;
            }
            VdbeFunc.AuxData auxData = vdbeFunc.Auxs[args];
            if (auxData.Aux != null && auxData.Aux is IDisposable)
            {
                (auxData.Aux as IDisposable).Dispose();
            }
            auxData.Aux = aux;
            return;

failed:
            if (aux != null && aux is IDisposable)
            {
                (aux as IDisposable).Dispose();
            }
        }
Example #28
0
        public static RC ChangeEncoding(Mem mem, TEXTENCODE newEncode)
        {
            Debug.Assert((mem.Flags & MEM.RowSet) == 0);
            Debug.Assert(newEncode == TEXTENCODE.UTF8 || newEncode == TEXTENCODE.UTF16LE || newEncode == TEXTENCODE.UTF16BE);
            if ((mem.Flags & MEM.Str) == 0 || mem.Encode == newEncode)
            {
                if (mem.Z == null && mem.Z_ != null)
                {
                    mem.Z = Encoding.UTF8.GetString(mem.Z_, 0, mem.Z_.Length);
                }
                return(RC.OK);
            }
            Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
#if OMIT_UTF16
            return(RC.ERROR);
#else
            // MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, then the encoding of the value may not have changed.
            RC rc = MemTranslate(mem, newEncode);
            Debug.Assert(rc == RC.OK || rc == RC.NOMEM);
            Debug.Assert(rc == RC.OK || mem.Encode != newEncode);
            Debug.Assert(rc == RC.NOMEM || mem.Encode == newEncode);
            return(rc);
#endif
        }
Example #29
0
        public static Mem Aggregate_Context(FuncContext fctx, int bytes)
        {
            Debug.Assert(fctx != null && fctx.Func != null && fctx.Func.Step != null);
            Debug.Assert(MutexEx.Held(fctx.S.Ctx.Mutex));
            Mem mem = fctx.Mem;

            C.ASSERTCOVERAGE(bytes < 0);
            if ((mem.Flags & MEM.Agg) == 0)
            {
                if (bytes <= 0)
                {
                    MemReleaseExternal(mem);
                    mem.Flags = 0;
                    mem.Z     = null;
                }
                else
                {
                    MemGrow(mem, bytes, 0);
                    mem.Flags = MEM.Agg;
                    mem.u.Def = fctx.Func;
                }
            }
            return(Mem.ToMem_(mem));
        }
Example #30
0
        public static RC Prepare_(Context ctx, string sql, int bytes, bool isPrepareV2, Vdbe reprepare, ref Vdbe stmtOut, ref string tailOut)
        {
            stmtOut = null;
            tailOut = null;
            string errMsg = null; // Error message
            RC     rc     = RC.OK;
            int    i;

            // Allocate the parsing context
            Parse parse = new Parse(); // Parsing context

            if (parse == null)
            {
                rc = RC.NOMEM;
                goto end_prepare;
            }
            parse.Reprepare      = reprepare;
            parse.LastToken.data = null; //: C#?
            Debug.Assert(tailOut == null);
            Debug.Assert(!ctx.MallocFailed);
            Debug.Assert(MutexEx.Held(ctx.Mutex));

            // Check to verify that it is possible to get a read lock on all database schemas.  The inability to get a read lock indicates that
            // some other database connection is holding a write-lock, which in turn means that the other connection has made uncommitted changes
            // to the schema.
            //
            // Were we to proceed and prepare the statement against the uncommitted schema changes and if those schema changes are subsequently rolled
            // back and different changes are made in their place, then when this prepared statement goes to run the schema cookie would fail to detect
            // the schema change.  Disaster would follow.
            //
            // This thread is currently holding mutexes on all Btrees (because of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
            // is not possible for another thread to start a new schema change while this routine is running.  Hence, we do not need to hold
            // locks on the schema, we just need to make sure nobody else is holding them.
            //
            // Note that setting READ_UNCOMMITTED overrides most lock detection, but it does *not* override schema lock detection, so this all still
            // works even if READ_UNCOMMITTED is set.
            for (i = 0; i < ctx.DBs.length; i++)
            {
                Btree bt = ctx.DBs[i].Bt;
                if (bt != null)
                {
                    Debug.Assert(bt.HoldsMutex());
                    rc = bt.SchemaLocked();
                    if (rc != 0)
                    {
                        string dbName = ctx.DBs[i].Name;
                        sqlite3Error(ctx, rc, "database schema is locked: %s", dbName);
                        C.ASSERTCOVERAGE((ctx.Flags & Context.FLAG.ReadUncommitted) != 0);
                        goto end_prepare;
                    }
                }
            }

            VTable.UnlockList(ctx);

            parse.Ctx        = ctx;
            parse.QueryLoops = (double)1;
            if (bytes >= 0 && (bytes == 0 || sql[bytes - 1] != 0))
            {
                int maxLen = ctx.aLimit[SQLITE_LIMIT_SQL_LENGTH];
                C.ASSERTCOVERAGE(bytes == maxLen);
                C.ASSERTCOVERAGE(bytes == maxLen + 1);
                if (bytes > maxLen)
                {
                    sqlite3Error(ctx, RC.TOOBIG, "statement too long");
                    rc = SysEx.ApiExit(ctx, RC.TOOBIG);
                    goto end_prepare;
                }
                string sqlCopy = sql.Substring(0, bytes);
                if (sqlCopy != null)
                {
                    parse.RunParser(sqlCopy, ref errMsg);
                    C._tagfree(ctx, ref sqlCopy);
                    parse.Tail = null; //: &sql[parse->Tail - sqlCopy];
                }
                else
                {
                    parse.Tail = null; //: &sql[bytes];
                }
            }
            else
            {
                parse.RunParser(sql, ref errMsg);
            }
            Debug.Assert((int)parse.QueryLoops == 1);

            if (ctx.MallocFailed)
            {
                parse.RC = RC.NOMEM;
            }
            if (parse.RC == RC.DONE)
            {
                parse.RC = RC.OK;
            }
            if (parse.CheckSchema != 0)
            {
                SchemaIsValid(parse);
            }
            if (ctx.MallocFailed)
            {
                parse.RC = RC.NOMEM;
            }
            tailOut = (parse.Tail == null ? null : parse.Tail.ToString());
            rc      = parse.RC;

            Vdbe v = parse.V;

#if !OMIT_EXPLAIN
            if (rc == RC.OK && parse.V != null && parse.Explain != 0)
            {
                int first, max;
                if (parse.Explain == 2)
                {
                    v.SetNumCols(4);
                    first = 8;
                    max   = 12;
                }
                else
                {
                    v.SetNumCols(8);
                    first = 0;
                    max   = 8;
                }
                for (i = first; i < max; i++)
                {
                    v.SetColName(i - first, COLNAME_NAME, _colName[i], C.DESTRUCTOR_STATIC);
                }
            }
#endif

            Debug.Assert(!ctx.Init.Busy || !isPrepareV2);
            if (!ctx.Init.Busy)
            {
                Vdbe.SetSql(v, sql, (int)(sql.Length - (parse.Tail == null ? 0 : parse.Tail.Length)), isPrepareV2);
            }
            if (v != null && (rc != RC.OK || ctx.MallocFailed))
            {
                v.Finalize();
                Debug.Assert(stmtOut == null);
            }
            else
            {
                stmtOut = v;
            }

            if (errMsg != null)
            {
                sqlite3Error(ctx, rc, "%s", errMsg);
                C._tagfree(ctx, ref errMsg);
            }
            else
            {
                sqlite3Error(ctx, rc, null);
            }

            // Delete any TriggerPrg structures allocated while parsing this statement.
            while (parse.TriggerPrg != null)
            {
                TriggerPrg t = parse.TriggerPrg;
                parse.TriggerPrg = t.Next;
                C._tagfree(ctx, ref t);
            }

end_prepare:
            //sqlite3StackFree( db, pParse );
            rc = SysEx.ApiExit(ctx, rc);
            Debug.Assert((RC)((int)rc & ctx.ErrMask) == rc);
            return(rc);
        }