001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.query.model;
017:
018: import java.sql.PreparedStatement;
019: import java.sql.SQLException;
020:
021: import org.outerj.daisy.query.EvaluationInfo;
022: import org.outerj.daisy.query.QueryContext;
023: import org.outerj.daisy.repository.query.QueryException;
024:
025: public class Between extends AbstractPredicateExpr {
026: private final ValueExpr testValueExpr;
027: private final ValueExpr valueExpr1;
028: private final ValueExpr valueExpr2;
029: private final boolean not;
030: private QValueType valueType;
031:
032: public Between(boolean not, ValueExpr testValueExpr,
033: ValueExpr valueExpr1, ValueExpr valueExpr2) {
034: this .testValueExpr = testValueExpr;
035: this .valueExpr1 = valueExpr1;
036: this .valueExpr2 = valueExpr2;
037: this .not = not;
038: }
039:
040: public void prepare(QueryContext context) throws QueryException {
041: testValueExpr.prepare(context);
042: if (!ValueExprUtil.isComparable(testValueExpr))
043: throw new QueryException(
044: "A non-comparable identifier cannot be used with BETWEEN.");
045:
046: valueExpr1.prepare(context);
047: valueExpr2.prepare(context);
048:
049: if (!isExprOkForComparison(valueExpr1, testValueExpr
050: .getValueType()))
051: throw new QueryException(
052: "BETWEEN used with an expression whose type does not correspond to the value being tested: "
053: + valueExpr1.getExpression());
054: if (!isExprOkForComparison(valueExpr2, testValueExpr
055: .getValueType()))
056: throw new QueryException(
057: "BETWEEN used with an expression whose type does not correspond to the value being tested: "
058: + valueExpr2.getExpression());
059:
060: this .valueType = testValueExpr.getValueType();
061: }
062:
063: private boolean isExprOkForComparison(ValueExpr expr,
064: QValueType testExprType) {
065: return ValueExprUtil.isPrimitiveValue(expr)
066: && (testExprType.isCompatible(expr.getValueType()));
067: }
068:
069: public boolean evaluate(ExprDocData data,
070: EvaluationInfo evaluationInfo) throws QueryException {
071: Comparable testValue = (Comparable) testValueExpr.evaluate(
072: valueType, data, evaluationInfo);
073:
074: if (testValue == null)
075: return false;
076:
077: Object value1 = valueExpr1.evaluate(valueType, data,
078: evaluationInfo);
079: Object value2 = valueExpr2.evaluate(valueType, data,
080: evaluationInfo);
081:
082: return evaluate(testValue, value1, value2);
083: }
084:
085: private boolean evaluate(Comparable testValue, Object value1,
086: Object value2) throws QueryException {
087: boolean result = testValue.compareTo(value1) >= 0
088: && testValue.compareTo(value2) <= 0;
089: return not ? !result : result;
090: }
091:
092: public AclConditionViolation isAclAllowed() {
093: return testValueExpr.isAclAllowed();
094: }
095:
096: public Tristate appliesTo(ExprDocData data,
097: EvaluationInfo evaluationInfo) throws QueryException {
098: return Tristate.MAYBE;
099: }
100:
101: public void generateSql(StringBuilder sql,
102: SqlGenerationContext context) throws QueryException {
103: sql.append(" (");
104:
105: String preCond = testValueExpr.getSqlPreConditions(context);
106: if (preCond != null)
107: sql.append(preCond).append(" and ");
108:
109: String valueExpr1PreCond = valueExpr1
110: .getSqlPreConditions(context);
111: if (valueExpr1PreCond != null)
112: sql.append(valueExpr1PreCond).append(" and ");
113:
114: String valueExpr2PreCond = valueExpr2
115: .getSqlPreConditions(context);
116: if (valueExpr2PreCond != null)
117: sql.append(valueExpr2PreCond).append(" and ");
118:
119: testValueExpr.generateSqlValueExpr(sql, context);
120: sql.append(" BETWEEN ");
121: valueExpr1.generateSqlValueExpr(sql, context);
122: sql.append(" AND ");
123: valueExpr2.generateSqlValueExpr(sql, context);
124: sql.append(" ) ");
125: }
126:
127: public int bindSql(PreparedStatement stmt, int bindPos,
128: EvaluationInfo evaluationInfo) throws SQLException,
129: QueryException {
130: bindPos = testValueExpr.bindPreConditions(stmt, bindPos,
131: evaluationInfo);
132: bindPos = valueExpr1.bindPreConditions(stmt, bindPos,
133: evaluationInfo);
134: bindPos = valueExpr2.bindPreConditions(stmt, bindPos,
135: evaluationInfo);
136: bindPos = testValueExpr.bindValueExpr(stmt, bindPos, valueType,
137: evaluationInfo);
138: bindPos = valueExpr1.bindValueExpr(stmt, bindPos, valueType,
139: evaluationInfo);
140: bindPos = valueExpr2.bindValueExpr(stmt, bindPos, valueType,
141: evaluationInfo);
142: return bindPos;
143: }
144:
145: public void collectAccessRestrictions(
146: AccessRestrictions restrictions) {
147: testValueExpr.collectAccessRestrictions(restrictions);
148: valueExpr1.collectAccessRestrictions(restrictions);
149: valueExpr2.collectAccessRestrictions(restrictions);
150: }
151: }
|