Does Cayenne handle binary primary keys (Sybase) in relationships?

From: Michael Gentry (michael_gentr..anniemae.com)
Date: Tue Oct 21 2003 - 12:44:04 EDT

  • Next message: Andrus Adamchik: "Re: Does Cayenne handle binary primary keys (Sybase) in relationships?"

    Hi, I'm trying to use Cayenne against a legacy Sybase model (current
    system uses EOF, but has "additions" to it) that uses binary primary
    keys (a 12-byte binary data type inside Sybase).

    I put together a little test program and I could fetch a record with a
    basic SelectQuery just fine, but when I tried to do a relationship, I
    get exceptions. Here is what I've discovered so far ...

    My first query gives me:

    DEBUG QueryLogger: SELECT t0.identifier, t0.isAssumable, t0.isBalloon,
    t0.numberPID FROM Pool t0, APNPoolNumber t1 WHERE t0.numberPID =
    t1.identifier AND (t1.apnPoolNumber = ?) [bind: '461105'] - prepared in
    30 ms.
    DEBUG QueryLogger: === returned 1 row. - took 150 ms.

    Pool = {[ isAssumable => false
            isBalloon => true
            identifier => [..9ce8c
            number => {<oid: test.APNPoolNumber: <identifier: [..eea66>; state:
    hollow>}

    ]<oid: test.Pool: <identifier: [..9ce8c>; state: committed>}

    Which seems fine so far. Then I try to follow the "number" relationship
    to our "APNPoolNumber" entity and that's where it blows apart with:

    java.lang.StringIndexOutOfBoundsException: String index out of range:
    268435450
            at java.lang.String.charAt(String.java:460)
            at
    org.objectstyle.cayenne.access.QueryLogger.appendFormattedByte(QueryLogger.java:187)
            at
    org.objectstyle.cayenne.access.QueryLogger.sqlLiteralForObject(QueryLogger.java:157)
            at
    org.objectstyle.cayenne.access.QueryLogger.logQuery(QueryLogger.java:297)
            at
    org.objectstyle.cayenne.access.trans.QueryAssembler.createStatement(QueryAssembler.java:135)
            at org.objectstyle.cayenne.access.DataNode.runSelect(DataNode.java:377)
            at
    org.objectstyle.cayenne.access.DataNode.performQueries(DataNode.java:281)
            at
    org.objectstyle.cayenne.access.DataDomain.performQueries(DataDomain.java:466)
            at
    org.objectstyle.cayenne.access.DataContext.performQueries(DataContext.java:822)
            at
    org.objectstyle.cayenne.access.DataContext.performQuery(DataContext.java:874)
            at
    org.objectstyle.cayenne.access.DataContext.performQuery(DataContext.java:752)
            at
    org.objectstyle.cayenne.access.DataContext.refetchObject(DataContext.java:626)
            at
    org.objectstyle.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:198)
            at
    org.objectstyle.cayenne.CayenneDataObject.readNestedProperty(CayenneDataObject.java:157)
            at Main.runTest(Main.java:39)
            at Main.main(Main.java:71)
    INFO QueryLogger: *** error.

    I've stepped through the code and discovered what I think might be the
    problem. In
    org.objectstyle.cayenne.access.QueryLogger.sqlLiteralForObject(StringBuffer,
    Object), line 158, it appears to be building part of the SQL with:

                 for (int i = 0; i < len; i++) {
                     appendFormattedByte(buf, b[i]);
                     buf.append(' ');
                 }

    buf = "SELECT t0.apnPoolNumber, t0.identifier FROM APNPoolNumber t0
    WHERE t0.identifier = ? [bind: < "
    b = [0, 0, 0, 0, 0, 0, 0, 34, 76, -96, 110, 73]
    len = 12

    The problem occurs when i=9 and it hits the -96 value. That's when the
    exception occurs. It seems to me this might work if the value is
    unsigned or if the appendFormattedByte(StringBuffer, byte) function
    added 128 to it, such as:

         protected static void appendFormattedByte(
             StringBuffer buf,
             byte byteValue) {

             String hexDecode = "0123456789ABCDEF";

             if (byteValue < 0)
               byteValue += 128;

             buf.append(hexDecode.charAt(byteValue >>> 4));
             buf.append(hexDecode.charAt(byteValue & 0x0F));
         }

    Also, you might want to make hexDecode final so you aren't allocating
    strings repeatedly.

    Does this seem the right thing to do? I'm *very* new to Cayenne and am
    just looking for an ORM tool that can handle our DB model (Hibernate
    cannot -- they explicitly do not allow for binary -- array of bytes -- PKs).

    Thanks!

    /dev/mrg



    This archive was generated by hypermail 2.0.0 : Tue Oct 21 2003 - 12:44:06 EDT