postgresql jdbc prepared 的通訊過程的分析

    經過postgresql的官方文檔,能夠了解到與prepared整個過程相關的包大概包含parse, bind, describe , execute ,sync,這5個包是從客戶端向服務端發送的。當服務端處理完畢這些包後會返回對應的parseComplete, bindComplete,rowDescription, rowdata, nodata 等等數據包做爲迴應。java

    本文想講解的重點是bind包中關於結果字段格式的問題。從官方文檔能夠知道字段格式有兩種:文本(0)和二進制(1)。那麼哪些字段是文本格式,哪些字段是二進制格式呢。prepared中何時使用文本格式,何時使用二進制格式呢?sql

一,使用二進制格式的數據類型post

    從postgresql jdbc 9.4源碼的AbstractJdbc2Connection.java文件的163行左右(代碼段以下)來看。debug

if (binaryTransfer && protoConnection.getProtocolVersion() >= 3) {
            binaryOids.add(Oid.BYTEA);
            binaryOids.add(Oid.INT2);
            binaryOids.add(Oid.INT4);
            binaryOids.add(Oid.INT8);
            binaryOids.add(Oid.FLOAT4);
            binaryOids.add(Oid.FLOAT8);
            binaryOids.add(Oid.TIME);
            binaryOids.add(Oid.DATE);
            binaryOids.add(Oid.TIMETZ);
            binaryOids.add(Oid.TIMESTAMP);
            binaryOids.add(Oid.TIMESTAMPTZ);
            binaryOids.add(Oid.INT2_ARRAY);
            binaryOids.add(Oid.INT4_ARRAY);
            binaryOids.add(Oid.INT8_ARRAY);
            binaryOids.add(Oid.FLOAT4_ARRAY);
            binaryOids.add(Oid.FLOAT8_ARRAY);
            binaryOids.add(Oid.FLOAT8_ARRAY);
            binaryOids.add(Oid.VARCHAR_ARRAY);
            binaryOids.add(Oid.TEXT_ARRAY);
            binaryOids.add(Oid.POINT);
            binaryOids.add(Oid.BOX);
            binaryOids.add(Oid.UUID);
        }        
        // the pre 8.0 servers do not disclose their internal encoding for
        // time fields so do not try to use them.
        if (!haveMinimumCompatibleVersion(ServerVersion.v8_0)) {
            binaryOids.remove(Oid.TIME);
            binaryOids.remove(Oid.TIMETZ);
            binaryOids.remove(Oid.TIMESTAMP);
            binaryOids.remove(Oid.TIMESTAMPTZ);
        }
        // driver supports only null-compatible arrays
        if (!haveMinimumCompatibleVersion(ServerVersion.v8_3)) {
            binaryOids.remove(Oid.INT2_ARRAY);
            binaryOids.remove(Oid.INT4_ARRAY);
            binaryOids.remove(Oid.INT8_ARRAY);
            binaryOids.remove(Oid.FLOAT4_ARRAY);
            binaryOids.remove(Oid.FLOAT8_ARRAY);
            binaryOids.remove(Oid.FLOAT8_ARRAY);
            binaryOids.remove(Oid.VARCHAR_ARRAY);
            binaryOids.remove(Oid.TEXT_ARRAY);
        }

        binaryOids.addAll(getOidSet(PGProperty.BINARY_TRANSFER_ENABLE.get(info)));
        binaryOids.removeAll(getOidSet(PGProperty.BINARY_TRANSFER_DISABLE.get(info)));

只有協議版本在3及以上纔會出現二進制的類型。而且在postgresql 小於8.0, 小於8.3 以及大於等於8.3的版本之間有必定的差別。postgresql

 有時候爲了避免讓某些類型經過二進制通訊,則能夠經過PGProperty來DISABLE這些類型便可。相反則ENABLE這些類型。code

須要注意的是全部 版本中都不支持Oid.DATE進行二進制通訊。(無論用戶ENABLE與否)server

排除以上 出現的類型外,其餘的類型都使用文本進行通訊。ip

二,prepared中使用二進制的時機v8

   只有當針對同一個語句進行屢次bind時,纔會進行二進制的格式進行通訊。第一次通訊都是以文本的形式獲得結果數據的。只有第二次及之後的調用對應的類型的字段的值才以二進制的格式進行通訊。能夠經過postgresql jdbc打開debug來觀察。rem

    從理論上面來說,第一次發送parse和bind包時,根本就不知道表中字段的類型。故bind沒法要求服務端以特定的格式返回數據。第二次發送bind時,因爲已經存在第一次調用返回的字段信息,故能夠知道要求返回特定格式的數據。

相關文章
相關標籤/搜索