示例#1
0
        public PrimaryRecord(byte[] bytes, Page page)
            : base(page)
        {
            short offset = 0;

            // Parse status bits A
            parseStatusBitsA(new BitArray(new [] { bytes[offset++] }));

            // TODO: Strategize this stuff to avoid ifs, switches & impersonation
            if(Type == RecordType.ForwardingStub)
            {
                // Forwarding stub only has one status byte. Remaining 8 bytes are for (PageID, FileID, Slot)
                FixedLengthData = bytes.Skip(1).Take(8).ToArray();

                int pageID = BitConverter.ToInt32(bytes, 1);
                short fileID = BitConverter.ToInt16(bytes, 5);
                short slot = BitConverter.ToInt16(bytes, 7);

                var forwardPage = page.Database.GetPrimaryRecordPage(new PagePointer(fileID, pageID), CompressionContext.NoCompression);
                byte[] forwardedRecordBytes = forwardPage.Records[slot].RawBytes;

                parseStatusBitsA(new BitArray(new[] {forwardedRecordBytes[0]}));
                bytes = forwardedRecordBytes;

                // We'll impersonate the ForwardingStub record type that we originated from, this allows
                // the engine to distinguish BlobFragments and the records that actually reference them.
                Type = RecordType.ForwardingStub;
            }

            // Parse status bits B
            parseStatusBitsB(bytes[offset++]);

            // Parse fixed length size
            short fixedLengthSize = BitConverter.ToInt16(bytes, offset);
            fixedLengthSize -= 4;
            offset += 2;

            // Parse fixed length data
            FixedLengthData = bytes.Skip(offset).Take(fixedLengthSize).ToArray();
            offset += fixedLengthSize;

            // Parse number of columns
            NumberOfColumns = BitConverter.ToInt16(bytes, offset);
            offset += 2;

            // Parse null bitmap, if present
            if (HasNullBitmap)
                offset = ParseNullBitmap(bytes, ref offset);

            // Parse variable length columns, if present
            if (HasVariableLengthColumns)
                ParseVariableLengthColumns(bytes, ref offset);

            // Save complete record raw bytes
            RawBytes = bytes.Take(offset).ToArray();
        }
示例#2
0
        internal CompressedRecord(byte[] record, Page page)
        {
            this.record = record;
            this.page = page;

            short recordPointer = 1;

            parseHeader();
            parseCDRegion(ref recordPointer);
            parseShortDataRegion(ref recordPointer);
            parseLongDataRegion(ref recordPointer);
        }
示例#3
0
        public BlobInlineRootProxy(Page page, byte[] data)
            : base(page)
        {
            this.data = data;

            // Parsed according to table 7-1 (p. 378) in [SQL Server 2008 Internals]
            complexColumnType = data[0];
            indexLevel = BitConverter.ToInt16(data, 1);
            unused = data[3];
            sequence = BitConverter.ToInt32(data, 4);

            // Technically a 6-byte long value. Low two bytes always zero, thus not stored (http://bit.ly/mdAQpm)
            timestamp = BitConverter.ToUInt32(data, 8) << 16;
        }
示例#4
0
        public TextPointerProxy(Page page, byte[] bytes)
            : base(page)
        {
            this.bytes = bytes;

            /* 16 byte LOB Textpointer:
             *
             * Bytes	Content
             * 0-3		Timestamp (int)
             * 4-7		?
             * 8-16		Slot pointer
            */

            timestamp = BitConverter.ToInt32(bytes, 0);
            lobRootSlot = new SlotPointer(bytes.Skip(8).ToArray());
        }
示例#5
0
        public IndexRecord(byte[] bytes, Page page)
            : base(page)
        {
            parseStatusBitsA(new BitArray(new[] { bytes[0] }));

            // Index records don't contain fixed length header - it's stored in the page header
            FixedLengthData = bytes.Skip(1).Take(Page.Header.Pminlen - 1).ToArray();
            short offset = Page.Header.Pminlen;

            NumberOfColumns = BitConverter.ToInt16(bytes, offset);
            offset += 2;

            if (HasNullBitmap)
                offset = ParseNullBitmap(bytes, ref offset);

            if (HasVariableLengthColumns)
                ParseVariableLengthColumns(bytes, ref offset);
        }
示例#6
0
        public TextRecord(byte[] bytes, Page page)
            : base(page)
        {
            short offset = 0;

            // Parse status bits, even though we currently ignore their values.
            // Only one I can currently imagine being relevant is HasVersioningInformation.
            parseStatusBitsA(new BitArray(new [] { bytes[offset++] }));
            parseStatusBitsB(bytes[offset++]);

            // Read the fixed length portion
            short fixedLengthSize = BitConverter.ToInt16(bytes, offset);
            fixedLengthSize -= 4;
            offset += 2;

            FixedLengthData = bytes.Skip(offset).Take(fixedLengthSize).ToArray();
            offset += fixedLengthSize;

            // No matter the text structure, they all have a common 14 byte header
            parseCommonTextStructureHeader();

            // Save complete record raw bytes
            RawBytes = bytes.Take(offset).ToArray();
        }
示例#7
0
 protected DataProxy(Page page)
 {
     OriginPage = page;
 }