![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.mongodb_jdbc_driver.zql.data.ZEval Maven / Gradle / Ivy
The newest version!
/*
* This file is part of Zql.
*
* Zql is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Zql is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Zql. If not, see .
*/
package net.sf.mongodb_jdbc_driver.zql.data;
import java.sql.SQLException;
import java.util.Vector;
import java.io.*;
import net.sf.mongodb_jdbc_driver.zql.*;
/**
* Evaluate SQL expressions
*/
public class ZEval {
/**
* Evaluate a boolean expression to true or false (for example, SQL WHERE
* clauses are boolean expressions)
* @param tuple The tuple on which to evaluate the expression
* @param exp The expression to evaluate
* @return true if the expression evaluate to true for this tuple,
* false if not.
*/
public boolean eval(ZTuple tuple, ZExp exp) throws SQLException {
if(tuple == null || exp == null) {
throw new SQLException("ZEval.eval(): null argument or operator");
}
if(! (exp instanceof ZExpression))
throw new SQLException("ZEval.eval(): only expressions are supported");
ZExpression pred = (ZExpression)exp;
String op = pred.getOperator();
if(op.equals("AND")) {
boolean and = true;
for(int i = 0; i")) {
return evalCmp(tuple, pred.getOperands()) != 0;
} else if(op.equals("#")) {
throw new SQLException("ZEval.eval(): Operator # not supported");
} else if(op.equals(">")) {
return evalCmp(tuple, pred.getOperands()) > 0;
} else if(op.equals(">=")) {
return evalCmp(tuple, pred.getOperands()) >= 0;
} else if(op.equals("<")) {
return evalCmp(tuple, pred.getOperands()) < 0;
} else if(op.equals("<=")) {
return evalCmp(tuple, pred.getOperands()) <= 0;
} else if(op.equals("BETWEEN") || op.equals("NOT BETWEEN")) {
// Between: borders included
ZExpression newexp = new ZExpression("AND",
new ZExpression(">=", pred.getOperand(0), pred.getOperand(1)),
new ZExpression("<=", pred.getOperand(0), pred.getOperand(2)));
if(op.equals("NOT BETWEEN"))
return ! eval(tuple, newexp);
else
return eval(tuple, newexp);
} else if(op.equals("LIKE") || op.equals("NOT LIKE")) {
boolean like = evalLike(tuple, pred.getOperands());
return op.equals("LIKE") ? like : !like;
} else if(op.equals("IN") || op.equals("NOT IN")) {
ZExpression newexp = new ZExpression("OR");
for(int i = 1; i < pred.nbOperands(); i++) {
newexp.addOperand(new ZExpression("=",
pred.getOperand(0), pred.getOperand(i)));
}
if(op.equals("NOT IN"))
return ! eval(tuple, newexp);
else
return eval(tuple, newexp);
} else if(op.equals("IS NULL")) {
if(pred.nbOperands() <= 0 || pred.getOperand(0) == null) return true;
ZExp x = pred.getOperand(0);
if(x instanceof ZConstant) {
return (((ZConstant)x).getType() == ZConstant.NULL);
} else {
throw new SQLException("ZEval.eval(): can't eval IS (NOT) NULL");
}
} else if(op.equals("IS NOT NULL")) {
ZExpression x = new ZExpression("IS NULL");
x.setOperands(pred.getOperands());
return ! eval(tuple, x);
} else {
throw new SQLException("ZEval.eval(): Unknown operator " + op);
}
}
double evalCmp(ZTuple tuple, Vector operands) throws SQLException {
if(operands.size() < 2) {
throw new SQLException(
"ZEval.evalCmp(): Trying to compare less than two values");
}
if(operands.size() > 2) {
throw new SQLException(
"ZEval.evalCmp(): Trying to compare more than two values");
}
Object o1 = null, o2 = null, obj;
o1 = evalExpValue(tuple, (ZExp)operands.elementAt(0));
o2 = evalExpValue(tuple, (ZExp)operands.elementAt(1));
if(o1 instanceof String || o2 instanceof String) {
return(o1.equals(o2) ? 0 : -1);
}
if(o1 instanceof Number && o2 instanceof Number) {
return ((Number)o1).doubleValue() - ((Number)o2).doubleValue();
} else {
throw new SQLException("ZEval.evalCmp(): can't compare (" + o1.toString()
+ ") with (" + o2.toString() + ")");
}
}
// -------------------------------------------------------------------------
/**
* evalLike
* evaluates the LIKE operand
*
* @param tuple the tuple to evaluate
* @param operands the operands
* @return true-> the expression matches
* @throws SQLException
*/
private boolean evalLike(ZTuple tuple, Vector operands) throws SQLException
{
if(operands.size() < 2) {
throw new SQLException(
"ZEval.evalCmp(): Trying to compare less than two values");
}
if(operands.size() > 2) {
throw new SQLException(
"ZEval.evalCmp(): Trying to compare more than two values");
}
Object o1 = evalExpValue(tuple, (ZExp)operands.elementAt(0));
Object o2 = evalExpValue(tuple, (ZExp)operands.elementAt(1));
if ( (o1 instanceof String) && (o2 instanceof String) ) {
String s1 = (String)o1;
String s2 = (String)o2;
if ( s2.startsWith("%") ) {
return s1.endsWith(s2.substring(1));
} else if ( s2.endsWith("%") ) {
return s1.startsWith(s2.substring(0,s2.length()-1));
} else {
return s1.equalsIgnoreCase(s2);
}
}
else {
throw new SQLException("ZEval.evalLike(): LIKE can only compare strings");
}
}
double evalNumericExp(ZTuple tuple, ZExpression exp)
throws SQLException {
if(tuple == null || exp == null || exp.getOperator() == null) {
throw new SQLException("ZEval.eval(): null argument or operator");
}
String op = exp.getOperator();
Object o1 = evalExpValue(tuple, (ZExp)exp.getOperand(0));
if(! (o1 instanceof Double))
throw new SQLException("ZEval.evalNumericExp(): expression not numeric");
Double dobj = (Double)o1;
if(op.equals("+")) {
double val = dobj.doubleValue();
for(int i = 1; i < exp.nbOperands(); i++) {
Object obj = evalExpValue(tuple, (ZExp)exp.getOperand(i));
val += ((Number)obj).doubleValue();
}
return val;
} else if(op.equals("-")) {
double val = dobj.doubleValue();
if(exp.nbOperands() == 1) return -val;
for(int i = 1; i < exp.nbOperands(); i++) {
Object obj = evalExpValue(tuple, (ZExp)exp.getOperand(i));
val -= ((Number)obj).doubleValue();
}
return val;
} else if(op.equals("*")) {
double val = dobj.doubleValue();
for(int i = 1; i < exp.nbOperands(); i++) {
Object obj = evalExpValue(tuple, (ZExp)exp.getOperand(i));
val *= ((Number)obj).doubleValue();
}
return val;
} else if(op.equals("/")) {
double val = dobj.doubleValue();
for(int i = 1; i < exp.nbOperands(); i++) {
Object obj = evalExpValue(tuple, (ZExp)exp.getOperand(i));
val /= ((Number)obj).doubleValue();
}
return val;
} else if(op.equals("**")) {
double val = dobj.doubleValue();
for(int i = 1; i < exp.nbOperands(); i++) {
Object obj = evalExpValue(tuple, (ZExp)exp.getOperand(i));
val = Math.pow(val, ((Number)obj).doubleValue());
}
return val;
} else {
throw new SQLException("ZEval.evalNumericExp(): Unknown operator " + op);
}
}
/**
* Evaluate a numeric or string expression (example: a+1)
* @param tuple The tuple on which to evaluate the expression
* @param exp The expression to evaluate
* @return The expression's value
*/
public Object evalExpValue(ZTuple tuple, ZExp exp) throws SQLException {
Object o2 = null;
if(exp instanceof ZConstant) {
ZConstant c = (ZConstant)exp;
switch(c.getType()) {
case ZConstant.COLUMNNAME:
Object o1 = tuple.getAttValue(c.getValue());
if(o1 == null)
throw new SQLException("ZEval.evalExpValue(): unknown column "
+ c.getValue());
try {
o2 = new Double(o1.toString());
} catch(NumberFormatException e) {
o2 = o1;
}
break;
case ZConstant.NUMBER:
o2 = new Double(c.getValue());
break;
case ZConstant.STRING:
default:
o2 = c.getValue();
break;
}
} else if(exp instanceof ZExpression) {
o2 = new Double(evalNumericExp(tuple, (ZExpression)exp));
}
return o2;
}
// test
public static void main(String args[]) {
try {
BufferedReader db = new BufferedReader(new FileReader("test.db"));
String tpl = db.readLine();
ZTuple t = new ZTuple(tpl);
ZqlParser parser = new ZqlParser();
ZEval evaluator = new ZEval();
while((tpl = db.readLine()) != null) {
t.setRow(tpl);
BufferedReader sql = new BufferedReader(new FileReader("test.sql"));
String query;
while((query = sql.readLine()) != null) {
parser.initParser(new ByteArrayInputStream(query.getBytes()));
ZExp exp = parser.readExpression();
System.out.print(tpl + ", " + query + ", ");
System.out.println(evaluator.eval(t, exp));
}
sql.close();
}
db.close();
} catch(Exception e) {
e.printStackTrace();
}
}
};
© 2015 - 2025 Weber Informatics LLC | Privacy Policy