diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java index fc7d7d466..b5866bb1a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java @@ -19,9 +19,8 @@ /** * Analytic function. The name of the function is variable but the parameters following the special - * analytic function path. e.g. row_number() over (order by test). Additional there can be an - * expression for an analytical aggregate like sum(col) or the "all collumns" wildcard like - * count(*). + * analytic function path. e.g. row_number() over (order by test). Additionally, there can be an + * expression for an analytical aggregate like sum(col) or the "all columns" wildcard like count(*). * * @author tw */ diff --git a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java index 848783206..8216a8cb8 100644 --- a/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/BinaryExpression.java @@ -9,8 +9,15 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.arithmetic.Addition; +import net.sf.jsqlparser.expression.operators.arithmetic.Concat; +import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Iterator; + /** * A basic class for binary expressions, that is expressions having a left member and a right member * which are in turn expressions. @@ -20,7 +27,67 @@ public abstract class BinaryExpression extends ASTNodeAccessImpl implements Expr private Expression leftExpression; private Expression rightExpression; - public BinaryExpression() { + public BinaryExpression() {} + + public BinaryExpression(Expression leftExpression, Expression rightExpression) { + this.leftExpression = leftExpression; + this.rightExpression = rightExpression; + } + + public static Expression build(Class clz, Expression... expressions) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + switch (expressions.length) { + case 0: + return new NullValue(); + case 1: + return expressions[0]; + default: + Iterator it = Arrays.stream(expressions).iterator(); + + Expression leftExpression = it.next(); + Expression rightExpression = it.next(); + BinaryExpression binaryExpression = + clz.getConstructor(Expression.class, Expression.class) + .newInstance(leftExpression, rightExpression); + + while (it.hasNext()) { + rightExpression = it.next(); + binaryExpression = clz.getConstructor(Expression.class, Expression.class) + .newInstance(binaryExpression, rightExpression); + } + return binaryExpression; + } + } + + public static Expression add(Expression... expressions) { + try { + return build(Addition.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression multiply(Expression... expressions) { + try { + return build(Multiplication.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } + } + + public static Expression concat(Expression... expressions) { + try { + return build(Concat.class, expressions); + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException + | IllegalAccessException e) { + // this should never happen, at least I don't see how + throw new RuntimeException(e); + } } public Expression getLeftExpression() { @@ -52,7 +119,7 @@ public void setRightExpression(Expression expression) { @Override public String toString() { return // (not ? "NOT " : "") + - getLeftExpression() + " " + getStringExpression() + " " + getRightExpression(); + getLeftExpression() + " " + getStringExpression() + " " + getRightExpression(); } public abstract String getStringExpression(); diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java index 50ad8cf7b..39960b35f 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/arithmetic/Concat.java @@ -15,6 +15,12 @@ public class Concat extends BinaryExpression { + public Concat() {} + + public Concat(Expression leftExpression, Expression rightExpression) { + super(leftExpression, rightExpression); + } + @Override public void accept(ExpressionVisitor expressionVisitor) { expressionVisitor.visit(this); diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java new file mode 100644 index 000000000..d33fe857e --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/operators/arithmetic/ConcatTest.java @@ -0,0 +1,56 @@ +package net.sf.jsqlparser.expression.operators.arithmetic; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.StringValue; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ConcatTest { + + @Test + void concatTest() { + Expression expression = + Concat.concat(new StringValue("A"), new StringValue("B"), new StringValue("C")); + Assertions.assertInstanceOf(Concat.class, expression); + Assertions.assertEquals("'A' || 'B' || 'C'", expression.toString()); + + expression = Concat.concat(new StringValue("A")); + Assertions.assertInstanceOf(StringValue.class, expression); + Assertions.assertEquals("'A'", expression.toString()); + + expression = Concat.concat(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } + + void addTest() { + Expression expression = Addition.add(new LongValue(1), new LongValue(2), new LongValue(3)); + Assertions.assertInstanceOf(Addition.class, expression); + Assertions.assertEquals("1 + 2 + 3", expression.toString()); + + expression = Addition.add(new LongValue(1)); + Assertions.assertInstanceOf(LongValue.class, expression); + Assertions.assertEquals("1", expression.toString()); + + expression = Addition.add(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } + + void multiplyTest() { + Expression expression = + Multiplication.multiply(new LongValue(1), new LongValue(2), new LongValue(3)); + Assertions.assertInstanceOf(Addition.class, expression); + Assertions.assertEquals("1 + 2 + 3", expression.toString()); + + expression = Multiplication.multiply(new LongValue(1)); + Assertions.assertInstanceOf(LongValue.class, expression); + Assertions.assertEquals("1", expression.toString()); + + expression = Multiplication.multiply(); + Assertions.assertInstanceOf(NullValue.class, expression); + Assertions.assertEquals("NULL", expression.toString()); + } +}