From ac5f9266730685d16ba6d735dc1ea74bc62d97a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=97=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Tue, 27 Apr 2021 11:06:46 +0300 Subject: [PATCH 1/3] Row acess support --- .../expression/ExpressionVisitor.java | 2 + .../expression/ExpressionVisitorAdapter.java | 5 ++ .../expression/RowGetExpression.java | 48 +++++++++++++++++++ .../sf/jsqlparser/util/TablesNamesFinder.java | 6 +++ .../util/deparser/ExpressionDeParser.java | 7 +++ .../validator/ExpressionValidator.java | 6 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 16 ++++--- .../statement/select/SelectTest.java | 6 +++ 8 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index 7174bcaef..b94e4b0f0 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -142,6 +142,8 @@ public interface ExpressionVisitor { void visit(RowConstructor rowConstructor); + void visit(RowGetExpression rowGetExpression); + void visit(OracleHint hint); void visit(TimeKeyExpression timeKeyExpression); diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 60e86c0d4..b120c4c4b 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -509,6 +509,11 @@ public void visit(RowConstructor rowConstructor) { } } + @Override + public void visit(RowGetExpression rowGetExpression) { + rowGetExpression.getExpression().accept(this); + } + @Override public void visit(HexValue hexValue) { diff --git a/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java b/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java new file mode 100644 index 000000000..16376a470 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/RowGetExpression.java @@ -0,0 +1,48 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2021 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; + +public final class RowGetExpression extends ASTNodeAccessImpl implements Expression { + private Expression expression; + private String columnName; + + public RowGetExpression(Expression expression, String columnName) { + this.expression = expression; + this.columnName = columnName; + } + + @Override + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } + + @Override + public String toString() { + return expression + "." + columnName; + } + + public Expression getExpression() { + return expression; + } + + public void setExpression(Expression expression) { + this.expression = expression; + } + + public String getColumnName() { + return columnName; + } + + public void setColumnName(String columnName) { + this.columnName = columnName; + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index ca97477c5..2d1fb5986 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -43,6 +43,7 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RowConstructor; +import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.TimeKeyExpression; @@ -745,6 +746,11 @@ public void visit(RowConstructor rowConstructor) { } } + @Override + public void visit(RowGetExpression rowGetExpression) { + rowGetExpression.getExpression().accept(this); + } + @Override public void visit(HexValue hexValue) { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index 4cb362d45..fa8352652 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -45,6 +45,7 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RowConstructor; +import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.TimeKeyExpression; @@ -881,6 +882,12 @@ public void visit(RowConstructor rowConstructor) { buffer.append(")"); } + @Override + public void visit(RowGetExpression rowGetExpression) { + rowGetExpression.getExpression().accept(this); + buffer.append(".").append(rowGetExpression.getColumnName()); + } + @Override public void visit(OracleHint hint) { buffer.append(hint.toString()); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java index 66558f726..1daa4a438 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java @@ -41,6 +41,7 @@ import net.sf.jsqlparser.expression.OracleHint; import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.RowConstructor; +import net.sf.jsqlparser.expression.RowGetExpression; import net.sf.jsqlparser.expression.SignedExpression; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.TimeKeyExpression; @@ -499,6 +500,11 @@ public void visit(RowConstructor rowConstructor) { validateOptionalExpressionList(rowConstructor.getExprList()); } + @Override + public void visit(RowGetExpression rowGetExpression) { + rowGetExpression.getExpression().accept(this); + } + @Override public void visit(OracleHint hint) { // nothing to validate diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 2adf0f839..1f5919a60 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -3370,14 +3370,16 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD("(" retval=SubSelect() ")") "(" retval=SubSelect() ")" - | "(" list = SimpleExpressionList() ")" - { - if (list.getExpressions().size() == 1) { - retval = new Parenthesis(list.getExpressions().get(0)); - } else { - retval = new RowConstructor().withExprList(list); + | ( "(" list = SimpleExpressionList() ")" + { + if (list.getExpressions().size() == 1) { + retval = new Parenthesis(list.getExpressions().get(0)); + } else { + retval = new RowConstructor().withExprList(list); + } } - } + ["." tmp=RelObjectNameExt() { retval = new RowGetExpression(retval, tmp); }] + ) ) [ diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java index cae178fc4..51f0c6b46 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -4500,4 +4500,10 @@ public void testKeywordAlgorithmIssue1138() throws JSQLParserException { public void testFunctionOrderBy() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("SELECT array_agg(DISTINCT s ORDER BY b)[1] FROM t"); } + + @Test + public void testSelectRowElement() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("SELECT (t.tup).id, (tup).name FROM t"); + } + } From 25c3aa3436b5e511aa199aae1955a7b7c3d78ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=97=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Tue, 27 Apr 2021 11:13:40 +0300 Subject: [PATCH 2/3] Remove IN Left Expression List, replaced by RowConstructor Expression --- .../expression/ExpressionVisitorAdapter.java | 2 -- .../operators/relational/InExpression.java | 24 +------------------ .../sf/jsqlparser/util/TablesNamesFinder.java | 2 -- .../util/deparser/ExpressionDeParser.java | 10 +++----- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 9 +------ .../ExpressionVisitorAdapterTest.java | 9 ++----- .../statement/select/SelectTest.java | 2 +- 7 files changed, 8 insertions(+), 50 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index b120c4c4b..36b500556 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -173,8 +173,6 @@ public void visit(GreaterThanEquals expr) { public void visit(InExpression expr) { if (expr.getLeftExpression() != null) { expr.getLeftExpression().accept(this); - } else if (expr.getLeftItemsList() != null) { - expr.getLeftItemsList().accept(this); } if (expr.getRightExpression() != null) { expr.getRightExpression().accept(this); diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java index be65acc67..28f3a17b9 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/InExpression.java @@ -16,7 +16,6 @@ public class InExpression extends ASTNodeAccessImpl implements Expression, SupportsOldOracleJoinSyntax { private Expression leftExpression; - private ItemsList leftItemsList; private ItemsList rightItemsList; private boolean not = false; private Expression rightExpression; @@ -80,14 +79,6 @@ public void setNot(boolean b) { not = b; } - public ItemsList getLeftItemsList() { - return leftItemsList; - } - - public void setLeftItemsList(ItemsList leftItemsList) { - this.leftItemsList = leftItemsList; - } - public Expression getRightExpression() { return rightExpression; } @@ -108,11 +99,7 @@ private String getLeftExpressionString() { @Override public String toString() { StringBuilder statementBuilder = new StringBuilder(); - if (leftExpression == null) { - statementBuilder.append(leftItemsList); - } else { - statementBuilder.append(getLeftExpressionString()); - } + statementBuilder.append(getLeftExpressionString()); statementBuilder.append(" "); if (not) { @@ -156,11 +143,6 @@ public void setMultiExpressionList(MultiExpressionList multiExpressionList) { this.multiExpressionList = multiExpressionList; } - public InExpression withLeftItemsList(ItemsList leftItemsList) { - this.setLeftItemsList(leftItemsList); - return this; - } - public InExpression withRightExpression(Expression rightExpression) { this.setRightExpression(rightExpression); return this; @@ -196,10 +178,6 @@ public E getLeftExpression(Class type) { return type.cast(getLeftExpression()); } - public E getLeftItemsList(Class type) { - return type.cast(getLeftItemsList()); - } - public E getRightExpression(Class type) { return type.cast(getRightExpression()); } diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 2d1fb5986..7d13b2b3c 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -272,8 +272,6 @@ public void visit(GreaterThanEquals greaterThanEquals) { public void visit(InExpression inExpression) { if (inExpression.getLeftExpression() != null) { inExpression.getLeftExpression().accept(this); - } else if (inExpression.getLeftItemsList() != null) { - inExpression.getLeftItemsList().accept(this); } if (inExpression.getRightExpression() != null) { inExpression.getRightExpression().accept(this); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index fa8352652..381ef4873 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -223,13 +223,9 @@ public void visit(GreaterThanEquals greaterThanEquals) { @Override public void visit(InExpression inExpression) { - if (inExpression.getLeftExpression() == null) { - inExpression.getLeftItemsList().accept(this); - } else { - inExpression.getLeftExpression().accept(this); - if (inExpression.getOldOracleJoinSyntax() == SupportsOldOracleJoinSyntax.ORACLE_JOIN_RIGHT) { - buffer.append("(+)"); - } + inExpression.getLeftExpression().accept(this); + if (inExpression.getOldOracleJoinSyntax() == SupportsOldOracleJoinSyntax.ORACLE_JOIN_RIGHT) { + buffer.append("(+)"); } if (inExpression.isNot()) { buffer.append(" NOT"); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 1f5919a60..05e1484a9 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2797,14 +2797,7 @@ Expression InExpression() #InExpression : ExpressionList expressionList = null; } { - ( LOOKAHEAD(3) "(" ( - LOOKAHEAD(SimpleExpressionList()) leftItemsList = SimpleExpressionList() { result.setLeftItemsList(leftItemsList); } - | - leftExpression=SimpleExpression() - [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ] - ) - ")" - | + ( leftExpression=SimpleExpression() { result.setLeftExpression(leftExpression); } [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ] ) diff --git a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java index 5257af1d1..78af6a1bb 100644 --- a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java @@ -18,7 +18,6 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import net.sf.jsqlparser.JSQLParserException; @@ -67,14 +66,12 @@ public void testInExpressionProblem() throws JSQLParserException { public void visit(InExpression expr) { super.visit(expr); exprList.add(expr.getLeftExpression()); - exprList.add(expr.getLeftItemsList()); exprList.add(expr.getRightItemsList()); } }); assertTrue(exprList.get(0) instanceof Expression); - assertNull(exprList.get(1)); - assertTrue(exprList.get(2) instanceof ItemsList); + assertTrue(exprList.get(1) instanceof ItemsList); } @Test @@ -90,14 +87,12 @@ public void testInExpression() throws JSQLParserException { public void visit(InExpression expr) { super.visit(expr); exprList.add(expr.getLeftExpression()); - exprList.add(expr.getLeftItemsList()); exprList.add(expr.getRightItemsList()); } }); - assertNull(exprList.get(0)); + assertTrue(exprList.get(0) instanceof RowConstructor); assertTrue(exprList.get(1) instanceof ItemsList); - assertTrue(exprList.get(2) instanceof ItemsList); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java index 51f0c6b46..50c6efed0 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -4503,7 +4503,7 @@ public void testFunctionOrderBy() throws JSQLParserException { @Test public void testSelectRowElement() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT (t.tup).id, (tup).name FROM t"); + assertSqlCanBeParsedAndDeparsed("SELECT (t.tup).id, (tup).name FROM t WHERE (t.tup).id IN (1, 2, 3)"); } } From 1cf0a616965ccaf4265bf2478c9897e21a8da537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=97=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Tue, 27 Apr 2021 11:13:54 +0300 Subject: [PATCH 3/3] Remove IN Left Expression List, replaced by RowConstructor Expression Formatting --- src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 05e1484a9..e2af79775 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2797,10 +2797,9 @@ Expression InExpression() #InExpression : ExpressionList expressionList = null; } { - ( - leftExpression=SimpleExpression() { result.setLeftExpression(leftExpression); } - [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ] - ) + leftExpression=SimpleExpression() { result.setLeftExpression(leftExpression); } + [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ] + [ { result.setNot(true); } ] ( // syntactic lookahead for a multi expression list, ie: ((a,b),(c,d))