ru.curs.celesta.score.Expr Maven / Gradle / Ivy
The newest version!
package ru.curs.celesta.score;
import ru.curs.celesta.dbutils.QueryBuildingHelper;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Scalar SQL expression.
*/
public abstract class Expr {
final void assertType(ViewColumnType t) throws ParseException {
// INT and REAL are both numeric types, so they are comparable
final ViewColumnType columnType = getMeta().getColumnType();
if (t == ViewColumnType.INT || t == ViewColumnType.REAL || t == ViewColumnType.DECIMAL) {
if (!(columnType == ViewColumnType.INT || columnType == ViewColumnType.REAL
|| columnType == ViewColumnType.DECIMAL)) {
throw new ParseException(
String.format("Expression '%s' is expected to be of numeric type, but it is %s", getCSQL(),
getMeta().getColumnType().getCelestaType()));
}
} else {
if (columnType != t) {
throw new ParseException(String.format("Expression '%s' is expected to be of %s type, but it is %s",
getCSQL(), t.toString(), getMeta().getColumnType().getCelestaType()));
}
}
}
/**
* Returns a Celesta-SQL view of the expression.
*
* @return
*/
public final String getCSQL() {
SQLGenerator gen = new SQLGenerator();
return gen.generateSQL(this);
}
/**
* Returns an SQL view of the expression in dialect of current DB.
*
* @param dba DB adapter.
* @return
*/
public final String getSQL(QueryBuildingHelper dba) {
SQLGenerator gen = dba.getViewSQLGenerator();
return gen.generateSQL(this);
}
/**
* Returns the expression type.
*
* @return
*/
public abstract ViewColumnMeta> getMeta();
/**
* Resolves references to the fields of tables using the context of the defined
* tables with their aliases.
*
* @param tables list of tables.
* @throws ParseException in case if a reference can't be resolved
*/
final void resolveFieldRefs(List tables) throws ParseException {
FieldResolver r = new FieldResolver(tables);
accept(r);
}
/**
* Resolves references to the fields of tables using the context of current
* object of the score.
*
* @param ge table or view
* @throws ParseException in case if a reference can't be resolved
*/
public final void resolveFieldRefs(GrainElement ge) throws ParseException {
if (ge instanceof DataGrainElement) {
FilterFieldResolver fr = new FilterFieldResolver((DataGrainElement) ge);
accept(fr);
}
}
final ParameterResolverResult resolveParameterRefs(Map parameters) throws ParseException {
ParameterResolver r = new ParameterResolver(parameters);
accept(r);
return r.getResult();
}
/**
* Validates the types of all subexpressions in the expression.
*
* @throws ParseException in case if types check fails.
*/
final void validateTypes() throws ParseException {
TypeChecker c = new TypeChecker();
accept(c);
}
/**
* Accepts a visitor during a traversal of the parse tree for solving tasks of
* types validation, code generation etc.
*
* @param visitor universal visitor element performing tasks with the parse tree.
* @throws ParseException semantic error during the tree traversal
*/
abstract void accept(ExprVisitor visitor) throws ParseException;
}
/**
* Expression in parentheses.
*/
final class ParenthesizedExpr extends Expr {
private final Expr parenthesized;
ParenthesizedExpr(Expr parenthesized) {
this.parenthesized = parenthesized;
}
/**
* Returns the expression encompassed by parentheses.
*
* @return
*/
public Expr getParenthesized() {
return parenthesized;
}
@Override
public ViewColumnMeta> getMeta() {
return parenthesized.getMeta();
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
parenthesized.accept(visitor);
visitor.visitParenthesizedExpr(this);
}
}
/**
* ... IN (..., ..., ...).
*/
final class In extends LogicValuedExpr {
private final Expr left;
private final List operands;
In(Expr left, List operands) {
this.operands = operands;
this.left = left;
}
/**
* Returns the operator.
*
* @return
*/
public Expr getLeft() {
return left;
}
/**
* Returns the operands.
*
* @return
*/
public List getOperands() {
return operands;
}
@Override
public List getAllOperands() {
return Stream.of(Collections.singletonList(left), this.getOperands())
.flatMap(List::stream)
.collect(Collectors.toList());
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
left.accept(visitor);
for (Expr operand : operands) {
operand.accept(visitor);
}
visitor.visitIn(this);
}
}
/**
* BETWEEN.
*/
final class Between extends LogicValuedExpr {
private final Expr left;
private final Expr right1;
private final Expr right2;
Between(Expr left, Expr right1, Expr right2) {
this.left = left;
this.right1 = right1;
this.right2 = right2;
}
/**
* Returns the left part.
*
* @return
*/
public Expr getLeft() {
return left;
}
/**
* Returns the part from....
*
* @return
*/
public Expr getRight1() {
return right1;
}
/**
* Returns the part to....
*
* @return
*/
public Expr getRight2() {
return right2;
}
@Override
public List getAllOperands() {
return Arrays.asList(this.getLeft(), this.getRight1(), this.getRight2());
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
left.accept(visitor);
right1.accept(visitor);
right2.accept(visitor);
visitor.visitBetween(this);
}
}
/**
* IS NULL.
*/
final class IsNull extends LogicValuedExpr {
private final Expr expr;
IsNull(Expr expr) throws ParseException {
if (expr.getMeta().getColumnType() == ViewColumnType.LOGIC) {
throw new ParseException(String.format(
"Expression '%s' is logical condition and cannot be an argument of IS NULL operator.", getCSQL()));
}
this.expr = expr;
}
/**
* The expression that IS NULL is taken from.
*
* @return
*/
public Expr getExpr() {
return expr;
}
@Override
public List getAllOperands() {
return Collections.singletonList(this.getExpr());
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
expr.accept(visitor);
visitor.visitIsNull(this);
}
}
/**
* NOT.
*/
final class NotExpr extends LogicValuedExpr {
private final Expr expr;
NotExpr(Expr expr) {
this.expr = expr;
}
/**
* The expression that NOT is taken from.
*
* @return
*/
public Expr getExpr() {
return expr;
}
@Override
public List getAllOperands() {
return Collections.singletonList(getExpr());
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
expr.accept(visitor);
visitor.visitNotExpr(this);
}
}
/**
* Unary minus.
*/
final class UnaryMinus extends Expr {
private final Expr arg;
UnaryMinus(Expr arg) {
this.arg = arg;
}
public Expr getExpr() {
return arg;
}
@Override
public ViewColumnMeta> getMeta() {
// Real or Integer
return arg.getMeta();
}
@Override
public void accept(ExprVisitor visitor) throws ParseException {
arg.accept(visitor);
visitor.visitUnaryMinus(this);
}
}
/**
* UPPER(..) operation.
*/
final class Upper extends Expr {
private final Expr arg;
Upper(Expr arg) {
this.arg = arg;
}
@Override
public ViewColumnMeta> getMeta() {
return new ViewColumnMeta<>(ViewColumnType.TEXT);
}
@Override
void accept(ExprVisitor visitor) throws ParseException {
arg.accept(visitor);
visitor.visitUpper(this);
}
public Expr getArg() {
return arg;
}
}
/**
* LOWER(..) operation.
*/
final class Lower extends Expr {
private final Expr arg;
Lower(Expr arg) {
this.arg = arg;
}
@Override
public ViewColumnMeta> getMeta() {
return new ViewColumnMeta<>(ViewColumnType.TEXT);
}
@Override
void accept(ExprVisitor visitor) throws ParseException {
arg.accept(visitor);
visitor.visitLower(this);
}
public Expr getArg() {
return arg;
}
}
/**
* Base class for literal expressions.
*/
abstract class Literal extends Expr {
private final ViewColumnType type;
private ViewColumnMeta> meta;
Literal(ViewColumnType type) {
this.type = type;
}
@Override
public final ViewColumnMeta> getMeta() {
if (meta == null) {
meta = new ViewColumnMeta<>(type);
meta.setNullable(false);
}
return meta;
}
}
/**
* Numeric numeral with a floating point.
*/
final class RealLiteral extends Literal {
private final String lexValue;
RealLiteral(String lexValue) {
super(ViewColumnType.REAL);
this.lexValue = lexValue;
}
/**
* Returns the lexical value.
*
* @return
*/
public String getLexValue() {
return lexValue;
}
@Override
public void accept(ExprVisitor visitor) {
visitor.visitRealLiteral(this);
}
}
/**
* Numeric numeral.
*/
final class IntegerLiteral extends Literal {
private final String lexValue;
IntegerLiteral(String lexValue) {
super(ViewColumnType.INT);
this.lexValue = lexValue;
}
/**
* Returns the lexical value.
*
* @return
*/
public String getLexValue() {
return lexValue;
}
@Override
public void accept(ExprVisitor visitor) {
visitor.visitIntegerLiteral(this);
}
}
/**
* {@code TRUE} or {@code FALSE} literal.
*/
final class BooleanLiteral extends Literal {
private final boolean val;
BooleanLiteral(boolean val) {
super(ViewColumnType.BIT);
this.val = val;
}
@Override
public void accept(ExprVisitor visitor) {
visitor.visitBooleanLiteral(this);
}
public boolean getValue() {
return val;
}
}
/**
* Text literal.
*/
final class TextLiteral extends Literal {
private final String lexValue;
TextLiteral(String lexValue) {
super(ViewColumnType.TEXT);
this.lexValue = lexValue;
}
/**
* Returns the lexical value.
*
* @return
*/
public String getLexValue() {
return lexValue;
}
@Override
public void accept(ExprVisitor visitor) {
visitor.visitTextLiteral(this);
}
}
final class GetDate extends Expr {
@Override
public ViewColumnMeta> getMeta() {
return new ViewColumnMeta<>(ViewColumnType.DATE);
}
@Override
void accept(ExprVisitor visitor) {
visitor.visitGetDate(this);
}
}
abstract class Aggregate extends Expr {
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy