From aa0ea39a9a6d7791e619619e2409ece126dc3c3a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 28 May 2024 13:13:33 +0200 Subject: [PATCH] [jOOQ/jOOQ#14398] Avoid rendering parentheses on left associative operations --- jOOQ/src/main/java/org/jooq/impl/Add.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/And.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/BitAnd.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/BitOr.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/BitXor.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/Div.java | 11 ++++++++++- jOOQ/src/main/java/org/jooq/impl/Expression.java | 15 +++++++++++---- jOOQ/src/main/java/org/jooq/impl/Mul.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/Operators.java | 1 + jOOQ/src/main/java/org/jooq/impl/Or.java | 4 +++- jOOQ/src/main/java/org/jooq/impl/Sub.java | 11 ++++++++++- jOOQ/src/main/java/org/jooq/impl/Xor.java | 4 +++- 12 files changed, 56 insertions(+), 14 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Add.java b/jOOQ/src/main/java/org/jooq/impl/Add.java index 29a31f228b..94dc08cc7d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Add.java +++ b/jOOQ/src/main/java/org/jooq/impl/Add.java @@ -63,6 +63,7 @@ import java.util.List; import java.util.Set; import org.jooq.conf.TransformUnneededArithmeticExpressions; +import org.jooq.impl.Expression.Associativity; /** @@ -117,7 +118,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operators.OP_PLUS, q.arg2), - c -> c.sql(' ') + c -> c.sql(' '), + Associativity.BOTH ); ctx.sql(')'); } diff --git a/jOOQ/src/main/java/org/jooq/impl/And.java b/jOOQ/src/main/java/org/jooq/impl/And.java index 5b7d28e21f..2eac71416d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/And.java +++ b/jOOQ/src/main/java/org/jooq/impl/And.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -122,7 +123,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operator.AND.toKeyword(), q.arg2), - Context::formatSeparator + Context::formatSeparator, + Associativity.BOTH ); ctx.sqlIndentEnd(')'); } diff --git a/jOOQ/src/main/java/org/jooq/impl/BitAnd.java b/jOOQ/src/main/java/org/jooq/impl/BitAnd.java index fc1d674744..4a334b3548 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BitAnd.java +++ b/jOOQ/src/main/java/org/jooq/impl/BitAnd.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -171,7 +172,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operators.OP_AMP, q.arg2), - c -> c.sql(' ') + c -> c.sql(' '), + Associativity.BOTH ); ctx.sql(')'); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/BitOr.java b/jOOQ/src/main/java/org/jooq/impl/BitOr.java index ef17c53aca..83b3d34c42 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BitOr.java +++ b/jOOQ/src/main/java/org/jooq/impl/BitOr.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -180,7 +181,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operators.OP_VERBAR, q.arg2), - c -> c.sql(' ') + c -> c.sql(' '), + Associativity.BOTH ); ctx.sql(')'); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/BitXor.java b/jOOQ/src/main/java/org/jooq/impl/BitXor.java index 0bd3a4a224..8ad032b30e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BitXor.java +++ b/jOOQ/src/main/java/org/jooq/impl/BitXor.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -190,7 +191,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, op, q.arg2), - c -> c.sql(' ') + c -> c.sql(' '), + Associativity.BOTH ); ctx.sql(')'); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/Div.java b/jOOQ/src/main/java/org/jooq/impl/Div.java index c6f868a0e4..11226f8014 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Div.java +++ b/jOOQ/src/main/java/org/jooq/impl/Div.java @@ -63,6 +63,7 @@ import java.util.List; import java.util.Set; import org.jooq.conf.TransformUnneededArithmeticExpressions; +import org.jooq.impl.Expression.Associativity; /** @@ -112,7 +113,15 @@ implements - ctx.sql('(').visit(arg1).sql(" / ").visit(arg2).sql(')'); + ctx.sql('('); + Expression., Div>acceptAssociative( + ctx, + this, + q -> new Expression.Expr<>(q.arg1, Operators.OP_SOL, q.arg2), + c -> c.sql(' '), + Associativity.LEFT + ); + ctx.sql(')'); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java index 3b64c272cb..ef7d03f464 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Expression.java +++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java @@ -882,12 +882,19 @@ implements static final record Expr(Q lhs, QueryPart op, Q rhs) {} + static enum Associativity { + BOTH, + LEFT, + RIGHT + } + @SuppressWarnings("unchecked") static final void acceptAssociative( Context ctx, Q2 exp, Function> expProvider, - Consumer> formatSeparator + Consumer> formatSeparator, + Associativity associativity ) { Expr e = expProvider.apply(exp); Class expType = (Class) exp.getClass(); @@ -907,7 +914,7 @@ implements // [#10665] Associativity is only given for two operands of the same data type // [#12896] ... and if the feature is enabled - boolean associativity = ( + boolean a = ( p.lhs instanceof Typed && p.rhs instanceof Typed ? ((Typed) p.lhs).getDataType().equals(((Typed) p.rhs).getDataType()) : true @@ -915,12 +922,12 @@ implements // [#14356] Delay processing of RHS to emulate depth first // traversal. - if (associativity && expType.isInstance(p.rhs)) + if (a && associativity != Associativity.LEFT && expType.isInstance(p.rhs)) queue.push(expProvider.apply((Q2) p.rhs)); else queue.push(p.rhs); - if (associativity && expType.isInstance(p.lhs)) + if (a && associativity != Associativity.RIGHT && expType.isInstance(p.lhs)) queue.push(expProvider.apply((Q2) p.lhs)); else elements.add(p.lhs); diff --git a/jOOQ/src/main/java/org/jooq/impl/Mul.java b/jOOQ/src/main/java/org/jooq/impl/Mul.java index 35beec2cdc..f14a89e55e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Mul.java +++ b/jOOQ/src/main/java/org/jooq/impl/Mul.java @@ -63,6 +63,7 @@ import java.util.List; import java.util.Set; import org.jooq.conf.TransformUnneededArithmeticExpressions; +import org.jooq.impl.Expression.Associativity; /** @@ -117,7 +118,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operators.OP_AST, q.arg2), - c -> c.sql(' ') + c -> c.sql(' '), + Associativity.BOTH ); ctx.sql(')'); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Operators.java b/jOOQ/src/main/java/org/jooq/impl/Operators.java index d22514c8af..be8315e3cf 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Operators.java +++ b/jOOQ/src/main/java/org/jooq/impl/Operators.java @@ -58,6 +58,7 @@ final class Operators { static final SQL OP_GT = raw(">"); static final SQL OP_HAT = raw("^"); static final SQL OP_LT = raw("<"); + static final SQL OP_MINUS = raw("-"); static final SQL OP_NUM = raw("#"); static final SQL OP_PERCNT = raw("%"); static final SQL OP_PLUS = raw("+"); diff --git a/jOOQ/src/main/java/org/jooq/impl/Or.java b/jOOQ/src/main/java/org/jooq/impl/Or.java index 534e0539dd..c3b47809f8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Or.java +++ b/jOOQ/src/main/java/org/jooq/impl/Or.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -122,7 +123,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operator.OR.toKeyword(), q.arg2), - Context::formatSeparator + Context::formatSeparator, + Associativity.BOTH ); ctx.sqlIndentEnd(')'); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Sub.java b/jOOQ/src/main/java/org/jooq/impl/Sub.java index 3578143d45..7f2e969678 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Sub.java +++ b/jOOQ/src/main/java/org/jooq/impl/Sub.java @@ -63,6 +63,7 @@ import java.util.List; import java.util.Set; import org.jooq.conf.TransformUnneededArithmeticExpressions; +import org.jooq.impl.Expression.Associativity; /** @@ -112,7 +113,15 @@ implements - ctx.sql('(').visit(arg1).sql(" - ").visit(arg2).sql(')'); + ctx.sql('('); + Expression., Sub>acceptAssociative( + ctx, + this, + q -> new Expression.Expr<>(q.arg1, Operators.OP_MINUS, q.arg2), + c -> c.sql(' '), + Associativity.LEFT + ); + ctx.sql(')'); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/Xor.java b/jOOQ/src/main/java/org/jooq/impl/Xor.java index 9317d07527..04923f903e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Xor.java +++ b/jOOQ/src/main/java/org/jooq/impl/Xor.java @@ -52,6 +52,7 @@ import org.jooq.*; import org.jooq.Function1; import org.jooq.Record; import org.jooq.conf.ParamType; +import org.jooq.impl.Expression.Associativity; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -119,7 +120,8 @@ implements ctx, this, q -> new Expression.Expr<>(q.arg1, Operator.XOR.toKeyword(), q.arg2), - Context::formatSeparator + Context::formatSeparator, + Associativity.BOTH ); ctx.sqlIndentEnd(')'); }