openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fa...@apache.org
Subject svn commit: r725728 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/ openjpa-persistence-jdbc/...
Date Thu, 11 Dec 2008 16:16:33 GMT
Author: fancy
Date: Thu Dec 11 08:16:32 2008
New Revision: 725728

URL: http://svn.apache.org/viewvc?rev=725728&view=rev
Log:
OPENJPA-805 JPQL iteration 1: add support for Case Expressions

Added:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GeneralCaseExpression.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SimpleCaseExpression.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenCondition.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenScalar.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.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

Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GeneralCaseExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GeneralCaseExpression.java?rev=725728&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GeneralCaseExpression.java
(added)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/GeneralCaseExpression.java
Thu Dec 11 08:16:32 2008
@@ -0,0 +1,193 @@
+/*
+ * 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.jdbc.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Raw;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * General case expression.
+ *
+ * @author Catalina Wei
+ */
+public class GeneralCaseExpression
+    extends AbstractVal {
+
+    private final Exp[] _exp;
+    private final Val _val;
+    private ClassMetaData _meta = null;
+    private Class _cast = null;
+
+    /**
+     * Constructor.
+     */
+    public GeneralCaseExpression(Exp[] exp, Val val) {
+        _exp = exp;
+        _val = val;
+    }
+
+    public Exp[] getExp() {
+        return _exp;
+    }
+
+    public Val getVal() {
+        return _val;
+    }
+
+    public Class getType() {
+        if (_cast != null)
+            return _cast;
+        Class type = _val.getType();
+        for (int i = 0; i < _exp.length; i++)
+            type = Filters.promote(type,
+                ((WhenCondition) _exp[i]).getVal().getType());
+        if (type == Raw.class)
+            return String.class;
+        return type;
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        ExpState[] states = new ExpState[_exp.length+1];
+        Joins joins = null;
+        int i = 0;
+        for (; i < _exp.length; i++) {
+            states[i] = _exp[i].initialize(sel, ctx, null);
+            if (joins == null)
+                joins = states[i].joins;
+            else
+                joins = sel.and(joins, states[i].joins);
+        }
+        states[i] = _val.initialize(sel, ctx, 0);
+        if (joins == null)
+            joins = states[i].joins;
+        else
+            joins = sel.and(joins, states[i].joins);
+        return new GeneralCaseExpState(joins, states);
+    }
+
+    private static class GeneralCaseExpState
+        extends ExpState {
+        
+        public ExpState[] states;
+        
+        public GeneralCaseExpState(Joins joins, ExpState[] states) {
+            super(joins);
+            this.states = states;
+        }
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf, int index) {
+        GeneralCaseExpState cstate = (GeneralCaseExpState) state;
+
+        buf.append(" CASE ");
+        int i = 0;
+        for (; i < _exp.length; i++)
+            _exp[i].appendTo(sel, ctx, cstate.states[i], buf);
+
+        buf.append(" ELSE ");
+        _val.appendTo(sel, ctx, cstate.states[i], buf, 0);
+
+        buf.append(" END ");
+    }
+
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        GeneralCaseExpState cstate = (GeneralCaseExpState) state;
+        int i = 0;
+        for (; i < _exp.length; i++)
+            _exp[i].selectColumns(sel, ctx, cstate.states[i], pks);
+        _val.selectColumns(sel, ctx, cstate.states[i], pks);
+    }
+
+    public void acceptVisit(ExpressionVisitor visitor) {
+        visitor.enter(this);
+        for (int i = 0; i < _exp.length; i++)
+            _exp[i].acceptVisit(visitor);
+        _val.acceptVisit(visitor);
+        visitor.exit(this);
+    }
+
+    public int getId() {
+        return Val.SIMPLECASE_VAL;
+    }
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state,
+        Val other, ExpState otherState) {
+        GeneralCaseExpState gstate = (GeneralCaseExpState) state;
+        for (int i = 0; i < _exp.length; i++) {   
+            BinaryOpExpState bstate = (BinaryOpExpState) gstate.states[i];
+            ((WhenCondition) _exp[i]).getVal().calculateValue(sel, ctx,
+                bstate.state2, null, null);
+        }
+        _val.calculateValue(sel, ctx, gstate.states[_exp.length], null, null);
+    }
+
+    public void groupBy(Select sel, ExpContext ctx, ExpState state) {
+        sel.groupBy(newSQLBuffer(sel, ctx, state));
+    }
+
+    public int length(Select sel, ExpContext ctx, ExpState state) {
+        return 1;
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) {
+        calculateValue(sel, ctx, state, null, null);
+        SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
+        appendTo(sel, ctx, state, buf, 0);
+        return buf;
+    }
+
+    public Object load(ExpContext ctx, ExpState state, Result res)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public void orderBy(Select sel, ExpContext ctx, ExpState state,
+        boolean asc) {
+        sel.orderBy(newSQLBuffer(sel, ctx, state), asc, false, getSelectAs());
+    }
+
+    public void select(Select sel, ExpContext ctx, ExpState state, boolean pks){
+        sel.select(newSQLBuffer(sel, ctx, state), this);
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setImplicitType(Class type) {
+        _cast = type;        
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+}
+

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=725728&r1=725727&r2=725728&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
Thu Dec 11 08:16:32 2008
@@ -23,6 +23,7 @@
 import org.apache.openjpa.jdbc.meta.ClassMapping;
 import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Raw;
 import org.apache.openjpa.kernel.exps.AggregateListener;
 import org.apache.openjpa.kernel.exps.Arguments;
 import org.apache.openjpa.kernel.exps.Expression;
@@ -400,4 +401,50 @@
         return new GetMapValue((Val) map, (Val) arg, 
             "gmv" + _getMapValueAlias++);
     }
+
+    public Value simpleCaseExpression(Value caseOperand, Expression[] exp,
+            Value val1) {
+        Exp[] exps = new Exp[exp.length];
+        for (int i = 0; i < exp.length; i++)
+            exps[i] = (Exp) exp[i];
+        if (val1 instanceof Lit) {
+            Lit val = (Lit) val1;
+            StringBuffer value = new StringBuffer(val.getValue().toString());
+            if (val.getParseType() == Literal.TYPE_SQ_STRING)
+                value.insert(0, "'").append("'");
+            val.setValue(new Raw(value.toString()));
+        }
+        return new SimpleCaseExpression((Val) caseOperand, exps,
+            (Val) val1);
+    }
+
+    public Value generalCaseExpression(Expression[] exp,
+            Value val) {
+        Exp[] exps = new Exp[exp.length];
+        for (int i = 0; i < exp.length; i++)
+            exps[i] = (Exp) exp[i];
+        return new GeneralCaseExpression(exps, (Val) val);
+    }
+
+    public Expression whenCondition(Expression exp, Value val) {
+        return new WhenCondition((Exp) exp, (Val) val);
+    }
+
+    public Expression whenScalar(Value val1, Value val2) {
+        if (val1 instanceof Lit) {
+            Lit val = (Lit) val1;
+            StringBuffer value = new StringBuffer(val.getValue().toString());
+            if (val.getParseType() == Literal.TYPE_SQ_STRING)
+                value.insert(0, "'").append("'");
+            val.setValue(new Raw(value.toString()));
+        }
+        if (val2 instanceof Lit) {
+            Lit val = (Lit) val2;
+            StringBuffer value = new StringBuffer(val.getValue().toString());
+            if (val.getParseType() == Literal.TYPE_SQ_STRING)
+                value.insert(0, "'").append("'");
+            val.setValue(new Raw(value.toString()));
+        }
+        return new WhenScalar((Val) val1, (Val) val2);
+    }
 }

Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SimpleCaseExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SimpleCaseExpression.java?rev=725728&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SimpleCaseExpression.java
(added)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SimpleCaseExpression.java
Thu Dec 11 08:16:32 2008
@@ -0,0 +1,228 @@
+/*
+ * 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.jdbc.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Raw;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * Simple case expression.
+ *
+ * @author Catalina Wei
+ */
+public class SimpleCaseExpression
+    extends AbstractVal {
+
+    private final Val _caseOperand;
+    private final Exp[] _exp;
+    private final Val _val;
+    private ClassMetaData _meta = null;
+    private Class _cast = null;
+
+    /**
+     * Constructor.
+     */
+    public SimpleCaseExpression(Val caseOperand, Exp[] exp, Val val) {
+        _caseOperand = caseOperand;
+        _exp = exp;
+        _val = val;
+    }
+
+    public Val getCaseOperand() {
+        return _caseOperand;
+    }
+
+    public Exp[] getExp() {
+        return _exp;
+    }
+
+    public Val getVal() {
+        return _val;
+    }
+
+    public Class getType() {
+        if (_cast != null)
+            return _cast;
+        Class type = _val.getType();
+        for (int i = 0; i < _exp.length; i++)
+            type = Filters.promote(type,
+                ((WhenScalar) _exp[i]).getVal2().getType());
+        if (type == Raw.class)
+            return String.class;
+        return type;
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        ExpState[] states = new ExpState[_exp.length+2];
+        Joins joins = null;
+
+        states[0] = _caseOperand.initialize(sel, ctx, 0);
+        if (joins == null)
+            joins = states[0].joins;
+        else
+            joins = sel.and(joins, states[0].joins);
+        for (int i = 0; i < _exp.length; i++) {
+            states[i+1] = _exp[i].initialize(sel, ctx, null);
+            if (joins == null)
+                joins = states[i+1].joins;
+            else
+                joins = sel.and(joins, states[i+1].joins);
+        }
+        states[_exp.length+1] = _val.initialize(sel, ctx, 0);
+        if (joins == null)
+            joins = states[_exp.length+1].joins;
+        else
+            joins = sel.and(joins, states[_exp.length+1].joins);
+        return new SimpleCaseExpState(joins, states);
+    }
+
+    private static class SimpleCaseExpState
+        extends ExpState {
+        
+        public ExpState[] states;
+        
+        public SimpleCaseExpState(Joins joins, ExpState[] states) {
+            super(joins);
+            this.states = states;
+        }
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state,
+        SQLBuffer buf, int index) {
+        SimpleCaseExpState cstate = (SimpleCaseExpState) state;
+
+        DBDictionary dict = ctx.store.getDBDictionary();
+
+        buf.append(" CASE ");
+
+        for (int i = 0; i < _exp.length; i++) {
+            // if back-end does not support simple case expression,
+            // pushdown sql as general case expression.
+
+            if (!dict.supportsSimpleCaseExpression)
+                buf.append(" WHEN ");
+
+            if (i == 0 || !dict.supportsSimpleCaseExpression)
+                _caseOperand.appendTo(sel, ctx, cstate.states[0], buf, 0);
+
+            if (!dict.supportsSimpleCaseExpression)
+                buf.append(" = ");
+            else
+                buf.append(" WHEN ");
+
+            _exp[i].appendTo(sel, ctx, cstate.states[i+1], buf);
+        }
+        buf.append(" ELSE ");
+        _val.appendTo(sel, ctx, cstate.states[_exp.length+1], buf, 0);
+
+        buf.append(" END ");
+    }
+
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state,
+        boolean pks) {
+        SimpleCaseExpState cstate = (SimpleCaseExpState) state;
+        
+        _caseOperand.selectColumns(sel, ctx, cstate.states[0], pks);
+        for (int i = 0; i < _exp.length; i++)
+            _exp[i].selectColumns(sel, ctx, cstate.states[i+1], pks);
+        _val.selectColumns(sel, ctx, cstate.states[_exp.length+1], pks);
+    }
+
+    public void acceptVisit(ExpressionVisitor visitor) {
+        visitor.enter(this);
+        _caseOperand.acceptVisit(visitor);
+        for (int i = 0; i < _exp.length; i++)
+            _exp[i].acceptVisit(visitor);
+        _val.acceptVisit(visitor);
+        visitor.exit(this);
+    }
+
+    public int getId() {
+        return Val.SIMPLECASE_VAL;
+    }
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state,
+        Val other, ExpState otherState) {
+        SimpleCaseExpState cstate = (SimpleCaseExpState) state;
+        _caseOperand.calculateValue(sel, ctx, cstate.states[0], other,
+            otherState);
+        for (int i = 0; i < _exp.length; i++) {
+            BinaryOpExpState bstate = (BinaryOpExpState) cstate.states[i+1];
+            ((WhenScalar) _exp[i]).getVal1().calculateValue(sel, ctx,
+                bstate.state1, null, null);
+            ((WhenScalar) _exp[i]).getVal2().calculateValue(sel, ctx,
+                bstate.state2, null, null);
+        }
+        _val.calculateValue(sel, ctx, cstate.states[_exp.length+1], other,
+            otherState);
+    }
+
+    public void groupBy(Select sel, ExpContext ctx, ExpState state) {
+        sel.groupBy(newSQLBuffer(sel, ctx, state));
+    }
+
+    public int length(Select sel, ExpContext ctx, ExpState state) {
+        return 1;
+    }
+
+    private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) {
+        calculateValue(sel, ctx, state, null, null);
+        SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
+        appendTo(sel, ctx, state, buf, 0);
+        return buf;
+    }
+
+    public Object load(ExpContext ctx, ExpState state, Result res)
+        throws SQLException {
+        return Filters.convert(res.getObject(this,
+            JavaSQLTypes.JDBC_DEFAULT, null), getType());
+    }
+
+    public void orderBy(Select sel, ExpContext ctx, ExpState state,
+        boolean asc) {
+        sel.orderBy(newSQLBuffer(sel, ctx, state), asc, false, getSelectAs());
+    }
+
+    public void select(Select sel, ExpContext ctx, ExpState state, boolean pks){
+        sel.select(newSQLBuffer(sel, ctx, state), this);
+    }
+
+    public ClassMetaData getMetaData() {
+        return _meta;
+    }
+
+    public void setImplicitType(Class type) {
+        _cast = type;        
+    }
+
+    public void setMetaData(ClassMetaData meta) {
+        _meta = meta;
+    }
+}
+

Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenCondition.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenCondition.java?rev=725728&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenCondition.java
(added)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenCondition.java
Thu Dec 11 08:16:32 2008
@@ -0,0 +1,94 @@
+/*
+ * 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.jdbc.kernel.exps;
+
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+
+/**
+ * Value produced by a when_clause of a case expression.
+ *
+ * @author Catalina Wei
+ */
+public class WhenCondition
+    implements Exp {
+
+    private final Exp _exp;
+    private final Val _val;
+
+    /**
+     * Constructor.
+     */
+    public WhenCondition(Exp exp, Val val) {
+        _exp = exp;
+        _val = val;
+    }
+
+    public Exp getExp() {
+        return _exp;
+    }
+
+    public Val getVal() {
+        return _val;
+    }
+
+    public Class getType() {
+        return _val.getType();
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) {
+        ExpState s1 = _exp.initialize(sel, ctx, contains);
+        ExpState s2 = _val.initialize(sel, ctx, 0);
+        return new BinaryOpExpState(sel.and(s1.joins, s2.joins), s1, s2);
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+
+        buf.append(" WHEN ");
+
+        _exp.appendTo(sel, ctx, bstate.state1, buf);
+        buf.append(" THEN ");
+        _val.appendTo(sel, ctx, bstate.state2, buf, 0);
+
+    }
+
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _exp.selectColumns(sel, ctx, bstate.state1, pks);
+        _val.selectColumns(sel, ctx, bstate.state2, pks);
+    }
+
+    public void acceptVisit(ExpressionVisitor visitor) {
+        visitor.enter(this);
+        _exp.acceptVisit(visitor);
+        _val.acceptVisit(visitor);
+        visitor.exit(this);
+    }
+
+    public int getId() {
+        return Val.WHENCONDITION_VAL;
+    }
+}
+

Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenScalar.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenScalar.java?rev=725728&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenScalar.java
(added)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/WhenScalar.java
Thu Dec 11 08:16:32 2008
@@ -0,0 +1,90 @@
+/*
+ * 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.jdbc.kernel.exps;
+
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+
+/**
+ * Value produced by a when_clause of a case expression.
+ *
+ * @author Catalina Wei
+ */
+public class WhenScalar
+    implements Exp {
+
+    private final Val _val1;
+    private final Val _val2;
+
+    /**
+     * Constructor.
+     */
+    public WhenScalar(Val val1, Val val2) {
+        _val1 = val1;
+        _val2 = val2;
+    }
+
+    public Val getVal1() {
+        return _val1;
+    }
+
+    public Val getVal2() {
+        return _val2;
+    }
+
+    public Class getType() {
+        return _val2.getType();
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, Map contains) {
+        ExpState s1 = _val1.initialize(sel, ctx, 0);
+        ExpState s2 = _val2.initialize(sel, ctx, 0);
+        return new BinaryOpExpState(sel.and(s1.joins, s2.joins), s1, s2);
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer buf) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val1.appendTo(sel, ctx, bstate.state1, buf, 0);
+        buf.append(" THEN ");
+        _val2.appendTo(sel, ctx, bstate.state2, buf, 0);
+    }
+
+    public void selectColumns(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        BinaryOpExpState bstate = (BinaryOpExpState) state;
+        _val1.selectColumns(sel, ctx, bstate.state1, pks);
+        _val2.selectColumns(sel, ctx, bstate.state2, pks);
+    }
+
+    public void acceptVisit(ExpressionVisitor visitor) {
+        visitor.enter(this);
+        _val1.acceptVisit(visitor);
+        _val2.acceptVisit(visitor);
+        visitor.exit(this);
+    }
+
+    public int getId() {
+        return Val.WHENSCALAR_VAL;
+    }
+}
+

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=725728&r1=725727&r2=725728&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
Thu Dec 11 08:16:32 2008
@@ -407,4 +407,25 @@
 	 * Return the object id of the given value.
 	 */
 	public Value getObjectId (Value val);
+
+    /**
+     * Return a simple case expression
+     */
+    public Value simpleCaseExpression(Value caseOperand,
+            Expression[] exp, Value val);
+
+    /**
+     * Return a general case expression
+     */
+    public Value generalCaseExpression(Expression[] exp, Value val);
+
+    /**
+     * Return a when condidional clause
+     */
+    public Expression whenCondition(Expression exp, Value val);
+
+    /**
+     * Return a when scalar_expression clause
+     */
+    public Expression whenScalar(Value val1, Value val2);
 }

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=725728&r1=725727&r2=725728&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
Thu Dec 11 08:16:32 2008
@@ -725,4 +725,24 @@
 			}
 		}
 	}
+
+    public Value generalCaseExpression(Expression[] exp, Value val) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Value simpleCaseExpression(Value caseOperand, Expression[] exp, Value val) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Expression whenCondition(Expression exp, Value val) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Expression whenScalar(Value val1, Value val2) {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }

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=725728&r1=725727&r2=725728&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
Thu Dec 11 08:16:32 2008
@@ -745,6 +745,27 @@
             case JJTSCALAREXPRESSION:
                 return eval(onlyChild(node));
 
+            case JJTTYPE:
+                return eval(onlyChild(node));
+
+            case JJTCLASSNAME:
+                return getPathOrConstant(node);
+
+            case JJTCASE:
+                return eval(onlyChild(node));
+
+            case JJTSCASE:
+                return getSimpleCaseExpression(node);
+
+            case JJTGCASE:
+                return getGeneralCaseExpression(node);
+
+            case JJTWHEN:
+                return getWhenCondition(node);
+
+            case JJTWHENSCALAR:
+                return getWhenScalar(node);
+
             case JJTWHERE: // top-level WHERE clause
                 return getExpression(onlyChild(node));
 
@@ -1439,6 +1460,48 @@
         return (Expression) exp;
     }
 
+    /**
+     * Returns a Simple Case Expression for the given node by eval'ing it.
+     */
+    private Value getSimpleCaseExpression(JPQLNode node) {
+        Object caseOperand = eval(node.getChild(0));
+        int nChild = node.getChildCount();
+
+        Object val = eval(lastChild(node));
+        Object exp[] = new Expression[nChild - 2];
+        for (int i = 1; i < nChild - 1; i++)
+            exp[i-1] = eval(node.children[i]);
+        
+        return factory.simpleCaseExpression((Value) caseOperand,
+            (Expression[]) exp, (Value) val);
+    }
+
+    /**
+     * Returns a General Case Expression for the given node by eval'ing it.
+     */
+    private Value getGeneralCaseExpression(JPQLNode node) {
+        int nChild = node.getChildCount();
+
+        Object val = eval(lastChild(node));
+        Object exp[] = new Expression[nChild - 1];
+        for (int i = 0; i < nChild - 1; i++)
+            exp[i] = (Expression) eval(node.children[i]);
+        
+        return factory.generalCaseExpression((Expression[]) exp, (Value) val);
+    }
+
+    private Expression getWhenCondition(JPQLNode node) {
+        Object exp = eval(firstChild(node));
+        Object val = eval(secondChild(node));
+        return factory.whenCondition((Expression) exp, (Value) val);
+    }
+
+    private Expression getWhenScalar(JPQLNode node) {
+        Object val1 = eval(firstChild(node));
+        Object val2 = eval(secondChild(node));
+        return factory.whenScalar((Value) val1, (Value) val2);
+    }
+
     private Value getValue(JPQLNode node) {
         return getValue(node, VAR_PATH);
     }

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java?rev=725728&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
Thu Dec 11 08:16:32 2008
@@ -0,0 +1,169 @@
+/*
+ * 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.jpql.expressions;
+
+import java.util.List;
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.common.apps.*;
+import org.apache.openjpa.persistence.common.utils.AbstractTestCase;
+
+public class TestJPQLScalarExpressions extends AbstractTestCase {
+
+    private int userid1, userid2, userid3, userid4, userid5, userid6;
+
+    public TestJPQLScalarExpressions(String name) {
+        super(name, "jpqlclausescactusapp");
+    }
+
+    public void setUp() {
+        deleteAll(CompUser.class);
+        EntityManager em = currentEntityManager();
+        startTx(em);
+
+        Address[] add = new Address[]{
+            new Address("43 Sansome", "SF", "United-Kingdom", "94104"),
+            new Address("24 Mink", "ANTIOCH", "USA", "94513"),
+            new Address("23 Ogbete", "CoalCamp", "NIGERIA", "00000"),
+            new Address("10 Wilshire", "Worcester", "CANADA", "80080"),
+            new Address("23 Bellflower", "Ogui", null, "02000"),
+            new Address("22 Montgomery", "SF", null, "50054") };
+
+        CompUser user1 = createUser("Seetha", "MAC", add[0], 36, true);
+        CompUser user2 = createUser("Shannon ", "PC", add[1], 36, false);
+        CompUser user3 = createUser("Ugo", "PC", add[2], 19, true);
+        CompUser user4 = createUser("_Jacob", "LINUX", add[3], 10, true);
+        CompUser user5 = createUser("Famzy", "UNIX", add[4], 29, false);
+        CompUser user6 = createUser("Shade", "UNIX", add[5], 23, false);
+
+        em.persist(user1);
+        userid1 = user1.getUserid();
+        em.persist(user2);
+        userid2 = user2.getUserid();
+        em.persist(user3);
+        userid3 = user3.getUserid();
+        em.persist(user4);
+        userid4 = user4.getUserid();
+        em.persist(user5);
+        userid5 = user5.getUserid();
+        em.persist(user6);
+        userid6 = user6.getUserid();
+
+        endTx(em);
+        endEm(em);
+    }
+
+    public void testSimpleCaseExpressions() {
+        EntityManager em = currentEntityManager();
+
+        CompUser user = em.find(CompUser.class, userid1);
+        assertNotNull("user is null", user);
+        assertEquals("the name is not seetha", "Seetha", user.getName());
+        String query = "SELECT e.name, e.age+1 as cage, " +
+            "CASE e.address.country WHEN 'USA'" +
+            " THEN 'us' " +
+            " ELSE 'non-us'  END as d2," +
+            " e.address.country " +
+            " FROM CompUser e ORDER BY cage, d2 DESC";
+        List rs = em.createQuery(query).getResultList();
+        Object[] result = (Object[]) rs.get(rs.size()-1);
+        assertEquals("the name is not seetha", "Seetha", result[0]);
+
+        String query2 = "SELECT e.name, e.age+1 as cage, " +
+            "CASE e.address.country WHEN 'USA'" +
+            " THEN 'United-States' " +
+            " ELSE e.address.country  END as d2," +
+            " e.address.country " +
+            " FROM CompUser e ORDER BY cage, d2 DESC";
+        List rs2 = em.createQuery(query2).getResultList();
+        Object[] result2 = (Object[]) rs2.get(rs2.size()-1);
+        assertEquals("the name is not seetha", "Seetha", result2[0]);
+
+        // TODO: needs entity-type-expression
+        String query3 = "SELECT e.name, " +
+            " CASE TYPE(e) WHEN FemaleUser THEN 'Female' " +
+            " ELSE 'Male' " +
+            " END " +
+            " FROM CompUser e";
+        endEm(em);
+    }
+
+    public void testGeneralCaseExpressions() {
+        EntityManager em = currentEntityManager();
+        startTx(em);
+
+        CompUser user = em.find(CompUser.class, userid1);
+        assertNotNull("user is null", user);
+        assertEquals("the name is not seetha", "Seetha", user.getName());
+
+        String query = "SELECT e.name, e.age, " +
+            " CASE WHEN e.age > 30 THEN e.age - 1 " +
+            " WHEN e.age < 15 THEN e.age + 1 " +
+            " ELSE e.age + 0 " +
+            " END AS cage " +
+            " FROM CompUser e ORDER BY cage";
+        
+        List rs = em.createQuery(query).getResultList();
+       
+
+        String update = "UPDATE CompUser e SET e.age = " +
+            "CASE WHEN e.age > 30 THEN e.age - 1 " +
+            "WHEN e.age < 15 THEN e.age + 1 " +
+            "ELSE e.age + 0 " +
+            "END";
+
+        int result = em.createQuery(update).executeUpdate();
+
+        assertEquals("the result is not 6", 6, result);
+        endTx(em);
+        endEm(em);
+    }
+
+    public void testMathFuncOrderByAlias() {
+        EntityManager em = currentEntityManager();
+
+        String query = "SELECT e.age * 2 as cAge FROM CompUser e ORDER BY cAge";
+
+        List result = em.createQuery(query).getResultList();
+
+        assertNotNull(result);
+        assertEquals(6, result.size());
+
+        endEm(em);
+    }
+
+    public CompUser createUser(String name, String cName, Address add, int age,
+        boolean isMale) {
+        CompUser user = null;
+        if (isMale) {
+            user = new MaleUser();
+            user.setName(name);
+            user.setComputerName(cName);
+            user.setAddress(add);
+            user.setAge(age);
+        } else {
+            user = new FemaleUser();
+            user.setName(name);
+            user.setComputerName(cName);
+            user.setAddress(add);
+            user.setAge(age);
+        }
+        return user;
+    }
+}



Mime
View raw message