Re: cay-832 (enums in in exp)

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Sat Jul 28 2007 - 13:06:27 EDT

  • Next message: Andrus Adamchik: "Re: cay-832 (enums in in exp)"

    On Jul 28, 2007, at 10:00 AM, Robert Zeigler wrote:

    > Regarding lines 118 - 125, if attr is null, what should type
    > default to? I really don't think that will work, honestly.
    > In my own extended types, I do processing based on the type
    > attribute... so does the EnumType, for that matter, since it
    > determines whether to convert to int or string based on the
    > database type. So, seems like the long-term "right" solution is to
    > make sure that DbAttribute is something correct...

    Sure.

    On the long run we may also try to take advantage of JDBC
    'java.sql.ParameterMetaData'. When Cayenne project started years ago,
    most drivers were fairly low quality, so we have too many workarounds
    in the system. At some point we'll need to investigate whether there
    is a significant performance penalty with modern drivers when using
    PreparedStatememt parameter metadata instead of trying to guess the
    types from Cayenne mapping. This should make the translator code
    soooo much cleaner.

    > As for debugging, I put the breakpoint in and started walking back
    > up the stack.
    > As predicted, it's QualifierTranslator. More specifically, the
    > paramsDbType method of QueryAssemblerHelper is returning null.
    > So, digging a little further, the point at which the paramsDbType
    > returns null is on the unary operator check.
    >
    > Lines 286-291 of QueryAssemblerHelper:
    >
    > protected DbAttribute paramsDbType(Expression e) {
    > int len = e.getOperandCount();
    > // ignore unary expressions
    > if (len < 2) {
    > return null;
    > }
    >
    > e.getOperandCount returns 1.
    > e is an instance of ASTList, which always returns 1 for the operand
    > count.
    > So, you get the null DbAttribute there, which is then passed into
    > QueryTranslator.appendList, from there into
    > QueryTranslator.appendLiteral,
    > In appendLiteral, matchingObject is going to be false for any type
    > that isn't a data object
    > (which suggest that /any/ extended type is going to have issues
    > with inExp... something I will test tomorrow).

    I am sure you are right in this assessment. I played with it a bit,
    changing the algorithm above to use a parent expression for unary
    expressions. This worked, except that I noticed that
    ExpressionFactory doesn't initialize parent variable. So I had to fix
    that as well. The patch below made against 3.0 (trunk) fixes the
    problem for me. Now to be consistent I'll have to fix parent
    initialization of all expressions. Let me finish the patch, and apply
    it to all branches.

    Andrus

    Index: src/main/java/org/apache/cayenne/exp/parser/ASTIn.java
    ===================================================================
    --- src/main/java/org/apache/cayenne/exp/parser/ASTIn.java (revision
    558748)
    +++ src/main/java/org/apache/cayenne/exp/parser/ASTIn.java (working
    copy)
    ..-44,6 +44,8 @@
              super(ExpressionParserTreeConstants.JJTIN);
              jjtAddChild(path, 0);
              jjtAddChild(list, 1);
    + path.jjtSetParent(this);
    + list.jjtSetParent(this);
          }
          protected Object evaluateNode(Object o) throws Exception {
    Index: src/main/java/org/apache/cayenne/access/trans/
    QueryAssemblerHelper.java
    ===================================================================
    --- src/main/java/org/apache/cayenne/access/trans/
    QueryAssemblerHelper.java (revision 558748)
    +++ src/main/java/org/apache/cayenne/access/trans/
    QueryAssemblerHelper.java (working copy)
    ..-27,6 +27,7 @@
    import org.apache.cayenne.ObjectId;
    import org.apache.cayenne.Persistent;
    import org.apache.cayenne.exp.Expression;
    +import org.apache.cayenne.exp.parser.SimpleNode;
    import org.apache.cayenne.map.DbAttribute;
    import org.apache.cayenne.map.DbEntity;
    import org.apache.cayenne.map.DbJoin;
    ..-285,8 +286,18 @@
           */
          protected DbAttribute paramsDbType(Expression e) {
              int len = e.getOperandCount();
    - // ignore unary expressions
    +
    + // for unary expressions, find parent binary - this is a
    hack mainly to support
    + // ASTList
              if (len < 2) {
    +
    + if (e instanceof SimpleNode) {
    + Expression parent = (Expression) ((SimpleNode)
    e).jjtGetParent();
    + if (parent != null) {
    + return paramsDbType(parent);
    + }
    + }
    +
                  return null;
              }



    This archive was generated by hypermail 2.0.0 : Sat Jul 28 2007 - 13:06:55 EDT