亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

解剖SQLSERVER 第五篇 OrcaMDF里讀取Bits類型數

系統 2416 0
原文: 解剖SQLSERVER 第五篇 OrcaMDF里讀取Bits類型數據(譯)

解剖SQLSERVER 第五篇 ?OrcaMDF里讀取Bits類型數據(譯)

http://improve.dk/reading-bits-in-orcamdf/

Bits類型的存儲跟SQLSERVER其他定長數據類型的存儲很不一樣。通常,所有定長列都會顯示出來,一個條記錄里定長數據部分的字段數據總是一個挨著一個

我們可以寫入磁盤的最小數據單位是一個字節,存儲位類型數據的天真的方法就是使用一整個(字節@)來存儲每一個位,使用常用的格式去解釋位類型數據是很簡單的

,不過這會浪費一些空間 ,就像null位圖,如果一個表只有3列,那么用一個字節來存儲null位圖會比較浪費,因為其他的5個位都沒有用到

@:文章里是用位 ,這里應該是用字節吧

?

在記錄的內部位類型是如何存儲的?

一些位類型列的值是存儲在一個字節中的,最大可以到8個位,通常,我們會有如下表定義

      
        CREATE
      
      
        TABLE
      
      
         BitTest

(

    A 
      
      
        bit
      
      
        

    B 
      
      
        bit
      
      
        

    C 
      
      
        bit
      
      
        

    D 
      
      
        int
      
      
        

)
      
    

記錄的定長部分數據需要占用5個字節,4個字節存儲int 列 ,而另一個字節存儲A 、B、C這三列位類型的數據,只用了字節里面的3個位

解剖SQLSERVER 第五篇 OrcaMDF里讀取Bits類型數據

我們再添加一些列

      
        CREATE
      
      
        TABLE
      
      
         BitTest

(

    A 
      
      
        bit
      
      
        

    B 
      
      
        bit
      
      
        

    C 
      
      
        bit
      
      
        

    D 
      
      
        int
      
      
        

    E 
      
      
        bit
      
      
        

    F 
      
      
        bit
      
      
        

    G 
      
      
        bit
      
      
        

    H 
      
      
        smallint
      
      
        

    I 
      
      
        bit
      
      
        

    J 
      
      
        bit
      
      
        

    K 
      
      
        bit
      
      
        

)
      
    

E到G列按道理來說應該存儲在D列的后面,但是他們會繼續使用第一個 bit byte,直到第一個 bit byte使用完所有的位空間為止

下面的圖顯示了H列(smallint?)直接存儲在D列的后面,而在D列后面是存儲K列的新bit byte,因為第一個bit byte已經滿了

解剖SQLSERVER 第五篇 OrcaMDF里讀取Bits類型數據

?

當讀取行記錄里的位類型時我們需要知道的狀態

很明顯,我們一次不能只讀取一個字段的值,我們讀取固定長度數據類型的時候還需要讀取定長數據偏移指針

我們需要一些能在讀取的時候指示我們當前讀取到字節中哪一個位屬于哪一個字段的狀態,然后我們讀取一個新的bit byte

我來介紹一下RecordReadState類

      
        public
      
      
        class
      
      
         RecordReadState

{

    
      
      
        //
      
      
         We start out having consumed all bits as none have been read
      
      
        private
      
      
        int
      
       currentBitIndex = 
      
        8
      
      
        ;

    
      
      
        private
      
      
        byte
      
      
         bits;



    
      
      
        public
      
      
        void
      
       LoadBitByte(
      
        byte
      
      
         bits)

    {

        
      
      
        this
      
      .bits =
      
         bits;

        currentBitIndex 
      
      = 
      
        0
      
      
        ;

    }



    
      
      
        public
      
      
        bool
      
      
         AllBitsConsumed

    {

        
      
      
        get
      
       { 
      
        return
      
       currentBitIndex == 
      
        8
      
      
        ; }

    }



    
      
      
        public
      
      
        bool
      
      
         GetNextBit()

    {

        
      
      
        return
      
       (bits & (
      
        1
      
       << currentBitIndex++)) != 
      
        0
      
      
        ;

    }

}
      
    

RecordReadState 類當前只需要處理bits,但是將來我可能還要創建一個BitReadState 類用來保存讀取狀態

RecordReadState 類保存了一個字節用來當作指針指出下一個可用的位在字節的哪個地方,如果字節已經用完了存儲滿了所有的位數據

(currentBixIndex = 8 (0-7 being the available bits)),方法AllBitsConsumed 就會返回true,指示我們需要讀取一個新的?bit byte

GetNextBit方法只是簡單的從?bit byte中讀取當前的bit ,然后將currentBitIndex(bit index)的值加1

demo

      
        using
      
      
         NUnit.Framework;


      
      
        using
      
      
         OrcaMDF.Core.Engine.Records;


      
      
        namespace
      
      
         OrcaMDF.Core.Tests.Engine.Records

{

    [TestFixture]


      
      
        public
      
      
        class
      
      
         RecordReadStateTests

{

        [Test]


      
      
        public
      
      
        void
      
      
         General()

{


      
      
        var
      
       state = 
      
        new
      
      
         RecordReadState();


      
      
        //
      
      
         No bits available
      
      
        Assert.IsTrue(state.AllBitsConsumed);

state.LoadBitByte(
      
      
        0xD2
      
      ); 
      
        //
      
      
         11010010


      
      
        //
      
      
         Bits available
      
      
        Assert.IsFalse(state.AllBitsConsumed);


      
      
        //
      
      
         Reading bit values
      
      
        Assert.IsFalse(state.GetNextBit());

Assert.IsTrue(state.GetNextBit());

Assert.IsFalse(state.GetNextBit());

Assert.IsFalse(state.GetNextBit());

Assert.IsTrue(state.GetNextBit());

Assert.IsFalse(state.GetNextBit());

Assert.IsTrue(state.GetNextBit());


      
      
        //
      
      
         One bit left
      
      
        Assert.IsFalse(state.AllBitsConsumed);

Assert.IsTrue(state.GetNextBit());


      
      
        //
      
      
         Bits exhausted, ready for next byte
      
      
        Assert.IsTrue(state.AllBitsConsumed);

}

}

}
      
    

?

SqlBit實現

一旦我們實現了狀態的讀取,我們就可以實現SqlBit 類型

      
        public
      
      
        class
      
      
         SqlBit : ISqlType

{

    
      
      
        private
      
      
        readonly
      
      
         RecordReadState readState;



    
      
      
        public
      
      
         SqlBit(RecordReadState readState)

    {

        
      
      
        this
      
      .readState =
      
         readState;

    }



    
      
      
        public
      
      
        bool
      
      
         IsVariableLength

    {

        
      
      
        get
      
       { 
      
        return
      
      
        false
      
      
        ; }

    }



    
      
      
        public
      
      
        short
      
      ?
      
         FixedLength

    {

        
      
      
        get
      
      
        

        {

            
      
      
        if
      
      
         (readState.AllBitsConsumed)

                
      
      
        return
      
      
        1
      
      
        ;



            
      
      
        return
      
      
        0
      
      
        ;

        }

    }



    
      
      
        public
      
      
        object
      
       GetValue(
      
        byte
      
      
        [] value)

    {

        
      
      
        if
      
      (readState.AllBitsConsumed && value.Length != 
      
        1
      
      
        )

            
      
      
        throw
      
      
        new
      
       ArgumentException(
      
        "
      
      
        All bits consumed, invalid value length: 
      
      
        "
      
       +
      
         value.Length);



        
      
      
        if
      
       (value.Length == 
      
        1
      
      
        )

            readState.LoadBitByte(value[
      
      
        0
      
      
        ]);



        
      
      
        return
      
      
         readState.GetNextBit();

    }

}
      
    

SqlBit 在構造函數里傳入一個read state,read state指示當前記錄讀取操作的范圍。需要注意的是固定長度需要依據read state里的當前AllBitsConsumed值

如果字節里面所有位都被占用,那么意味著需要讀取整個字節,如果if (readState.AllBitsConsumed)返回0表示不需要讀取整個字節,但是GetValue方法依然會被調用

GetValue方法會驗證一種情況:readState.AllBitsConsumed 返回真,證明 bit byte是有數據存儲在里面,但是value.Length返回的長度是0,那證明有問題了

如果我們讀到一個值,我們會請求?read state 去裝載一個新的bit byte ,之后,我們可以調用GetNextBit 方法返回?read state的當前bit

相關測試

      
        using
      
      
         NUnit.Framework;


      
      
        using
      
      
         OrcaMDF.Core.Engine.Records;


      
      
        using
      
      
         OrcaMDF.Core.Engine.SqlTypes;




      
      
        namespace
      
      
         OrcaMDF.Core.Tests.Engine.SqlTypes

{

    [TestFixture]

    
      
      
        public
      
      
        class
      
      
         SqlBitTests

    {

        [Test]

        
      
      
        public
      
      
        void
      
      
         GetValue()

        {

            
      
      
        var
      
       readState = 
      
        new
      
      
         RecordReadState();

            
      
      
        var
      
       type = 
      
        new
      
      
         SqlBit(readState);



            
      
      
        //
      
      
         No bytes read - length is one
      
      

            Assert.AreEqual(
      
        1
      
      
        , type.FixedLength);



            
      
      
        //
      
      
         Load byte and check length is 0
      
      

            readState.LoadBitByte(
      
        0xD2
      
      
        );

            Assert.AreEqual(
      
      
        0
      
      
        , type.FixedLength);



            Assert.IsFalse((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsTrue((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsFalse((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsFalse((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsTrue((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsFalse((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));

            Assert.IsTrue((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));



            
      
      
        //
      
      
         One bit left - length should still be 0
      
      

            Assert.AreEqual(
      
        0
      
      
        , type.FixedLength);



            Assert.IsTrue((
      
      
        bool
      
      )type.GetValue(
      
        new
      
      
        byte
      
      [
      
        0
      
      
        ]));



            
      
      
        //
      
      
         All bits consumed - length should be 1
      
      

            Assert.AreEqual(
      
        1
      
      
        , type.FixedLength);

        }

    }

}
      
    

?

第五篇完

解剖SQLSERVER 第五篇 OrcaMDF里讀取Bits類型數據


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美亚洲国产成人精品 | 爱爱的免费视频 | 国产精品中文字幕在线观看 | 88国产精品欧美一区二区三区 | 日本不卡一二三区 | 三级西施 | 一级特黄a视频 | 亚洲日本人成中文字幕 | 日日天天干 | 成人影院午夜久久影院 | 亚洲一区二区久久 | 亚洲女精品一区二区三区 | 日韩中文字幕视频在线观看 | 色综合中文字幕天天在线 | 久草视频新| 一区二区三区精品国产欧美 | 欧美日穴 | 国产在线观看一区二区三区 | 中文线码中文高清播放中 | 在线一区播放 | 久久久成人啪啪免费网站 | 亚洲午夜片子大全精品 | 高清在线一区 | 狠狠插狠狠干 | 欧美交换乱理伦片在线观看 | 春暖花开亚洲 | 一级女人18片毛片免费视频 | 宅男看片午夜大片啪啪mv | 四虎永久免费在线观看 | 在线观看日韩视频 | 99久久精品费精品国产一区二区 | 伊人焦久影院 | 色四月| 国产99精品免费视频看6 | 性欧美www | 国产免费午夜a无码v视频 | 国产一区二区福利久久 | 久久福利在线 | 久久免费99精品久久久久久 | 国内精品久久久久影院6 | 99最新网址 |