You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2010/07/23 22:15:07 UTC

svn commit: r967240 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-jdbc/src/main/java/org/...

Author: faywang
Date: Fri Jul 23 20:15:06 2010
New Revision: 967240

URL: http://svn.apache.org/viewvc?rev=967240&view=rev
Log:
OPENJPA-1740: fix Type expression when entities use Joined table strategy.

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java   (with props)
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualTypeExpression.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ExpContext.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualTypeExpression.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Fri Jul 23 20:15:06 2010
@@ -363,22 +363,59 @@ public class JDBCStoreQuery 
                sel.setExpectedResultCount(optHint.intValue(), true);
             else if (this.ctx.isUnique())
                 sel.setExpectedResultCount(1, false);
-            for (int j = 0; j < verts.length; j++) {
-                selMappings.add(verts[j]);
-                if (j == verts.length - 1) {
-                    nextBits.set(sels.size());
-                    sels.add(sel);
-                } else
-                    sels.add(sel.fullClone(1));
+            
+            List selectFrom = getJoinedTableMeta(sel);
+            int size = 0;
+            if (selectFrom != null) {
+                size = selectFrom.size();
+                for (int j = 0; j < size; j++) {
+                    ClassMapping vert = (ClassMapping)selectFrom.get(j); 
+                    selMappings.add(vert);
+                    if (j == size - 1) {
+                        nextBits.set(sels.size());
+                        sel.select(vert.getPrimaryKeyColumns(), null);
+                        sels.add(sel);
+                    } else {
+                        SelectImpl selClone = (SelectImpl)sel.fullClone(1);
+                        selClone.select(vert.getPrimaryKeyColumns(), null);
+                        sels.add(selClone);
+                    }
+                }
+            } else {
+                for (int j = 0; j < verts.length; j++) {
+                    selMappings.add(verts[j]);
+                    if (j == verts.length - 1) {
+                        nextBits.set(sels.size());
+                        sels.add(sel);
+                    } else
+                        sels.add(sel.fullClone(1));
+                }
             }
-
+            
             // turn off unioning if a given independent mapping requires
             // multiple selects, or if we're using FROM selects
-            if (verts.length > 1 || sel.getFromSelect() != null)
+            if (verts.length > 1 || size > 1 || sel.getFromSelect() != null)
                 unionable = false;
         }
         return unionable;
     }
+    
+    private List getJoinedTableMeta(Select sel) {
+        List selectFrom = sel.getJoinedTableClassMeta();
+        List exSelectFrom = sel.getExcludedJoinedTableClassMeta();
+        if (exSelectFrom == null)
+            return selectFrom;
+        if (selectFrom == null)
+            return null;
+        int size = selectFrom.size();
+        List retList = new ArrayList(size);
+        for (int i = 0; i < size; i++) {
+            Object obj = selectFrom.get(i);
+            if (!exSelectFrom.contains(obj))
+                retList.add(obj);
+        }
+        return retList;
+    }
 
     /**
      * Return all the vertical mappings to select separately. Depends on

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualTypeExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualTypeExpression.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualTypeExpression.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EqualTypeExpression.java Fri Jul 23 20:15:06 2010
@@ -18,9 +18,14 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.meta.ClassMetaData;
 
 /**
  * Compares two entity types.
@@ -37,6 +42,30 @@ class EqualTypeExpression
         super(val1, val2);
     }
 
+    private ClassMapping getSubClassMapping(Val val1, Val val2, ExpContext ctx) {
+        ClassMapping sub = null;
+        Val val = val1 instanceof Type ? val2 : val1;
+        if (val instanceof TypeLit)
+            sub = (ClassMapping) val.getMetaData();
+        else if (val instanceof Param)
+            sub = ((Param) val).getValueMetaData(ctx);
+        if (sub != null)
+            ctx.isVerticalStrat = sub.isVerticalStrategy();
+        return sub;
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+            SQLBuffer buf) {
+        Val val1 = getValue1();
+        Val val2 = getValue2();
+        ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+        if (ctx.isVerticalStrat) {
+            appendTo(sel, ctx, (BinaryOpExpState)state, buf, false, false);
+            return;
+        }
+        super.appendTo(sel, ctx, state, buf);
+    }
+
     public void appendTo(Select sel, ExpContext ctx, BinaryOpExpState bstate, 
         SQLBuffer buf, boolean val1Null, boolean val2Null) {
         if (val1Null && val2Null)
@@ -59,17 +88,16 @@ class EqualTypeExpression
             Val val2 = getValue2();
             if (val1.length(sel, ctx, bstate.state1) == 1 
                 && val2.length(sel, ctx, bstate.state2) == 1) {
-                String op = "=";
-                if (sel.getTablePerClassMeta() != null) {
-                    if (val1 instanceof Type) {
-                        if ((ClassMapping) val2.getMetaData() != sel.getTablePerClassMeta())
-                            op = "<>";
-                    }
-                    else {
-                        if ((ClassMapping) val1.getMetaData() != sel.getTablePerClassMeta())
-                            op = "<>";
-                    }
+                ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+                if (ctx.isVerticalStrat) {
+                    processVerticalTypeAppend(sel, val1, val2, ctx, buf);
+                    return;
                 }
+                    
+                String op = "=";
+                if (sel.getTablePerClassMeta() != null && sub != sel.getTablePerClassMeta()) 
+                    op = "<>";
+
                 ctx.store.getDBDictionary().comparison(buf, op,
                     new FilterValueImpl(sel, ctx, bstate.state1, val1),
                     new FilterValueImpl(sel, ctx, bstate.state2, val2));
@@ -87,4 +115,27 @@ class EqualTypeExpression
             }
         }
     }
+    
+    void processVerticalTypeAppend(Select sel, Val val1, Val val2, ExpContext ctx,  
+        SQLBuffer buf) {
+        ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+        List selectFrom = sel.getJoinedTableClassMeta();
+        if (selectFrom == null) {
+            selectFrom = new ArrayList();
+            sel.setJoinedTableClassMeta(selectFrom);
+        }
+        ClassMapping cm1 = (ClassMapping)((val1 instanceof Type) ? val1.getMetaData() :
+            val1.getMetaData());
+        if (sub.isVerticalStrategy()) {
+            ClassMetaData[] subs = cm1.getPCSubclassMetaDatas();
+            for (int i = 0; i < subs.length; i++) {
+                if (!Modifier.isAbstract(subs[i].getDescribedType().getModifiers()) && subs[i] == sub 
+                    && !selectFrom.contains(subs[i]))
+                    selectFrom.add(subs[i]);
+            }
+            buf.append("1=1");
+            return;
+        }
+    }
+
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ExpContext.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ExpContext.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ExpContext.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ExpContext.java Fri Jul 23 20:15:06 2010
@@ -46,6 +46,8 @@ public class ExpContext {
     public JDBCFetchConfiguration fetch; 
 
     public ClassMapping tpcMeta = null;
+    
+    public boolean isVerticalStrat = false;
 
     public ExpContext() {
     }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java Fri Jul 23 20:15:06 2010
@@ -24,8 +24,8 @@ import java.util.Date;
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.meta.Discriminator;
 import org.apache.openjpa.jdbc.meta.strats.NoneDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
-import org.apache.openjpa.jdbc.sql.PostgresDictionary;
 import org.apache.openjpa.jdbc.sql.Raw;
 import org.apache.openjpa.kernel.exps.AggregateListener;
 import org.apache.openjpa.kernel.exps.Arguments;
@@ -574,4 +574,14 @@ public class JDBCExpressionFactory
     public Value newFunction(String functionName, Class<?> resultType, Value... args) {
         return new DatastoreFunction(functionName, resultType, newArgumentList(args));
     }
+    
+    public boolean isVerticalType(Value val) {
+        if (!(val instanceof Type))
+            return false;
+        ClassMapping cm = (ClassMapping)((Type)val).getMetaData();
+        String strat = cm.getMappingInfo().getHierarchyStrategy(); 
+        if (strat != null && strat.equals(VerticalClassStrategy.ALIAS)) 
+            return true;
+        return false;
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualTypeExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualTypeExpression.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualTypeExpression.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NotEqualTypeExpression.java Fri Jul 23 20:15:06 2010
@@ -18,9 +18,14 @@
  */
 package org.apache.openjpa.jdbc.kernel.exps;
 
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.meta.ClassMetaData;
 
 /**
  * Compares two entity types.
@@ -37,6 +42,31 @@ class NotEqualTypeExpression
         super(val1, val2);
     }
 
+    private ClassMapping getSubClassMapping(Val val1, Val val2, ExpContext ctx) {
+        ClassMapping sub = null;
+        Val val = val1 instanceof Type ? val2 : val1;
+        if (val instanceof TypeLit)
+            sub = (ClassMapping) val.getMetaData();
+        else if (val instanceof Param)
+            sub = ((Param) val).getValueMetaData(ctx);
+        if (sub != null)
+            ctx.isVerticalStrat = sub.isVerticalStrategy();
+        return sub;
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+            SQLBuffer buf) {
+        Val val1 = getValue1();
+        Val val2 = getValue2();
+        ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+        if (ctx.isVerticalStrat) {
+            appendTo(sel, ctx, (BinaryOpExpState)state, buf, false, false);
+            return;
+        }
+        
+        super.appendTo(sel, ctx, state, buf);
+    }
+    
     public void appendTo(Select sel, ExpContext ctx, BinaryOpExpState bstate, 
         SQLBuffer buf, boolean val1Null, boolean val2Null) {
         if (val1Null && val2Null)
@@ -59,14 +89,19 @@ class NotEqualTypeExpression
             Val val2 = getValue2();
             if (val1.length(sel, ctx, bstate.state1) == 1 
                 && val2.length(sel, ctx, bstate.state2) == 1) {
-                String op = "<>";
-                if (val1 instanceof Type)
-                    if ((ClassMapping) val2.getMetaData() != sel.getTablePerClassMeta())
-                        op = "=";
+                ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+                if (ctx.isVerticalStrat) {
+                    processVerticalTypeAppend(sel, val1, val2, ctx, buf);
+                    return;
+                }
+                    
+                String op;
+                if (sub != sel.getTablePerClassMeta())
+                    op = "=";
                 else
-                    if ((ClassMapping) val1.getMetaData() != sel.getTablePerClassMeta())
-                        op = "=";
-                ctx.store.getDBDictionary().comparison(buf, op,
+                    op = "<>";
+                
+               ctx.store.getDBDictionary().comparison(buf, op,
                     new FilterValueImpl(sel, ctx, bstate.state1, val1),
                     new FilterValueImpl(sel, ctx, bstate.state2, val2));
             } else {
@@ -84,4 +119,33 @@ class NotEqualTypeExpression
             }
         }
     }
+    
+    void processVerticalTypeAppend(Select sel, Val val1, Val val2, ExpContext ctx,  
+            SQLBuffer buf) {
+        ClassMapping sub = getSubClassMapping(val1, val2, ctx);
+        ClassMapping cm1 = (ClassMapping)((val1 instanceof Type) ? val1.getMetaData() :
+            val1.getMetaData());
+        if (sub != null && sub.isVerticalStrategy()) {
+            ClassMetaData[] subs = cm1.getPCSubclassMetaDatas();
+            List exSelectFrom = sel.getExcludedJoinedTableClassMeta();
+            if (exSelectFrom == null) {
+                exSelectFrom = new ArrayList();
+                sel.setExcludedJoinedTableClassMeta(exSelectFrom);
+            }
+            List selectFrom = sel.getJoinedTableClassMeta();
+            exSelectFrom.add(sub);
+            if (selectFrom == null) {
+                selectFrom = new ArrayList();
+                sel.setJoinedTableClassMeta(selectFrom);
+            }
+            
+            for (int i = 0; i < subs.length; i++) {
+                if (!Modifier.isAbstract(subs[i].getDescribedType().getModifiers()) && 
+                    !selectFrom.contains(subs[i]))
+                    selectFrom.add(subs[i]);
+            }
+            buf.append("1=1");
+            return;
+        }
+    }    
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java Fri Jul 23 20:15:06 2010
@@ -75,6 +75,14 @@ public class Param
         _idx = idx;
     }
 
+    public ClassMapping getValueMetaData(ExpContext ctx) {
+        Object[] params = ctx.params;
+        if (params[_idx] != null && params[_idx] instanceof Class)
+            return (ClassMapping) ctx.store.getConfiguration().getMetaDataRepositoryInstance().
+                getMetaData((Class) params[_idx], getClass().getClassLoader(), true);
+        return null;
+    }
+
     public Object getValue(Object[] params) {
         return Filters.convert(params[_idx], getType());
     }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Fri Jul 23 20:15:06 2010
@@ -34,6 +34,7 @@ import org.apache.openjpa.enhance.Reflec
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
 import org.apache.openjpa.jdbc.schema.Column;
 import org.apache.openjpa.jdbc.schema.ColumnIO;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
@@ -1101,4 +1102,11 @@ public class ClassMapping
     	}
     	return result;
     }
+
+    public boolean isVerticalStrategy() {
+        String strat = getMappingInfo().getHierarchyStrategy();
+        if (strat != null && strat.equals(VerticalClassStrategy.ALIAS))
+            return true;
+        return false;
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java Fri Jul 23 20:15:06 2010
@@ -911,6 +911,22 @@ public class LogicalUnion
         public ClassMapping getTablePerClassMeta() {
             return sel.getTablePerClassMeta();
         }
+        
+        public void setJoinedTableClassMeta(List meta) {
+            sel.setJoinedTableClassMeta(meta);
+        }
+
+        public List getJoinedTableClassMeta() {
+            return sel.getJoinedTableClassMeta();
+        }
+        
+        public void setExcludedJoinedTableClassMeta(List meta) {
+            sel.setExcludedJoinedTableClassMeta(meta);
+        }
+
+        public List getExcludedJoinedTableClassMeta() {
+            return sel.getExcludedJoinedTableClassMeta();
+        }
     }
 
     /**

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java Fri Jul 23 20:15:06 2010
@@ -747,4 +747,24 @@ public interface Select
      * get table-per-class metadata for polymorphic queries
      */
     public ClassMapping getTablePerClassMeta();
+
+    /**
+     * Set joined table metadatas for polymorphic queries
+     */
+    public void setJoinedTableClassMeta(List meta);
+
+    /**
+     * get joined table metadatas for polymorphic queries
+     */
+    public List getJoinedTableClassMeta();
+
+    /**
+     * Set joined table metadatas excluded for polymorphic queries
+     */
+    public void setExcludedJoinedTableClassMeta(List meta);
+
+    /**
+     * get joined table metadatas excluded for polymorphic queries
+     */
+    public List getExcludedJoinedTableClassMeta();
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java Fri Jul 23 20:15:06 2010
@@ -170,12 +170,32 @@ public class SelectImpl
     // A path navigation is begin with this schema alias
     private String _schemaAlias = null;
     private ClassMapping _tpcMeta = null;
+    private List _joinedTables = null;
+    private List _exJoinedTables = null;
+    
     public ClassMapping getTablePerClassMeta() {
         return _tpcMeta;
     }
     public void setTablePerClassMeta(ClassMapping meta) {
         _tpcMeta = meta;
     }
+    
+    public void setJoinedTableClassMeta(List meta) {
+        _joinedTables = meta;
+    }
+
+    public List getJoinedTableClassMeta() {
+        return _joinedTables;
+    }
+    
+    public void setExcludedJoinedTableClassMeta(List meta) {
+        _exJoinedTables = meta;
+    }
+
+    public List getExcludedJoinedTableClassMeta() {
+        return _exJoinedTables;
+    }
+    
      
     /**
      * Helper method to return the proper table alias for the given alias index.

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java Fri Jul 23 20:15:06 2010
@@ -496,4 +496,9 @@ public interface ExpressionFactory {
      * Return a value representing the given datastore function with the given arguments.
      */
     public Value newFunction(String functionName, Class<?> resultType, Value... args);
+    
+    /**
+     * Return true if the Value is a Type expression and the Type uses joined table strategy.
+     */
+    public boolean isVerticalType(Value val);
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java Fri Jul 23 20:15:06 2010
@@ -796,4 +796,8 @@ public class InMemoryExpressionFactory
     public Value newFunction(String functionName, Class<?> resultType, Value... args) {
         throw new AbstractMethodError();
     }
+    
+    public boolean isVerticalType(Value val) {
+        return false;
+    }
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Fri Jul 23 20:15:06 2010
@@ -35,7 +35,6 @@ import java.util.Set;
 import java.util.Stack;
 import java.util.TreeSet;
 
-import org.apache.commons.collections.map.LinkedMap;
 import org.apache.openjpa.conf.Compatibility;
 import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.kernel.BrokerFactory;
@@ -1137,23 +1136,33 @@ public class JPQLExpressionBuilder
 
                     // special case for <value> IN (<subquery>) or
                     // <value> IN (<single value>)
-                    if (!(val2 instanceof Literal) && node.getChildCount() == 2)
+                    if (useContains(not, val1, val2, node))    
                         return evalNot(not, factory.contains(val2, val1)); 
 
                     // this is currently a sequence of OR expressions, since we
                     // do not have support for IN expressions
                     setImplicitTypes(val1, val2, null);
-                    if (inExp == null)
-                        inExp = factory.equal(val1, val2);
-                    else
-                        inExp = factory.or(inExp, factory.equal(val1, val2));
+                    if (isVerticalTypeInExpr(val1, node) && not) {
+                        if (inExp == null)
+                            inExp = factory.notEqual(val1, val2);
+                        else
+                            inExp = factory.and(inExp, factory.notEqual(val1, val2));
+                    } else {
+                        if (inExp == null)
+                            inExp = factory.equal(val1, val2);
+                        else
+                            inExp = factory.or(inExp, factory.equal(val1, val2));
+                    }
                 }
 
                 // we additionally need to add in a "NOT NULL" clause, since
                 // the IN behavior that is expected by the CTS also expects
                 // to filter our NULLs
-                return and(evalNot(not, inExp),
-                    factory.notEqual(val1, factory.getNull()));
+                if (isVerticalTypeInExpr(val1, node)) 
+                    return inExp;
+                else    
+                    return and(evalNot(not, inExp),
+                            factory.notEqual(val1, factory.getNull()));
 
             case JJTISNULL: // x.field IS [NOT] NULL
                 val1 = getValue(onlyChild(node));
@@ -1414,6 +1423,19 @@ public class JPQLExpressionBuilder
         }
     }
     
+    private boolean useContains(boolean not, Value val1, Value val2, JPQLNode node) {
+        if (isVerticalTypeInExpr(val1, node) && not)
+            return false;
+        else
+            return (!(val2 instanceof Literal) && node.getChildCount() == 2);
+    }
+    
+    private boolean isVerticalTypeInExpr(Value val, JPQLNode node) {
+        if (node.id != JJTIN)
+            return false;
+        return factory.isVerticalType(val);
+    }
+    
     private Value getIntegerValue(JPQLNode node) {
         BigDecimal bigdec = new BigDecimal
         (node.text.endsWith("l") || node.text.endsWith("L")

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java?rev=967240&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java Fri Jul 23 20:15:06 2010
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.Index;
+
+@Inheritance(strategy=InheritanceType.JOINED)
+@Entity
+@Table(name="WFulltimeEmployee")
+public class FulltimeEmployee extends Employee {
+    @Column(name="FTEmpProp1",length=10)
+    @Basic
+    private String ftEmpProp1;
+
+
+    @ManyToOne(optional=true,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.LAZY)
+    @JoinColumn(name="Dept_No",referencedColumnName="OID")
+    @Index
+    private Department dept;
+
+    public FulltimeEmployee() {
+    }
+
+    public FulltimeEmployee(String desc) {
+        setDescription(desc);
+    }
+
+    public String getFTEmpProp1() {
+        return ftEmpProp1;
+    }
+
+    public void setFTEmpProp1(String ftEmpProp1) {
+        this.ftEmpProp1 = ftEmpProp1;
+    }
+
+    public Department getDept() {
+        return dept;
+    }
+
+    public void setDept(Department dept) {
+        this.dept = dept;
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof FulltimeEmployee) {
+            FulltimeEmployee c = (FulltimeEmployee) other;
+            if (c.getOID() == this.getOID() &&
+                c.getDept() == this.getDept())
+                return true;
+        }
+        return false;
+    }
+}
+

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/FulltimeEmployee.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java?rev=967240&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java Fri Jul 23 20:15:06 2010
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.inheritance.jointable;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.Index;
+
+@Inheritance(strategy=InheritanceType.JOINED)
+@Entity
+@Table(name="WParttimeEmployee")
+public class ParttimeEmployee extends Employee {
+    @Column(name="PTEmpProp1",length=10)
+    @Basic
+    private String ptEmpProp1;
+
+
+    @ManyToOne(optional=true,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.LAZY)
+    @JoinColumn(name="Dept_No",referencedColumnName="OID")
+    @Index
+    private Department dept;
+
+    public ParttimeEmployee() {
+    }
+
+    public ParttimeEmployee(String desc) {
+        setDescription(desc);
+    }
+
+    public String getPTEmpProp1() {
+        return ptEmpProp1;
+    }
+
+    public void setPTEmpProp1(String ptEmpProp1) {
+        this.ptEmpProp1 = ptEmpProp1;
+    }
+
+    public Department getDept() {
+        return dept;
+    }
+
+    public void setDept(Department dept) {
+        this.dept = dept;
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof ParttimeEmployee) {
+            ParttimeEmployee c = (ParttimeEmployee) other;
+            if (c.getOID() == this.getOID() &&
+                c.getDept() == this.getDept())
+                return true;
+        }
+        return false;
+    }
+}
+

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/ParttimeEmployee.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java?rev=967240&r1=967239&r2=967240&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/jointable/TestInheritanceTypeJoinedQuery.java Fri Jul 23 20:15:06 2010
@@ -30,9 +30,13 @@ import org.apache.openjpa.persistence.te
 
 
 public class TestInheritanceTypeJoinedQuery  extends SQLListenerTestCase {
+    private int numPTEmployees = 1;
+    private int numFTEmployees = 2;
+    private int numContractors = 3;
 
     public void setUp() {
         setUp(Contractor.class, Employee.class, Department.class, Person.class,
+            FulltimeEmployee.class, ParttimeEmployee.class,     
             CLEAR_TABLES);
         populate();
     }
@@ -41,13 +45,25 @@ public class TestInheritanceTypeJoinedQu
         EntityManager em = emf.createEntityManager();
         
         Department d = new Department("IT");
-        for (int i = 0; i < 3; i++) {
+        for (int i = 0; i < numContractors; i++) {
             Contractor c = new Contractor("ctr" + i);
             c.setDept(d);
             em.persist(c);
         }
         em.persist(d);
-      
+
+        for (int i = 0; i < numFTEmployees; i++) {
+            FulltimeEmployee f = new FulltimeEmployee("ftemp" + i);
+            f.setDept(d);
+            em.persist(f);
+        }
+
+        for (int i = 0; i < numPTEmployees; i++) {
+            ParttimeEmployee p = new ParttimeEmployee("ptemp" + i);
+            p.setDept(d);
+            em.persist(p);
+        }
+        
         em.getTransaction().begin();
         em.getTransaction().commit();
         em.close();
@@ -57,16 +73,28 @@ public class TestInheritanceTypeJoinedQu
         EntityManager em = emf.createEntityManager();
         Query q = null;
         String qS = null;
+        List rs = null;
+        
+        qS = "SELECT p FROM Person p where TYPE(p) <> Contractor";
+        q = em.createQuery(qS);
+        rs = q.getResultList();
+        assertEquals(numPTEmployees + numFTEmployees, rs.size());
+        for (int i = 0; i < rs.size(); i++){
+            Object obj = rs.get(i);
+            assertTrue((obj instanceof ParttimeEmployee) || (obj instanceof FulltimeEmployee));
+        }
+        
         qS = "SELECT p FROM Person p where TYPE(p) = Contractor";
         q = em.createQuery(qS); 
-        List rs = q.getResultList();
-        assertEquals(3, rs.size());
+        rs = q.getResultList();
+        assertEquals(numContractors, rs.size());
         for (int i = 0; i < rs.size(); i++)
             assertTrue(rs.get(i) instanceof Contractor);
+        
         qS = "select p from Person p where TYPE(p) in (?1) order by p.name";
         q = em.createQuery(qS).setParameter(1, Contractor.class);
         rs = q.getResultList();
-        assertEquals(3, rs.size());
+        assertEquals(numContractors, rs.size());
         for (int i = 0; i < rs.size(); i++)
             assertTrue(rs.get(i) instanceof Contractor);
 
@@ -82,6 +110,67 @@ public class TestInheritanceTypeJoinedQu
             //System.out.println(e.getMessage());
         }
         
+        qS = "SELECT p FROM Person p where TYPE(p) = Contractor AND p.name = 'Name ctr0'";
+        q = em.createQuery(qS);
+        rs = q.getResultList();
+        assertEquals(1, rs.size());
+        for (int i = 0; i < rs.size(); i++)
+            assertTrue(rs.get(i) instanceof Contractor);
+
+        qS = "select p from Person p where TYPE(p) in (?1, ?2) and p.name = ?3 order by p.name";
+        q = em.createQuery(qS);
+        q.setParameter(1, Contractor.class);
+        q.setParameter(2, FulltimeEmployee.class);
+        q.setParameter(3, "Name ctr0");
+       
+        rs = q.getResultList();
+        assertEquals(1, rs.size());
+        for (int i = 0; i < rs.size(); i++) {
+            Object obj = rs.get(i);
+            assertTrue(obj instanceof Contractor || obj instanceof FulltimeEmployee);
+        }
+
+        qS = "select p from Person p where TYPE(p) in (?1, ?2) order by p.name";
+        q = em.createQuery(qS);
+        q.setParameter(1, Contractor.class);
+        q.setParameter(2, FulltimeEmployee.class);
+        
+        rs = q.getResultList();
+        assertEquals(numContractors + numFTEmployees, rs.size());
+        for (int i = 0; i < rs.size(); i++) {
+            Object obj = rs.get(i);
+            assertTrue(obj instanceof Contractor || obj instanceof FulltimeEmployee);
+        }
+        
+        qS = "select p from Person p where TYPE(p) not in (Contractor) order by p.name";
+        q = em.createQuery(qS);
+        rs = q.getResultList();
+        assertEquals(numPTEmployees + numFTEmployees, rs.size());
+        for (int i = 0; i < rs.size(); i++){
+            Object obj = rs.get(i);
+            assertTrue((obj instanceof ParttimeEmployee) || (obj instanceof FulltimeEmployee));
+        }
+        
+        qS = "select p from Person p where TYPE(p) not in (?1) order by p.name";
+        q = em.createQuery(qS);
+        q.setParameter(1, Contractor.class);
+        rs = q.getResultList();
+        assertEquals(numPTEmployees + numFTEmployees, rs.size());
+        for (int i = 0; i < rs.size(); i++){
+            Object obj = rs.get(i);
+            assertTrue((obj instanceof ParttimeEmployee) || (obj instanceof FulltimeEmployee));
+        }
+
+        qS = "select p from Person p where TYPE(p) not in (?1, ?2) order by p.name";
+        q = em.createQuery(qS);
+        q.setParameter(1, Contractor.class);
+        q.setParameter(2, FulltimeEmployee.class);
+        rs = q.getResultList();
+        assertEquals(numPTEmployees, rs.size());
+        for (int i = 0; i < rs.size(); i++){
+            Object obj = rs.get(i);
+            assertTrue((obj instanceof ParttimeEmployee) || (obj instanceof FulltimeEmployee));
+        }
     }
 
     public void testInheritanceTypeJoinedQuery() {
@@ -183,8 +272,10 @@ public class TestInheritanceTypeJoinedQu
 
         qS = "SELECT p FROM Person p ";
         q = em.createQuery(qS);
-        for (Object aResult: (List<Object>) q.getResultList()) {
-            assertTrue(aResult instanceof Contractor);
+        List rs = (List<Object>) q.getResultList();
+        assertEquals(numPTEmployees + numFTEmployees + numContractors, rs.size());        
+        for (Object aResult: rs) {
+            assertTrue(aResult instanceof Person);
         }
 
         em.close();