OpenJPA
  1. OpenJPA
  2. OPENJPA-922

setByteArrayInputStream being used in stead of setBytes

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.0, 2.0.0-M2
    • Fix Version/s: 2.0.0-M3
    • Component/s: None
    • Labels:
      None
    • Environment:
      DB2 on Windows
    • Patch Info:
      Patch Available

      Description

      I have an Entity and one of its fields is defined as CHAR(16) FOR BIT DATA NOT NULL.

      When trying to persist the entity, I get the following error:

      Error: SQLCODE=-301, SQLSTATE=07006, SQLERRMC=1, DRIVER=3.50.152

      {prepstmnt 1386959531 INSERT INTO NULLID.TESTTBL (tkiid) VALUES (?) [params=(InputStream) java.io.ByteArrayInputStream@75947594]}

      It seems that the wrong kind of set is being used to set the parameter on the prepared statement.

        Activity

        Hide
        B.J. Reed added a comment -

        For DB2, the DBDictionary useSetBytesForBlobs field is set to false. Within setBytes, if this flag is true, setBinaryStream() is called regardless of what kind of column we really have (BYTES or BLOB_OBJECT). Patch includes change to the if statement to also check the column type before using the setBinaryStream and a simple test case.

        Please apply to both 1.2.x and trunk

        Show
        B.J. Reed added a comment - For DB2, the DBDictionary useSetBytesForBlobs field is set to false. Within setBytes, if this flag is true, setBinaryStream() is called regardless of what kind of column we really have (BYTES or BLOB_OBJECT). Patch includes change to the if statement to also check the column type before using the setBinaryStream and a simple test case. Please apply to both 1.2.x and trunk
        Hide
        B.J. Reed added a comment -

        Was premature with the patch. The "fix" breaks BLOBs so it's no good. Basically, both unserialized BLOBS and byte arrays go through the ByteArrayValueHandler in stead of the BlobValueHandler (determined in MappingHandler.defaultHandler()) so the jdbc layer doesn't know there is a difference between the 2 and can't make the correct call to set the data....the use of ByteArrayValueHandler for both also happened on Derby so we need a way to differentiate between the two different kinds of byte[] (BLOBs and char for bit data) so that we know which method to use to set the data in the DB.

        Show
        B.J. Reed added a comment - Was premature with the patch. The "fix" breaks BLOBs so it's no good. Basically, both unserialized BLOBS and byte arrays go through the ByteArrayValueHandler in stead of the BlobValueHandler (determined in MappingHandler.defaultHandler()) so the jdbc layer doesn't know there is a difference between the 2 and can't make the correct call to set the data....the use of ByteArrayValueHandler for both also happened on Derby so we need a way to differentiate between the two different kinds of byte[] (BLOBs and char for bit data) so that we know which method to use to set the data in the DB.
        Hide
        B.J. Reed added a comment -

        I have attached OPENJPA-922-B.patch as a second attempt to fix this problem (also includes the test case). Basically, the DB2Dictionary needs to override the DBDictionary setBytes and getBytes methods. For setBytes, it can check the Column definition to use the proper set, for getBytes, the Column is nowhere to be found so it just tries the original getBlob, but if that fails, then it tries to getBytes as a last resort. I'm sure there's a better way for the get, but I haven't stumbled across it yet.

        Show
        B.J. Reed added a comment - I have attached OPENJPA-922 -B.patch as a second attempt to fix this problem (also includes the test case). Basically, the DB2Dictionary needs to override the DBDictionary setBytes and getBytes methods. For setBytes, it can check the Column definition to use the proper set, for getBytes, the Column is nowhere to be found so it just tries the original getBlob, but if that fails, then it tries to getBytes as a last resort. I'm sure there's a better way for the get, but I haven't stumbled across it yet.
        Hide
        Milosz Tylenda added a comment -

        Since the test case is likely to fail on databases other then DB2 (specific columnDefinition), it is a good idea to run it only when DB2 is connected. A few ideas:
        1. Use the annotation described in OPENJPA-942.
        2. Test whether DBDictionary is an instance of DB2Dictionary. Some other tests already use that approach.

        Show
        Milosz Tylenda added a comment - Since the test case is likely to fail on databases other then DB2 (specific columnDefinition), it is a good idea to run it only when DB2 is connected. A few ideas: 1. Use the annotation described in OPENJPA-942 . 2. Test whether DBDictionary is an instance of DB2Dictionary. Some other tests already use that approach.
        Hide
        B.J. Reed added a comment -

        Thanks Milosz. I was so worried about the fix not breaking other DBs that I forgot about the test breaking other DBs. Have attached the OPENJPA-922-C.patch to fix this. When the annotation in OPENJPA-942 is working, it would probably be better to use that.

        Show
        B.J. Reed added a comment - Thanks Milosz. I was so worried about the fix not breaking other DBs that I forgot about the test breaking other DBs. Have attached the OPENJPA-922 -C.patch to fix this. When the annotation in OPENJPA-942 is working, it would probably be better to use that.

          People

          • Assignee:
            Michael Dick
            Reporter:
            B.J. Reed
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development