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时,因为已经存在第一次调用返回的字段信息,故能够知道要求返回特定格式的数据。

相关文章
相关标签/搜索