blob: 57c2ed717baa6a9ea947d72904a3506c3d910cd1 [file] [log] [blame]
/*
* 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 org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.kernel.exps.AggregateListener;
import org.apache.openjpa.kernel.exps.Arguments;
import org.apache.openjpa.kernel.exps.Expression;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.FilterListener;
import org.apache.openjpa.kernel.exps.Literal;
import org.apache.openjpa.kernel.exps.Parameter;
import org.apache.openjpa.kernel.exps.Path;
import org.apache.openjpa.kernel.exps.Subquery;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.util.UserException;
/**
* Expression factory implementation that can be used to execute queries
* via SQL.
*
* @author Abe White
* @nojavadoc
*/
public class JDBCExpressionFactory
implements ExpressionFactory {
private static final Val NULL = new Null();
private static final Val CURRENT_DATE = new CurrentDate(JavaSQLTypes.DATE);
private static final Val CURRENT_TIME = new CurrentDate(JavaSQLTypes.TIME);
private static final Val CURRENT_TIMESTAMP =
new CurrentDate(JavaSQLTypes.TIMESTAMP);
private static final Localizer _loc = Localizer.forPackage
(JDBCExpressionFactory.class);
private final ClassMapping _type;
private final SelectConstructor _cons = new SelectConstructor();
/**
* Constructor. Supply the type we're querying against.
*/
public JDBCExpressionFactory(ClassMapping type) {
_type = type;
}
/**
* Use to create SQL select.
*/
public SelectConstructor getSelectConstructor() {
return _cons;
}
public Expression emptyExpression() {
return new EmptyExpression();
}
public Expression asExpression(Value v) {
return equal(v, newLiteral(Boolean.TRUE, Literal.TYPE_BOOLEAN));
}
public Expression equal(Value v1, Value v2) {
// if we're comparing an unaccessed bound variable, like in:
// coll.contains (var) && var == x, then translate into:
// coll.contains (x)
if (v1 instanceof PCPath && ((PCPath) v1).isUnaccessedVariable())
return contains(v1, v2);
if (v2 instanceof PCPath && ((PCPath) v2).isUnaccessedVariable())
return contains(v2, v1);
return new EqualExpression((Val) v1, (Val) v2);
}
public Expression notEqual(Value v1, Value v2) {
return new NotEqualExpression((Val) v1, (Val) v2);
}
public Expression lessThan(Value v1, Value v2) {
return new CompareExpression((Val) v1, (Val) v2,
CompareExpression.LESS);
}
public Expression greaterThan(Value v1, Value v2) {
return new CompareExpression((Val) v1, (Val) v2,
CompareExpression.GREATER);
}
public Expression lessThanEqual(Value v1, Value v2) {
return new CompareExpression((Val) v1, (Val) v2,
CompareExpression.LESS_EQUAL);
}
public Expression greaterThanEqual(Value v1, Value v2) {
return new CompareExpression((Val) v1, (Val) v2,
CompareExpression.GREATER_EQUAL);
}
public Expression isEmpty(Value val) {
return new IsEmptyExpression((Val) val);
}
public Expression isNotEmpty(Value val) {
return new IsNotEmptyExpression((Val) val);
}
public Expression contains(Value map, Value arg) {
if (map instanceof Const)
return new InExpression((Val) arg, (Const) map);
if (map instanceof SubQ)
return new InSubQExpression((Val) arg, (SubQ) map);
return new ContainsExpression((Val) map, (Val) arg);
}
public Expression containsKey(Value map, Value arg) {
if (map instanceof Const)
return new InKeyExpression((Val) arg, (Const) map);
return new ContainsKeyExpression((Val) map, (Val) arg);
}
public Expression containsValue(Value map, Value arg) {
if (map instanceof Const)
return new InValueExpression((Val) arg, (Const) map);
return new ContainsExpression((Val) map, (Val) arg);
}
public Expression isInstance(Value val, Class c) {
if (val instanceof Const)
return new ConstInstanceofExpression((Const) val, c);
return new InstanceofExpression((PCPath) val, c);
}
public Expression and(Expression exp1, Expression exp2) {
if (exp1 instanceof BindVariableExpression)
return new BindVariableAndExpression((BindVariableExpression) exp1,
(Exp) exp2);
if (exp2 instanceof BindVariableExpression)
return new BindVariableAndExpression((BindVariableExpression) exp2,
(Exp) exp1);
return new AndExpression((Exp) exp1, (Exp) exp2);
}
public Expression or(Expression exp1, Expression exp2) {
return new OrExpression((Exp) exp1, (Exp) exp2);
}
public Expression not(Expression exp) {
if (HasContainsExpressionVisitor.hasContains(exp))
return new NotContainsExpression((Exp) exp);
return new NotExpression((Exp) exp);
}
public Expression bindVariable(Value var, Value val) {
// handle the strange case of using a constant path to bind a
// variable; in these cases the variable acts like an unbound
// variable that we limit by using an IN clause on the constant
// value collection
if (val instanceof Const) {
PCPath path = new PCPath(_type, (Variable) var);
path.setMetaData(var.getMetaData());
return new InExpression(path, (Const) val);
}
return new BindVariableExpression((Variable) var, (PCPath) val, false);
}
public Expression bindKeyVariable(Value var, Value val) {
// handle the strange case of using a constant path to bind a
// variable; in these cases the variable acts like an unbound
// variable that we limit by using an IN clause on the constant
// value collection
if (val instanceof Const) {
PCPath path = new PCPath(_type, (Variable) var);
path.setMetaData(var.getMetaData());
return new InKeyExpression(path, (Const) val);
}
return new BindVariableExpression((Variable) var, (PCPath) val, true);
}
public Expression bindValueVariable(Value var, Value val) {
return bindVariable(var, val);
}
public Expression startsWith(Value v1, Value v2) {
return new StartsWithExpression((Val) v1, (Val) v2);
}
public Expression endsWith(Value v1, Value v2) {
return new EndsWithExpression((Val) v1, (Val) v2);
}
public Expression notMatches(Value v1, Value v2,
String single, String multi, String esc) {
return not(matches(v1, v2, single, multi, esc));
}
public Expression matches(Value v1, Value v2,
String single, String multi, String esc) {
if (!(v2 instanceof Const))
throw new UserException(_loc.get("const-only", "matches"));
return new MatchesExpression((Val) v1, (Const) v2, single, multi,
esc != null ? esc : _type.getMappingRepository().
getDBDictionary().searchStringEscape);
}
public Subquery newSubquery(ClassMetaData candidate, boolean subs,
String alias) {
DBDictionary dict = _type.getMappingRepository().getDBDictionary();
dict.assertSupport(dict.supportsSubselect, "SupportsSubselect");
return new SubQ((ClassMapping) candidate, subs, alias);
}
public Path newPath() {
return new PCPath(_type);
}
public Path newPath(Value val) {
if (val instanceof Const)
return new ConstPath((Const) val);
if (val instanceof SubQ)
return new PCPath((SubQ) val);
return new PCPath(_type, (Variable) val);
}
public Literal newLiteral(Object val, int ptype) {
return new Lit(val, ptype);
}
public Value getThis() {
return new PCPath(_type);
}
public Value getNull() {
return NULL;
}
public Value getCurrentDate() {
return CURRENT_DATE;
}
public Value getCurrentTime() {
return CURRENT_TIME;
}
public Value getCurrentTimestamp() {
return CURRENT_TIMESTAMP;
}
public Parameter newParameter(String name, Class type) {
return new Param(name, type);
}
public Value newExtension(FilterListener listener, Value target,
Value arg) {
return new Extension((JDBCFilterListener) listener,
(Val) target, (Val) arg, _type);
}
public Value newAggregate(AggregateListener listener, Value arg) {
return new Aggregate((JDBCAggregateListener) listener,
(Val) arg, _type);
}
public Arguments newArgumentList(Value v1, Value v2) {
return new Args((Val) v1, (Val) v2);
}
public Value newUnboundVariable(String name, Class type) {
return new Variable(name, type);
}
public Value newBoundVariable(String name, Class type) {
return newUnboundVariable(name, type);
}
public Value cast(Value val, Class cls) {
val.setImplicitType(cls);
return val;
}
public Value add(Value v1, Value v2) {
return new Math((Val) v1, (Val) v2, Math.ADD);
}
public Value subtract(Value v1, Value v2) {
return new Math((Val) v1, (Val) v2, Math.SUBTRACT);
}
public Value multiply(Value v1, Value v2) {
return new Math((Val) v1, (Val) v2, Math.MULTIPLY);
}
public Value divide(Value v1, Value v2) {
return new Math((Val) v1, (Val) v2, Math.DIVIDE);
}
public Value mod(Value v1, Value v2) {
return new Math((Val) v1, (Val) v2, Math.MOD);
}
public Value abs(Value val) {
return new Abs((Val) val);
}
public Value indexOf(Value v1, Value v2) {
return new IndexOf((Val) v1, (Val) v2);
}
public Value concat(Value v1, Value v2) {
return new Concat((Val) v1, (Val) v2);
}
public Value stringLength(Value str) {
return new StringLength((Val) str);
}
public Value trim(Value str, Value trimChar, Boolean where) {
return new Trim((Val) str, (Val) trimChar, where);
}
public Value sqrt(Value val) {
return new Sqrt((Val) val);
}
public Value substring(Value v1, Value v2) {
return new Substring((Val) v1, (Val) v2);
}
public Value toUpperCase(Value val) {
return new ToUpperCase((Val) val);
}
public Value toLowerCase(Value val) {
return new ToLowerCase((Val) val);
}
public Value avg(Value val) {
return new Avg((Val) val);
}
public Value count(Value val) {
return new Count((Val) val);
}
public Value distinct(Value val) {
return new Distinct((Val) val);
}
public Value max(Value val) {
return new Max((Val) val);
}
public Value min(Value val) {
return new Min((Val) val);
}
public Value sum(Value val) {
return new Sum((Val) val);
}
public Value any(Value val) {
return new Any((Val) val);
}
public Value all(Value val) {
return new All((Val) val);
}
public Value size(Value val) {
return new Size((Val) val);
}
public Value getObjectId(Value val) {
if (val instanceof Const)
return new ConstGetObjectId((Const) val);
return new GetObjectId((PCPath) val);
}
public Value getMapValue(Value map, Value arg) {
return new GetMapValue((Val) map, (Val) arg);
}
}