Пример #1
0
        static void walEncodeFrame(Wal wal, Pid id, uint truncate, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;

            Debug.Assert(WAL_FRAME_HDRSIZE == 24);
            ConvertEx.Put4(frame, 0, id);
            ConvertEx.Put4(frame, 4, truncate);
            Buffer.BlockCopy(frame, 8, wal.Header.Salt, 0, 8);

            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums

            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);

            ConvertEx.Put4(frame, 16, checksum[0]);
            ConvertEx.Put4(frame, 20, checksum[1]);
        }
Пример #2
0
        public static byte GetSafetyLevel(string z, int omitFull, byte dflt)
        {
            if (char.IsDigit(z[0]))
            {
                return((byte)ConvertEx.Atoi(z));
            }
            int n = z.Length;

            for (int i = 0; i < _safetyLevelLength.Length - omitFull; i++)
            {
                if (_safetyLevelLength[i] == n && string.CompareOrdinal(_safetyLevelText.Substring(_safetyLevelOffset[i]), 0, z, 0, n) == 0)
                {
                    return(_safetyLevelValue[i]);
                }
            }
            return(dflt);
        }
Пример #3
0
        static void walChecksumBytes(bool nativeChecksum, byte[] b, int length, byte[] checksum, byte[] checksumOut)
        {
            uint s1, s2;

            if (checksum != null)
            {
                s1 = ConvertEx.Get4(checksum, 0);
                s2 = ConvertEx.Get4(checksum, 4);
            }
            else
            {
                s1 = s2 = 0;
            }

            Debug.Assert(length >= 8);
            Debug.Assert((length & 0x00000007) == 0);

            uint data = 0;
            uint end  = (uint)length * 4;

            if (nativeChecksum)
            {
                do
                {
                    s1 += ConvertEx.Get4(b, data) + s2; data += 4;
                    s2 += ConvertEx.Get4(b, data) + s1; data += 4;
                } while (data < end);
            }
            else
            {
                do
                {
                    s1 += BYTESWAP32(ConvertEx.Get4(b, data)) + s2; data += 4;
                    s2 += BYTESWAP32(ConvertEx.Get4(b, data)) + s1; data += 4;
                } while (data < end);
            }

            ConvertEx.Put4(checksumOut, 0, s1);
            ConvertEx.Put4(checksumOut, 4, s2);
        }
Пример #4
0
        static bool walDecodeFrame(Wal wal, Pid idOut, uint truncateOut, byte[] data, byte[] frame)
        {
            var checksum = wal.Header.FrameChecksum;

            Debug.Assert(WAL_FRAME_HDRSIZE == 24);

            // A frame is only valid if the salt values in the frame-header match the salt values in the wal-header.
            var testFrame = new byte[8];

            Buffer.BlockCopy(frame, 8, testFrame, 0, 8);
            if (Enumerable.SequenceEqual(wal.Header.Salt, testFrame))
            {
                return(false);
            }

            // A frame is only valid if the page number is creater than zero.
            Pid id = ConvertEx.Get4(frame, 0); // Page number of the frame

            if (id == 0)
            {
                return(false);
            }

            // A frame is only valid if a checksum of the WAL header, all prior frams, the first 16 bytes of this frame-header,
            // and the frame-data matches the checksum in the last 8 bytes of this frame-header.
            bool nativeChecksum = true; // (wal.Header.BigEndianChecksum == TYPE_BIGENDIAN); // True for native byte-order checksums

            walChecksumBytes(nativeChecksum, frame, 8, checksum, checksum);
            walChecksumBytes(nativeChecksum, data, (int)wal.SizePage, checksum, checksum);
            if (checksum[0] != ConvertEx.Get4(frame, 16) || checksum[1] != ConvertEx.Get4(frame, 20)) // Checksum failed.
            {
                return(false);
            }

            // If we reach this point, the frame is valid.  Return the page number and the new database size.
            idOut       = id;
            truncateOut = ConvertEx.Get4(frame, 4);
            return(true);
        }
Пример #5
0
        public static bool InitCallback(object init, int argc, string[] argv, object notUsed1)
        {
            InitData data = (InitData)init;
            Context  ctx  = data.Ctx;
            int      db   = data.Db;

            Debug.Assert(argc == 3);
            Debug.Assert(MutexEx.Held(ctx.Mutex));
            E.DbClearProperty(ctx, db, SCHEMA.Empty);
            if (ctx.MallocFailed)
            {
                CorruptSchema(data, argv[0], null);
                return(true);
            }

            Debug.Assert(db >= 0 && db < ctx.DBs.length);
            if (argv == null)
            {
                return(false);              // Might happen if EMPTY_RESULT_CALLBACKS are on */
            }
            if (argv[1] == null)
            {
                CorruptSchema(data, argv[0], null);
            }
            else if (!string.IsNullOrEmpty(argv[2]))
            {
                // Call the parser to process a CREATE TABLE, INDEX or VIEW. But because ctx->init.busy is set to 1, no VDBE code is generated
                // or executed.  All the parser does is build the internal data structures that describe the table, index, or view.
                Debug.Assert(ctx.Init.Busy);
                ctx.Init.DB            = (byte)db;
                ctx.Init.NewTid        = ConvertEx.Atoi(argv[1]);
                ctx.Init.OrphanTrigger = false;
                Vdbe stmt = null;
#if DEBUG
                int rcp = Prepare(ctx, argv[2], -1, ref stmt, null);
#else
                Prepare(ctx, argv[2], -1, ref stmt, null);
#endif
                RC rc = ctx.ErrCode;
#if DEBUG
                Debug.Assert(((int)rc & 0xFF) == (rcp & 0xFF));
#endif
                ctx.Init.DB = 0;
                if (rc != RC.OK)
                {
                    if (ctx.Init.OrphanTrigger)
                    {
                        Debug.Assert(db == 1);
                    }
                    else
                    {
                        data.RC = rc;
                        if (rc == RC.NOMEM)
                        {
                            ctx.MallocFailed = true;
                        }
                        else if (rc != RC.INTERRUPT && (RC)((int)rc & 0xFF) != RC.LOCKED)
                        {
                            CorruptSchema(data, argv[0], sqlite3_errmsg(ctx));
                        }
                    }
                }
                stmt.Finalize();
            }
            else if (argv[0] == null)
            {
                CorruptSchema(data, null, null);
            }
            else
            {
                // If the SQL column is blank it means this is an index that was created to be the PRIMARY KEY or to fulfill a UNIQUE
                // constraint for a CREATE TABLE.  The index should have already been created when we processed the CREATE TABLE.  All we have
                // to do here is record the root page number for that index.
                Index index = Parse.FindIndex(ctx, argv[0], ctx.DBs[db].Name);
                if (index == null)
                {
                    // This can occur if there exists an index on a TEMP table which has the same name as another index on a permanent index.  Since
                    // the permanent table is hidden by the TEMP table, we can also safely ignore the index on the permanent table.
                    // Do Nothing
                }
                else if (!ConvertEx.Atoi(argv[1], ref index.Id))
                {
                    CorruptSchema(data, argv[0], "invalid rootpage");
                }
            }
            return(false);
        }
Пример #6
0
        public static bool UriBoolean(string filename, string param, bool dflt)
        {
            string z = UriParameter(filename, param);

            return(z != null ? ConvertEx.GetBoolean(z, (byte)(dflt ? 1 : 0)) : dflt);
        }
Пример #7
0
        public string ExpandSql(string rawSql)
        {
            Context     ctx = Ctx;               // The database connection
            TextBuilder b   = new TextBuilder(); // Accumulate the _output here

            TextBuilder.Init(b, 100, ctx.Limits[(int)LIMIT.LENGTH]);
            b.Tag = ctx;
            int rawSqlIdx = 0;
            int nextIndex = 1; // Index of next ? host parameter
            int idx       = 0; // Index of a host parameter

            if (ctx.VdbeExecCnt > 1)
            {
                while (rawSqlIdx < rawSql.Length)
                {
                    while (rawSql[rawSqlIdx++] != '\n' && rawSqlIdx < rawSql.Length)
                    {
                        ;
                    }
                    b.Append("-- ", 3);
                    b.Append(rawSql, (int)rawSqlIdx);
                }
            }
            else
            {
                while (rawSqlIdx < rawSql.Length)
                {
                    int tokenLength = 0;                                                         // Length of the parameter token
                    int n           = FindNextHostParameter(rawSql, rawSqlIdx, ref tokenLength); // Length of a token prefix
                    Debug.Assert(n > 0);
                    b.Append(rawSql.Substring(rawSqlIdx, n), n);
                    rawSqlIdx += n;
                    Debug.Assert(rawSqlIdx < rawSql.Length || tokenLength == 0);
                    if (tokenLength == 0)
                    {
                        break;
                    }
                    if (rawSql[rawSqlIdx] == '?')
                    {
                        if (tokenLength > 1)
                        {
                            Debug.Assert(char.IsDigit(rawSql[rawSqlIdx + 1]));
                            ConvertEx.Atoi(rawSql, rawSqlIdx + 1, ref idx);
                        }
                        else
                        {
                            idx = nextIndex;
                        }
                    }
                    else
                    {
                        Debug.Assert(rawSql[rawSqlIdx] == ':' || rawSql[rawSqlIdx] == '$' || rawSql[rawSqlIdx] == '@');
                        C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == ':');
                        C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '$');
                        C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '@');
                        idx = ParameterIndex(this, rawSql.Substring(rawSqlIdx, tokenLength), tokenLength);
                        Debug.Assert(idx > 0);
                    }
                    rawSqlIdx += tokenLength;
                    nextIndex  = idx + 1;
                    Debug.Assert(idx > 0 && idx <= Vars.length);
                    Mem var = Vars[idx - 1]; // Value of a host parameter
                    if ((var.Flags & MEM.Null) != 0)
                    {
                        b.Append("NULL", 4);
                    }
                    else if ((var.Flags & MEM.Int) != 0)
                    {
                        b.AppendFormat("%lld", var.u.I);
                    }
                    else if ((var.Flags & MEM.Real) != 0)
                    {
                        b.AppendFormat("%!.15g", var.R);
                    }
                    else if ((var.Flags & MEM.Str) != 0)
                    {
#if !OMIT_UTF16
                        TEXTENCODE encode = E.CTXENCODE(ctx);
                        if (encode != TEXTENCODE.UTF8)
                        {
                            Mem utf8;
                            //C._memset(&utf8, 0, sizeof(utf8));
                            utf8.Ctx = ctx;
                            MemSetStr(utf8, var.Z, var.N, encode, C.DESTRUCTOR_STATIC);
                            ChangeEncoding(utf8, TEXTENCODE.UTF8);
                            b.AppendFormat("'%.*q'", utf8.N, utf8.Z);
                            MemRelease(utf8);
                        }
                        else
#endif
                        b.AppendFormat("'%.*q'", var.N, var.Z);
                    }
                    else if ((var.Flags & MEM.Zero) != 0)
                    {
                        b.AppendFormat("zeroblob(%d)", var.u.Zeros);
                    }
                    else
                    {
                        Debug.Assert((var.Flags & MEM.Blob) != 0);
                        b.Append("x'", 2);
                        for (int i = 0; i < var.N; i++)
                        {
                            b.AppendFormat("%02x", var.u.Zeros[i] & 0xff);
                        }
                        b.Append("'", 1);
                    }
                }
            }
            return(b.ToString());
        }