All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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