From 4b7fd0b621ea39fc3714244885e6f9f56a7bdcd8 Mon Sep 17 00:00:00 2001 From: Tobias Warneke Date: Sun, 30 Jun 2024 22:53:14 +0200 Subject: [PATCH 01/88] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3dde1be38..b35de2067 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.github.jsqlparser jsqlparser - 5.0 + 5.1-SNAPSHOT JSQLParser library 2004 @@ -107,7 +107,7 @@ scm:git:https://github.com/JSQLParser/JSqlParser.git scm:git:ssh://git@github.com:JSQLParser/JSqlParser.git https://github.com/JSQLParser/JSqlParser.git - jsqlparser-5.0 + HEAD From 6a36b3fc6af5ae1edd5eed812f42244b81e26de3 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Fri, 5 Jul 2024 12:10:32 +0700 Subject: [PATCH 02/88] feat: improve usability of the `ExpressionVisitorAdapter` Signed-off-by: Andreas Reichel --- .../expression/ExpressionVisitorAdapter.java | 368 ++++++++---------- .../expression/LambdaExpression.java | 4 +- 2 files changed, 154 insertions(+), 218 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index f2223f890..8ade2f5f9 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -64,6 +64,9 @@ import net.sf.jsqlparser.statement.select.UnPivot; import net.sf.jsqlparser.statement.select.WithItem; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Optional; @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"}) @@ -88,65 +91,58 @@ public T visit(NullValue nullValue, S context) { @Override public T visit(Function function, S context) { + ArrayList subExpressions = new ArrayList<>(); if (function.getParameters() != null) { - function.getParameters().accept(this, context); + subExpressions.addAll(function.getParameters()); } if (function.getKeep() != null) { - function.getKeep().accept(this, context); + subExpressions.add(function.getKeep()); } if (function.getOrderByElements() != null) { for (OrderByElement orderByElement : function.getOrderByElements()) { - orderByElement.getExpression().accept(this, context); + subExpressions.add(orderByElement.getExpression()); } } - return null; + return visitExpressions(function, context, subExpressions); } @Override public T visit(SignedExpression signedExpression, S context) { - signedExpression.getExpression().accept(this, context); - return null; + return signedExpression.getExpression().accept(this, context); } @Override public T visit(JdbcParameter jdbcParameter, S context) { - return null; } @Override public T visit(JdbcNamedParameter jdbcNamedParameter, S context) { - return null; } @Override public T visit(DoubleValue doubleValue, S context) { - return null; } @Override public T visit(LongValue longValue, S context) { - return null; } @Override public T visit(DateValue dateValue, S context) { - return null; } @Override public T visit(TimeValue timeValue, S context) { - return null; } @Override public T visit(TimestampValue timestampValue, S context) { - return null; } @@ -157,171 +153,143 @@ public T visit(StringValue stringValue, S context) { @Override public T visit(Addition addition, S context) { - visitBinaryExpression(addition, context); - return null; + return visitBinaryExpression(addition, context); } @Override public T visit(Division division, S context) { - visitBinaryExpression(division, context); - return null; + return visitBinaryExpression(division, context); } @Override public T visit(IntegerDivision integerDivision, S context) { - visitBinaryExpression(integerDivision, context); - return null; + return visitBinaryExpression(integerDivision, context); } @Override public T visit(Multiplication multiplication, S context) { - visitBinaryExpression(multiplication, context); - return null; + return visitBinaryExpression(multiplication, context); } @Override public T visit(Subtraction subtraction, S context) { - visitBinaryExpression(subtraction, context); - return null; + return visitBinaryExpression(subtraction, context); } @Override public T visit(AndExpression andExpression, S context) { - visitBinaryExpression(andExpression, context); - return null; + return visitBinaryExpression(andExpression, context); } @Override public T visit(OrExpression orExpression, S context) { - visitBinaryExpression(orExpression, context); - return null; + return visitBinaryExpression(orExpression, context); } @Override public T visit(XorExpression xorExpression, S context) { - visitBinaryExpression(xorExpression, context); - return null; + return visitBinaryExpression(xorExpression, context); } @Override public T visit(Between between, S context) { - between.getLeftExpression().accept(this, context); - between.getBetweenExpressionStart().accept(this, context); - between.getBetweenExpressionEnd().accept(this, context); - return null; + return visitExpressions(between, context, between.getLeftExpression(), + between.getBetweenExpressionStart(), between.getBetweenExpressionEnd()); } public T visit(OverlapsCondition overlapsCondition, S context) { - overlapsCondition.getLeft().accept(this, context); - overlapsCondition.getRight().accept(this, context); - return null; + return visitExpressions(overlapsCondition, context, overlapsCondition.getLeft(), + overlapsCondition.getRight()); } @Override public T visit(EqualsTo equalsTo, S context) { - visitBinaryExpression(equalsTo, context); - return null; + return visitBinaryExpression(equalsTo, context); } @Override public T visit(GreaterThan greaterThan, S context) { - visitBinaryExpression(greaterThan, context); - return null; + return visitBinaryExpression(greaterThan, context); } @Override public T visit(GreaterThanEquals greaterThanEquals, S context) { - visitBinaryExpression(greaterThanEquals, context); - return null; + return visitBinaryExpression(greaterThanEquals, context); } @Override public T visit(InExpression inExpression, S context) { - inExpression.getLeftExpression().accept(this, context); - inExpression.getRightExpression().accept(this, context); - return null; + return visitExpressions(inExpression, context, inExpression.getLeftExpression(), + inExpression.getRightExpression()); } @Override public T visit(IncludesExpression includesExpression, S context) { - includesExpression.getLeftExpression().accept(this, context); - includesExpression.getRightExpression().accept(this, context); - return null; + return visitExpressions(includesExpression, context, includesExpression.getLeftExpression(), + includesExpression.getRightExpression()); } @Override public T visit(ExcludesExpression excludesExpression, S context) { - excludesExpression.getLeftExpression().accept(this, context); - excludesExpression.getRightExpression().accept(this, context); - return null; + return visitExpressions(excludesExpression, context, excludesExpression.getLeftExpression(), + excludesExpression.getRightExpression()); } @Override public T visit(IsNullExpression isNullExpression, S context) { - isNullExpression.getLeftExpression().accept(this, context); - return null; + return isNullExpression.getLeftExpression().accept(this, context); } @Override public T visit(FullTextSearch fullTextSearch, S context) { - for (Column col : fullTextSearch.getMatchColumns()) { - col.accept(this, context); - } - return null; + ArrayList subExpressions = new ArrayList<>(fullTextSearch.getMatchColumns()); + subExpressions.add(fullTextSearch.getAgainstValue()); + return visitExpressions(fullTextSearch, context, subExpressions); } @Override public T visit(IsBooleanExpression isBooleanExpression, S context) { - isBooleanExpression.getLeftExpression().accept(this, context); - return null; + return isBooleanExpression.getLeftExpression().accept(this, context); } @Override public T visit(LikeExpression likeExpression, S context) { - visitBinaryExpression(likeExpression, context); - return null; + return visitBinaryExpression(likeExpression, context); } @Override public T visit(MinorThan minorThan, S context) { - visitBinaryExpression(minorThan, context); - return null; + return visitBinaryExpression(minorThan, context); } @Override public T visit(MinorThanEquals minorThanEquals, S context) { - visitBinaryExpression(minorThanEquals, context); - return null; + return visitBinaryExpression(minorThanEquals, context); } @Override public T visit(NotEqualsTo notEqualsTo, S context) { - visitBinaryExpression(notEqualsTo, context); - return null; + return visitBinaryExpression(notEqualsTo, context); } @Override public T visit(DoubleAnd doubleAnd, S context) { - visitBinaryExpression(doubleAnd, context); - return null; + return visitBinaryExpression(doubleAnd, context); } @Override public T visit(Contains contains, S context) { - visitBinaryExpression(contains, context); - return null; + return visitBinaryExpression(contains, context); } @Override public T visit(ContainedBy containedBy, S context) { - visitBinaryExpression(containedBy, context); - return null; + return visitBinaryExpression(containedBy, context); } @Override public T visit(Column column, S context) { - return null; } @@ -336,102 +304,93 @@ public T visit(ParenthesedSelect select, S context) { @Override public T visit(CaseExpression caseExpression, S context) { + ArrayList subExpressions = new ArrayList<>(); + if (caseExpression.getSwitchExpression() != null) { - caseExpression.getSwitchExpression().accept(this, context); - } - for (Expression x : caseExpression.getWhenClauses()) { - x.accept(this, context); + subExpressions.add(caseExpression.getSwitchExpression()); } + subExpressions.addAll(caseExpression.getWhenClauses()); if (caseExpression.getElseExpression() != null) { - caseExpression.getElseExpression().accept(this, context); + subExpressions.add(caseExpression.getElseExpression()); } - return null; + return visitExpressions(caseExpression, context, subExpressions); } @Override public T visit(WhenClause whenClause, S context) { - whenClause.getWhenExpression().accept(this, context); - whenClause.getThenExpression().accept(this, context); - return null; + return visitExpressions(whenClause, context, whenClause.getWhenExpression(), + whenClause.getThenExpression()); } @Override public T visit(ExistsExpression existsExpression, S context) { - existsExpression.getRightExpression().accept(this, context); - return null; + return existsExpression.getRightExpression().accept(this, context); } @Override public T visit(MemberOfExpression memberOfExpression, S context) { - memberOfExpression.getRightExpression().accept(this, context); - return null; + return memberOfExpression.getRightExpression().accept(this, context); } @Override public T visit(AnyComparisonExpression anyComparisonExpression, S context) { - return null; } @Override public T visit(Concat concat, S context) { - visitBinaryExpression(concat, context); - return null; + return visitBinaryExpression(concat, context); } @Override public T visit(Matches matches, S context) { - visitBinaryExpression(matches, context); - return null; + return visitBinaryExpression(matches, context); } @Override public T visit(BitwiseAnd bitwiseAnd, S context) { - visitBinaryExpression(bitwiseAnd, context); - return null; + return visitBinaryExpression(bitwiseAnd, context); } @Override public T visit(BitwiseOr bitwiseOr, S context) { - visitBinaryExpression(bitwiseOr, context); - return null; + return visitBinaryExpression(bitwiseOr, context); } @Override public T visit(BitwiseXor bitwiseXor, S context) { - visitBinaryExpression(bitwiseXor, context); - return null; + return visitBinaryExpression(bitwiseXor, context); } @Override public T visit(CastExpression castExpression, S context) { - castExpression.getLeftExpression().accept(this, context); - return null; + return castExpression.getLeftExpression().accept(this, context); } @Override public T visit(Modulo modulo, S context) { - visitBinaryExpression(modulo, context); - return null; + return visitBinaryExpression(modulo, context); } @Override public T visit(AnalyticExpression analyticExpression, S context) { + ArrayList subExpressions = new ArrayList<>(); + if (analyticExpression.getExpression() != null) { - analyticExpression.getExpression().accept(this, context); + subExpressions.add(analyticExpression.getExpression()); } if (analyticExpression.getDefaultValue() != null) { - analyticExpression.getDefaultValue().accept(this, context); + subExpressions.add(analyticExpression.getDefaultValue()); } if (analyticExpression.getOffset() != null) { - analyticExpression.getOffset().accept(this, context); + subExpressions.add(analyticExpression.getOffset()); } if (analyticExpression.getKeep() != null) { - analyticExpression.getKeep().accept(this, context); + subExpressions.add(analyticExpression.getKeep()); } if (analyticExpression.getFuncOrderBy() != null) { for (OrderByElement element : analyticExpression.getOrderByElements()) { - element.getExpression().accept(this, context); + subExpressions.add(element.getExpression()); } } if (analyticExpression.getWindowElement() != null) { @@ -444,142 +403,144 @@ public T visit(AnalyticExpression analyticExpression, S context) { */ Optional.ofNullable(analyticExpression.getWindowElement().getRange()) .map(WindowRange::getStart) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); + .map(WindowOffset::getExpression).ifPresent(subExpressions::add); Optional.ofNullable(analyticExpression.getWindowElement().getRange()) .map(WindowRange::getEnd) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); + .map(WindowOffset::getExpression).ifPresent(subExpressions::add); Optional.ofNullable(analyticExpression.getWindowElement().getOffset()) - .map(WindowOffset::getExpression).ifPresent(e -> e.accept(this, context)); + .map(WindowOffset::getExpression).ifPresent(subExpressions::add); } - return null; + return visitExpressions(analyticExpression, context, subExpressions); } @Override public T visit(ExtractExpression extractExpression, S context) { - extractExpression.getExpression().accept(this, context); - return null; + return extractExpression.getExpression().accept(this, context); } @Override public T visit(IntervalExpression intervalExpression, S context) { - return null; + return intervalExpression.getExpression().accept(this, context); } @Override public T visit(OracleHierarchicalExpression hierarchicalExpression, S context) { - hierarchicalExpression.getConnectExpression().accept(this, context); - hierarchicalExpression.getStartExpression().accept(this, context); - return null; + return visitExpressions(hierarchicalExpression, context, + hierarchicalExpression.getConnectExpression(), + hierarchicalExpression.getStartExpression()); } @Override public T visit(RegExpMatchOperator regExpMatchOperator, S context) { - visitBinaryExpression(regExpMatchOperator, context); - return null; + return visitBinaryExpression(regExpMatchOperator, context); } @Override public T visit(ExpressionList expressionList, S context) { - for (Expression expr : expressionList) { - expr.accept(this, context); - } - return null; + return visitExpressions(expressionList, context, (Collection) expressionList); } @Override public T visit(RowConstructor rowConstructor, S context) { - for (Expression expr : rowConstructor) { - expr.accept(this, context); - } - return null; + return visitExpressions(rowConstructor, context, (Collection) rowConstructor); } @Override public T visit(NotExpression notExpr, S context) { - notExpr.getExpression().accept(this, context); - return null; + return notExpr.getExpression().accept(this, context); } @Override public T visit(BitwiseRightShift bitwiseRightShift, S context) { - visitBinaryExpression(bitwiseRightShift, context); - return null; + return visitBinaryExpression(bitwiseRightShift, context); } @Override public T visit(BitwiseLeftShift bitwiseLeftShift, S context) { - visitBinaryExpression(bitwiseLeftShift, context); + return visitBinaryExpression(bitwiseLeftShift, context); + } + + protected T visitExpressions(Expression expression, S context, + ExpressionList subExpressions) { + return visitExpressions(expression, context, (Collection) subExpressions); + } + + protected T visitExpressions(Expression expression, S context, + Collection subExpressions) { + for (Expression e : subExpressions) { + if (e != null) { + e.accept(this, context); + } + } return null; } + protected T visitExpressions(Expression expression, S context, + Expression... subExpressions) { + return visitExpressions(expression, context, Arrays.asList(subExpressions)); + } + protected T visitBinaryExpression(BinaryExpression binaryExpression, S context) { - binaryExpression.getLeftExpression().accept(this, context); - binaryExpression.getRightExpression().accept(this, context); - return null; + return visitExpressions(binaryExpression, context, binaryExpression.getLeftExpression(), + binaryExpression.getRightExpression()); } @Override public T visit(JsonExpression jsonExpr, S context) { - jsonExpr.getExpression().accept(this, context); - return null; + return jsonExpr.getExpression().accept(this, context); } @Override public T visit(JsonOperator jsonOperator, S context) { - visitBinaryExpression(jsonOperator, context); - return null; + return visitBinaryExpression(jsonOperator, context); } @Override public T visit(UserVariable userVariable, S context) { - return null; } @Override public T visit(NumericBind numericBind, S context) { - return null; } @Override public T visit(KeepExpression keepExpression, S context) { + ArrayList subExpressions = new ArrayList<>(); for (OrderByElement element : keepExpression.getOrderByElements()) { - element.getExpression().accept(this, context); + subExpressions.add(element.getExpression()); } - return null; + return visitExpressions(keepExpression, context, subExpressions); } @Override public T visit(MySQLGroupConcat groupConcat, S context) { - for (Expression expr : groupConcat.getExpressionList()) { - expr.accept(this, context); - } + ArrayList subExpressions = new ArrayList<>(groupConcat.getExpressionList()); if (groupConcat.getOrderByElements() != null) { for (OrderByElement element : groupConcat.getOrderByElements()) { - element.getExpression().accept(this, context); + subExpressions.add(element.getExpression()); } } - return null; + return visitExpressions(groupConcat, context, subExpressions); } @Override public T visit(Pivot pivot, S context) { for (SelectItem item : pivot.getFunctionItems()) { - item.getExpression().accept(this, context); + item.accept(this, context); } for (Column col : pivot.getForColumns()) { col.accept(this, context); } if (pivot.getSingleInItems() != null) { for (SelectItem item : pivot.getSingleInItems()) { - item.getExpression().accept(this, context); + item.accept(this, context); } } - if (pivot.getMultiInItems() != null) { for (SelectItem> item : pivot.getMultiInItems()) { - item.getExpression().accept(this, context); + item.accept(this, context); } } return null; @@ -588,7 +549,7 @@ public T visit(Pivot pivot, S context) { @Override public T visit(PivotXml pivotXml, S context) { for (SelectItem item : pivotXml.getFunctionItems()) { - item.getExpression().accept(this, context); + item.accept(this, context); } for (Column col : pivotXml.getForColumns()) { col.accept(this, context); @@ -622,37 +583,31 @@ public T visit(AllValue allValue, S context) { @Override public T visit(IsDistinctExpression isDistinctExpression, S context) { - visitBinaryExpression(isDistinctExpression, context); - return null; + return visitBinaryExpression(isDistinctExpression, context); } @Override public T visit(SelectItem selectItem, S context) { - selectItem.getExpression().accept(this, context); - return null; + return selectItem.getExpression().accept(this, context); } @Override public T visit(RowGetExpression rowGetExpression, S context) { - rowGetExpression.getExpression().accept(this, context); - return null; + return rowGetExpression.getExpression().accept(this, context); } @Override public T visit(HexValue hexValue, S context) { - return null; } @Override public T visit(OracleHint hint, S context) { - return null; } @Override public T visit(TimeKeyExpression timeKeyExpression, S context) { - return null; } @@ -668,99 +623,86 @@ public T visit(NextValExpression nextValExpression, S context) { @Override public T visit(CollateExpression collateExpression, S context) { - collateExpression.getLeftExpression().accept(this, context); - return null; + return collateExpression.getLeftExpression().accept(this, context); } @Override public T visit(SimilarToExpression similarToExpression, S context) { - visitBinaryExpression(similarToExpression, context); - return null; + return visitBinaryExpression(similarToExpression, context); } @Override public T visit(ArrayExpression arrayExpression, S context) { - arrayExpression.getObjExpression().accept(this, context); + ArrayList subExpressions = new ArrayList<>(); + + subExpressions.add(arrayExpression.getObjExpression()); if (arrayExpression.getIndexExpression() != null) { - arrayExpression.getIndexExpression().accept(this, context); + subExpressions.add(arrayExpression.getIndexExpression()); } if (arrayExpression.getStartIndexExpression() != null) { - arrayExpression.getStartIndexExpression().accept(this, context); + subExpressions.add(arrayExpression.getStartIndexExpression()); } if (arrayExpression.getStopIndexExpression() != null) { - arrayExpression.getStopIndexExpression().accept(this, context); + subExpressions.add(arrayExpression.getStopIndexExpression()); } - return null; + return visitExpressions(arrayExpression, context, subExpressions); } @Override public T visit(ArrayConstructor arrayConstructor, S context) { - for (Expression expression : arrayConstructor.getExpressions()) { - expression.accept(this, context); - } - return null; + return visitExpressions(arrayConstructor, context, arrayConstructor.getExpressions()); } @Override public T visit(VariableAssignment variableAssignment, S context) { - variableAssignment.getVariable().accept(this, context); - variableAssignment.getExpression().accept(this, context); - return null; + return visitExpressions(variableAssignment, context, variableAssignment.getVariable(), + variableAssignment.getExpression()); } @Override public T visit(XMLSerializeExpr xmlSerializeExpr, S context) { - xmlSerializeExpr.getExpression().accept(this, context); - for (OrderByElement elm : xmlSerializeExpr.getOrderByElements()) { - elm.getExpression().accept(this, context); + ArrayList subExpressions = new ArrayList<>(); + + subExpressions.add(xmlSerializeExpr.getExpression()); + for (OrderByElement orderByElement : xmlSerializeExpr.getOrderByElements()) { + subExpressions.add(orderByElement.getExpression()); } - return null; + return visitExpressions(xmlSerializeExpr, context, subExpressions); } @Override public T visit(TimezoneExpression timezoneExpression, S context) { - timezoneExpression.getLeftExpression().accept(this, context); - return null; + return timezoneExpression.getLeftExpression().accept(this, context); } @Override public T visit(JsonAggregateFunction jsonAggregateFunction, S context) { - Expression expr = jsonAggregateFunction.getExpression(); - if (expr != null) { - expr.accept(this, context); - } - - expr = jsonAggregateFunction.getFilterExpression(); - if (expr != null) { - expr.accept(this, context); - } - return null; + return visitExpressions(jsonAggregateFunction, context, + jsonAggregateFunction.getExpression(), jsonAggregateFunction.getFilterExpression()); } @Override public T visit(JsonFunction jsonFunction, S context) { + ArrayList subExpressions = new ArrayList<>(); for (JsonFunctionExpression expr : jsonFunction.getExpressions()) { - expr.getExpression().accept(this, context); + subExpressions.add(expr.getExpression()); } - return null; + return visitExpressions(jsonFunction, context, subExpressions); } @Override public T visit(ConnectByRootOperator connectByRootOperator, S context) { - connectByRootOperator.getColumn().accept(this, context); - return null; + return connectByRootOperator.getColumn().accept(this, context); } @Override public T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { - oracleNamedFunctionParameter.getExpression().accept(this, context); - return null; + return oracleNamedFunctionParameter.getExpression().accept(this, context); } @Override public T visit(GeometryDistance geometryDistance, S context) { - visitBinaryExpression(geometryDistance, context); - return null; + return visitBinaryExpression(geometryDistance, context); } @Override @@ -778,33 +720,28 @@ public T visit(Select select, S context) { @Override public T visit(TranscodingFunction transcodingFunction, S context) { - - return null; + return transcodingFunction.getExpression().accept(this, context); } @Override public T visit(TrimFunction trimFunction, S context) { - - return null; + return trimFunction.getExpression().accept(this, context); } @Override public T visit(RangeExpression rangeExpression, S context) { - rangeExpression.getStartExpression().accept(this, context); - rangeExpression.getEndExpression().accept(this, context); - return null; + return visitExpressions(rangeExpression, context, rangeExpression.getStartExpression(), + rangeExpression.getEndExpression()); } @Override public T visit(TSQLLeftJoin tsqlLeftJoin, S context) { - visitBinaryExpression(tsqlLeftJoin, context); - return null; + return visitBinaryExpression(tsqlLeftJoin, context); } @Override public T visit(TSQLRightJoin tsqlRightJoin, S context) { - visitBinaryExpression(tsqlRightJoin, context); - return null; + return visitBinaryExpression(tsqlRightJoin, context); } @Override @@ -812,7 +749,7 @@ public T visit(StructType structType, S context) { // @todo: visit the ColType also if (structType.getArguments() != null) { for (SelectItem selectItem : structType.getArguments()) { - visit(selectItem, context); + selectItem.accept(this, context); } } return null; @@ -820,8 +757,7 @@ public T visit(StructType structType, S context) { @Override public T visit(LambdaExpression lambdaExpression, S context) { - lambdaExpression.getExpression().accept(this, context); - return null; + return lambdaExpression.getExpression().accept(this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java index 46d057f96..78d857287 100644 --- a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java @@ -11,7 +11,7 @@ import net.sf.jsqlparser.parser.ASTNodeAccessImpl; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public class LambdaExpression extends ASTNodeAccessImpl implements Expression { @@ -19,7 +19,7 @@ public class LambdaExpression extends ASTNodeAccessImpl implements Expression { private Expression expression; public LambdaExpression(String identifier, Expression expression) { - this.identifiers = Arrays.asList(identifier); + this.identifiers = Collections.singletonList(identifier); this.expression = expression; } From f3268e73bdd0040257df4b27cedf67a68d78eed3 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Fri, 5 Jul 2024 12:11:18 +0700 Subject: [PATCH 03/88] feat: improve String representation of `Table` and `Column` Signed-off-by: Andreas Reichel --- src/main/java/net/sf/jsqlparser/schema/Column.java | 3 ++- src/main/java/net/sf/jsqlparser/schema/Table.java | 8 ++++++++ .../sf/jsqlparser/util/deparser/ExpressionDeParser.java | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/schema/Column.java b/src/main/java/net/sf/jsqlparser/schema/Column.java index b14c1d03f..55b5a31a9 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Column.java +++ b/src/main/java/net/sf/jsqlparser/schema/Column.java @@ -159,7 +159,8 @@ public T accept(ExpressionVisitor expressionVisitor, S context) { @Override public String toString() { - return getFullyQualifiedName(true); + return getFullyQualifiedName(true) + + (commentText != null ? " /* " + commentText + "*/ " : ""); } public Column withTable(Table table) { diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index dd9f5a6b2..1ee42a923 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -194,6 +194,14 @@ private String getIndex(int idx) { public String getFullyQualifiedName() { StringBuilder fqn = new StringBuilder(); + // remove any leading empty items + // only middle items can be suppressed (e.g. dbo..MY_TABLE ) + while (!partItems.isEmpty() && (partItems.get(partItems.size() - 1) == null + || partItems.get(partItems.size() - 1).isEmpty())) { + partItems.remove(partItems.size() - 1); + } + + for (int i = partItems.size() - 1; i >= 0; i--) { String part = partItems.get(i); if (part == null) { 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 a91b77dea..65ea93489 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -787,6 +787,11 @@ public StringBuilder visit(Column tableColumn, S context) { if (tableColumn.getArrayConstructor() != null) { tableColumn.getArrayConstructor().accept(this, context); } + + if (tableColumn.getCommentText() != null) { + buffer.append(" /* ").append(tableColumn.getCommentText()).append("*/ "); + } + return buffer; } From 13572a83b7033245ced50d956f52f22a9f53959d Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sun, 7 Jul 2024 12:15:51 +0700 Subject: [PATCH 04/88] feat: syntax sugar Signed-off-by: Andreas Reichel --- src/main/java/net/sf/jsqlparser/schema/Table.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 1ee42a923..08d89ce1c 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -110,6 +110,11 @@ public void setDatabase(Database database) { } } + public Table setDatabaseName(String databaseName) { + this.setDatabase( new Database(databaseName) ); + return this; + } + public Table withDatabase(Database database) { setDatabase(database); return this; @@ -119,8 +124,9 @@ public String getSchemaName() { return getIndex(SCHEMA_IDX); } - public void setSchemaName(String schemaName) { - setIndex(SCHEMA_IDX, schemaName); + public Table setSchemaName(String schemaName) { + this.setIndex(SCHEMA_IDX, schemaName); + return this; } public Table withSchemaName(String schemaName) { From 8a662af8109b650418c55856b05e56d347e26a37 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sun, 7 Jul 2024 12:16:36 +0700 Subject: [PATCH 05/88] feat: improve Visitors Signed-off-by: Andreas Reichel --- .../net/sf/jsqlparser/expression/ExpressionVisitor.java | 8 -------- .../jsqlparser/statement/select/SelectVisitorAdapter.java | 7 +++++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index 985547fc6..5ef4c6ad6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -302,10 +302,6 @@ default void visit(ContainedBy containedBy) { T visit(ParenthesedSelect select, S context); - default void visit(ParenthesedSelect select) { - this.visit(select, null); - } - T visit(Column column, S context); default void visit(Column column) { @@ -596,10 +592,6 @@ default void visit(GeometryDistance geometryDistance) { T visit(Select select, S context); - default void visit(Select select) { - this.visit(select, null); - } - T visit(TranscodingFunction transcodingFunction, S context); default void visit(TranscodingFunction transcodingFunction) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java index 5820fa864..90fa3b8c2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java @@ -24,12 +24,15 @@ public T visit(PlainSelect plainSelect, S context) { @Override public T visit(SetOperationList setOpList, S context) { + for (Select select : setOpList.getSelects()) { + select.accept(this, context); + } return null; } @Override public T visit(WithItem withItem, S context) { - return null; + return withItem.getSelect().accept(this, context); } @Override @@ -39,7 +42,7 @@ public T visit(Values aThis, S context) { @Override public T visit(LateralSubSelect lateralSubSelect, S context) { - return null; + return lateralSubSelect.getSelect().accept(this, context); } @Override From e8bc4463f907b75ec80182f9111fad9326da2726 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Mon, 8 Jul 2024 10:00:22 +0700 Subject: [PATCH 06/88] feat: improve the Expression Visitor Adapter Signed-off-by: Andreas Reichel --- .../expression/ExpressionVisitorAdapter.java | 50 ++++++++++--------- .../java/net/sf/jsqlparser/schema/Table.java | 2 +- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 8ade2f5f9..c49bf6aea 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -85,8 +85,7 @@ public void setSelectVisitor(SelectVisitor selectVisitor) { @Override public T visit(NullValue nullValue, S context) { - - return null; + return visitExpression(nullValue, context); } @Override @@ -113,42 +112,42 @@ public T visit(SignedExpression signedExpression, S context) { @Override public T visit(JdbcParameter jdbcParameter, S context) { - return null; + return visitExpression(jdbcParameter, context); } @Override public T visit(JdbcNamedParameter jdbcNamedParameter, S context) { - return null; + return visitExpression(jdbcNamedParameter, context); } @Override public T visit(DoubleValue doubleValue, S context) { - return null; + return visitExpression(doubleValue, context); } @Override public T visit(LongValue longValue, S context) { - return null; + return visitExpression(longValue, context); } @Override public T visit(DateValue dateValue, S context) { - return null; + return visitExpression(dateValue, context); } @Override public T visit(TimeValue timeValue, S context) { - return null; + return visitExpression(timeValue, context); } @Override public T visit(TimestampValue timestampValue, S context) { - return null; + return visitExpression(timestampValue, context); } @Override public T visit(StringValue stringValue, S context) { - return null; + return visitExpression(stringValue, context); } @Override @@ -290,7 +289,7 @@ public T visit(ContainedBy containedBy, S context) { @Override public T visit(Column column, S context) { - return null; + return visitExpression(column, context); } @Override @@ -334,7 +333,7 @@ public T visit(MemberOfExpression memberOfExpression, S context) { @Override public T visit(AnyComparisonExpression anyComparisonExpression, S context) { - return null; + return visitExpression(anyComparisonExpression, context); } @Override @@ -460,6 +459,10 @@ public T visit(BitwiseLeftShift bitwiseLeftShift, S context) { return visitBinaryExpression(bitwiseLeftShift, context); } + protected T visitExpression(Expression expression, S context) { + return null; + } + protected T visitExpressions(Expression expression, S context, ExpressionList subExpressions) { return visitExpressions(expression, context, (Collection) subExpressions); @@ -497,12 +500,12 @@ public T visit(JsonOperator jsonOperator, S context) { @Override public T visit(UserVariable userVariable, S context) { - return null; + return visitExpression(userVariable, context); } @Override public T visit(NumericBind numericBind, S context) { - return null; + return visitExpression(numericBind, context); } @Override @@ -562,23 +565,22 @@ public T visit(PivotXml pivotXml, S context) { @Override public T visit(UnPivot unpivot, S context) { - unpivot.accept(this, context); - return null; + return unpivot.accept(this, context); } @Override public T visit(AllColumns allColumns, S context) { - return null; + return visitExpression(allColumns, context); } @Override public T visit(AllTableColumns allTableColumns, S context) { - return null; + return visitExpression(allTableColumns, context); } @Override public T visit(AllValue allValue, S context) { - return null; + return visitExpression(allValue, context); } @Override @@ -598,27 +600,27 @@ public T visit(RowGetExpression rowGetExpression, S context) { @Override public T visit(HexValue hexValue, S context) { - return null; + return visitExpression(hexValue, context); } @Override public T visit(OracleHint hint, S context) { - return null; + return visitExpression(hint, context); } @Override public T visit(TimeKeyExpression timeKeyExpression, S context) { - return null; + return visitExpression(timeKeyExpression, context); } @Override public T visit(DateTimeLiteralExpression dateTimeLiteralExpression, S context) { - return null; + return visitExpression(dateTimeLiteralExpression, context); } @Override public T visit(NextValExpression nextValExpression, S context) { - return null; + return visitExpression(nextValExpression, context); } @Override diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 08d89ce1c..1c8a3e5a6 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -111,7 +111,7 @@ public void setDatabase(Database database) { } public Table setDatabaseName(String databaseName) { - this.setDatabase( new Database(databaseName) ); + this.setDatabase(new Database(databaseName)); return this; } From d8207aaf616f10e856741e3313fc8355f6ff8a43 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 11 Jul 2024 06:32:29 +0700 Subject: [PATCH 07/88] fix: `FromItem` alias must not shade an actual table (found before) - fixes #2035 Signed-off-by: Andreas Reichel --- .../net/sf/jsqlparser/util/TablesNamesFinder.java | 3 --- .../sf/jsqlparser/util/TablesNamesFinderTest.java | 12 ++++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 19d0c7d42..c44470534 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -1330,9 +1330,6 @@ public void visit(UseStatement use) { @Override public Void visit(ParenthesedFromItem parenthesis, S context) { - if (parenthesis.getAlias() != null) { - otherItemNames.add(parenthesis.getAlias().getName()); - } parenthesis.getFromItem().accept(this, context); // support join keyword in fromItem visitJoins(parenthesis.getJoins(), context); diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index 5a27f8aa1..7b91f0a96 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -497,5 +497,17 @@ void testSubqueryAliasesIssue1987() throws JSQLParserException { assertThat(tables).containsExactlyInAnyOrder("a", "b"); assertThat(tables).doesNotContain("a1"); } + + @Test + void testSubqueryAliasesIssue2035() throws JSQLParserException { + String sqlStr = "SELECT * FROM (SELECT * FROM A) AS A \n" + + "JOIN B ON A.a = B.a \n" + + "JOIN C ON A.a = C.a;"; + Set tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("A", "B", "C"); + + tables = TablesNamesFinder.findTables(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("B", "C"); + } } From e0ad7c84b688c39d40578755f089b65b1860e67b Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 11 Jul 2024 09:24:25 +0700 Subject: [PATCH 08/88] fix: Multi-Variable `LambdaExpression` - fixes #2030 - fixes #2032 Signed-off-by: Andreas Reichel --- .../expression/LambdaExpression.java | 11 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 84 +++++++++++-------- .../expression/LambdaExpressionTest.java | 18 +++- .../statement/select/oracle-tests/lexer01.sql | 3 +- 4 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java index 78d857287..e2819060f 100644 --- a/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java @@ -9,8 +9,10 @@ */ package net.sf.jsqlparser.expression; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -28,6 +30,15 @@ public LambdaExpression(List identifiers, Expression expression) { this.expression = expression; } + public static LambdaExpression from(ExpressionList expressionList, + Expression expression) { + List identifiers = new ArrayList<>(expressionList.size()); + for (Expression variable : expressionList) { + identifiers.add(variable.toString()); + } + return new LambdaExpression(identifiers, expression); + } + public List getIdentifiers() { return identifiers; } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 581999a38..0c98e4a63 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -912,7 +912,7 @@ Statements Statements() #Statements: { ) - ( + ( LOOKAHEAD(2) ( )* try { ( @@ -1932,7 +1932,7 @@ Column Column() #Column : data = RelObjectNames() [ LOOKAHEAD(2) tk= ] // @todo: we better should return a SEQUENCE instead of a COLUMN - [ "." { data.getNames().add("nextval"); } ] + [ LOOKAHEAD(2) "." { data.getNames().add("nextval"); } ] [ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ] { @@ -4081,12 +4081,24 @@ ParenthesedExpressionList ParenthesedExpressionList(): ExpressionList SimpleExpressionList(): { + ExpressionList columns; ExpressionList expressions = new ExpressionList(); Expression expr; } { expr=SimpleExpression() { expressions.add(expr); } - ( LOOKAHEAD(2, {!interrupted} ) "," ( LOOKAHEAD(2) expr=LambdaExpression() | expr=SimpleExpression()) { expressions.add(expr); } )* + ( + LOOKAHEAD(2, {!interrupted} ) "," + ( + // @todo: Check hot to avoid this expensive look ahead + LOOKAHEAD( LambdaExpression() ) expr=LambdaExpression() + | + expr=SimpleExpression() + ) + { + expressions.add(expr); + } + )* { return expressions; } @@ -4119,6 +4131,7 @@ ParenthesedExpressionList ParenthesedColumnList(): ExpressionList ComplexExpressionList(): { + ExpressionList columns; ExpressionList expressions = new ExpressionList(); Expression expr; } @@ -4135,7 +4148,9 @@ ExpressionList ComplexExpressionList(): LOOKAHEAD(2, {!interrupted}) "," ( LOOKAHEAD(2) expr=OracleNamedFunctionParameter() - | LOOKAHEAD(2) expr=LambdaExpression() + | + // @todo: Check hot to avoid this expensive look ahead + LOOKAHEAD( LambdaExpression() ) expr=LambdaExpression() | expr=Expression() ) { expressions.add(expr); } )* @@ -4378,7 +4393,7 @@ Expression BitwiseXor(): } { leftExpression=PrimaryExpression() { result = leftExpression; } - ( + ( LOOKAHEAD(2) "^" rightExpression=PrimaryExpression() { @@ -4514,6 +4529,16 @@ Expression PrimaryExpression() #PrimaryExpression: | ( list=ParenthesedExpressionList() + // Mutli-Variable Lambda Expression, e. g. + // SELECT map_filter(my_column, (k,v) -> v.my_inner_column = 'some_value') + [ LOOKAHEAD(2) "->" + retval = Expression() + { + retval = LambdaExpression.from(list, retval); + } + ] + + { if (list.size() == 1) { retval = new ParenthesedExpressionList( (Expression) list.getExpressions().get(0)); @@ -4521,7 +4546,10 @@ Expression PrimaryExpression() #PrimaryExpression: retval = list; } } - ["." tmp=RelObjectNameExt() { retval = new RowGetExpression(retval, tmp); }] + + + // RowGet Expression + [ LOOKAHEAD(2) "." tmp=RelObjectNameExt() { retval = new RowGetExpression(retval, tmp); }] ) ) @@ -4535,7 +4563,7 @@ Expression PrimaryExpression() #PrimaryExpression: [ LOOKAHEAD(2) retval = ArrayExpression(retval) ] - ( "::" type=ColDataType() { + ( LOOKAHEAD(2) "::" type=ColDataType() { castExpr = new CastExpression(); castExpr.setUseCastKeyword(false); castExpr.setLeftExpression(retval); @@ -4546,8 +4574,8 @@ Expression PrimaryExpression() #PrimaryExpression: // Check for JSON operands [ - LOOKAHEAD(2) ( - "->" (token= | token=) { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"->")); } + LOOKAHEAD(2) ( + "->" ( token= | token=) { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"->")); } | "->>" (token= | token=) { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"->>")); } | @@ -4784,17 +4812,6 @@ StructType StructType() #StruckType: } } -Expression ParenthesedExpression(): -{ - Expression expression; -} -{ - "(" expression = PrimaryExpression() ")" - { - return new ParenthesedExpressionList(expression); - } -} - JsonExpression JsonExpression(Expression expr, List> idents) : { JsonExpression result = new JsonExpression(expr, idents); Token token; @@ -5453,28 +5470,22 @@ FullTextSearch FullTextSearch() : { LambdaExpression LambdaExpression() #LambdaExpression: { + ExpressionList columns; String s; - ArrayList identifiers = new ArrayList(); Expression expression; LambdaExpression lambdaExpression; } { -// wip, right now the Grammar works but collides with Multi Value Lists -// ( -// LOOKAHEAD(3) "(" -// s = RelObjectName() { identifiers.add(s); } -// ( "," s = RelObjectName() { identifiers.add(s); } )* -// ")" -// ) -// | ( - s = RelObjectName() { identifiers.add(s); } + columns = ParenthesedColumnList() + | + s = RelObjectName() { columns = new ExpressionList(new Column(s)); } ) "->" expression = Expression() { - lambdaExpression = new LambdaExpression(identifiers, expression); + lambdaExpression = LambdaExpression.from(columns, expression); linkAST(lambdaExpression,jjtThis); return lambdaExpression; } @@ -5559,7 +5570,7 @@ Function SimpleFunction(): } } - [ "." ( + [ LOOKAHEAD(2) "." ( // tricky lookahead since we do need to support the following constructs // schema.f1().f2() - Function with Function Column // schema.f1().f2.f3 - Function with Attribute Column @@ -5632,7 +5643,7 @@ Function InternalFunction(boolean escaped): ")" - [ "." ( + [ LOOKAHEAD(2) "." ( // tricky lookahead since we do need to support the following constructs // schema.f1().f2() - Function with Function Column // schema.f1().f2.f3 - Function with Attribute Column @@ -5862,7 +5873,8 @@ CreateSchema CreateSchema(): table.getTable().setSchemaName(schema.getSchemaName()); schema.addStatement(table); } - | view = CreateView(false) + | + view = CreateView(false) { view.getView().setSchemaName(schema.getSchemaName()); schema.addStatement(view); @@ -6209,7 +6221,7 @@ ColDataType ColDataType(): | tk= ) { schema = tk.image; } - [ "." arrayType = ColDataType() { schema += "." + arrayType.toString(); } ] + [ LOOKAHEAD(2) "." arrayType = ColDataType() { schema += "." + arrayType.toString(); } ] { colDataType.setDataType(schema); } ) @@ -7753,7 +7765,7 @@ String IdentifierChain(): } { identifierChain=RelObjectNameExt2() - ( "." part=RelObjectNameExt2() { identifierChain += "." + part; } )* + ( LOOKAHEAD(2) "." part=RelObjectNameExt2() { identifierChain += "." + part; } )* { return identifierChain; diff --git a/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java index 1d51dbe99..c9437437c 100644 --- a/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/LambdaExpressionTest.java @@ -11,7 +11,6 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.test.TestUtils; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -24,10 +23,8 @@ void testLambdaFunctionSingleParameter() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } - @Disabled @Test - // wip, right now the Grammar works but collides with Multi Value Lists - void testLambdaFunctionMultipleParameter() throws JSQLParserException { + void testNestedLambdaFunctionMultipleParameter() throws JSQLParserException { String sqlStr = "SELECT list_transform(\n" + " [1, 2, 3],\n" + " x -> list_reduce([4, 5, 6], (a, b) -> a + b) + x\n" + @@ -35,4 +32,17 @@ void testLambdaFunctionMultipleParameter() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + @Test + void testLambdaMultiParameterIssue2030() throws JSQLParserException { + String sqlStr = "SELECT map_filter(my_column, v -> v.my_inner_column = 'some_value')\n" + + "FROM my_table"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + void testLambdaMultiParameterIssue2032() throws JSQLParserException { + String sqlStr = "SELECT array_sort(array_agg(named_struct('depth', events_union.depth, 'eventtime',events_union.eventtime)), (left, right) -> case when(left.eventtime, left.depth) <(right.eventtime, right.depth) then -1 when(left.eventtime, left.depth) >(right.eventtime, right.depth) then 1 else 0 end) as col1 FROM your_table;"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + } diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/lexer01.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/lexer01.sql index eeceac635..bf0f6c5e9 100644 --- a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/lexer01.sql +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/lexer01.sql @@ -10,4 +10,5 @@ select * from dual where 1 < > 2 and 1 ! = 2 and 1 ^ /*aaa */ = 2 ---@FAILURE: Encountered unexpected token: "=" "=" recorded first on Aug 3, 2021, 7:20:08 AM \ No newline at end of file +--@FAILURE: Encountered unexpected token: "=" "=" recorded first on Aug 3, 2021, 7:20:08 AM +--@FAILURE: Encountered unexpected token: "^" "^" recorded first on Jul 11, 2024, 9:09:49 AM \ No newline at end of file From 11cebcfd122094402548cc8d5b53a063134284f5 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 11 Jul 2024 10:01:35 +0700 Subject: [PATCH 09/88] fix: TablesNamesFinder `UpdateSets` - fixes #2028 Signed-off-by: Andreas Reichel --- .../sf/jsqlparser/util/TablesNamesFinder.java | 14 +++-- .../util/TablesNamesFinderTest.java | 52 +++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index c44470534..8635ecfc2 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -172,6 +172,7 @@ import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; import net.sf.jsqlparser.statement.update.Update; +import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.statement.upsert.Upsert; import java.util.ArrayList; @@ -389,7 +390,7 @@ public Void visit(Table tableName, S context) { @Override public void visit(Table tableName) { - FromItemVisitor.super.visit(tableName); + this.visit(tableName, null); } @Override @@ -984,21 +985,24 @@ public void visit(Delete delete) { @Override public Void visit(Update update, S context) { - visit(update.getTable(), context); if (update.getWithItemsList() != null) { for (WithItem withItem : update.getWithItemsList()) { withItem.accept((SelectVisitor) this, context); } } + visit(update.getTable(), context); + if (update.getStartJoins() != null) { for (Join join : update.getStartJoins()) { join.getRightItem().accept(this, context); } } - if (update.getExpressions() != null) { - for (Expression expression : update.getExpressions()) { - expression.accept(this, context); + + if (update.getUpdateSets() != null) { + for (UpdateSet updateSet : update.getUpdateSets()) { + updateSet.getColumns().accept(this, context); + updateSet.getValues().accept(this, context); } } diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index 7b91f0a96..f3025e02e 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -21,6 +21,8 @@ import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.List; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -509,5 +511,55 @@ void testSubqueryAliasesIssue2035() throws JSQLParserException { tables = TablesNamesFinder.findTables(sqlStr); assertThat(tables).containsExactlyInAnyOrder("B", "C"); } + + @Test + void testTableRenamingIssue2028() throws JSQLParserException { + List IGNORE_SCHEMAS = + Arrays.asList("mysql", "information_schema", "performance_schema"); + final String prefix = "test_"; + + //@formatter:off + String sql = + "UPDATE table_1 a\n" + + "SET a.a1 = ( SELECT b1\n" + + " FROM table_2 b\n" + + " WHERE b.xx = 'xx' )\n" + + " , a.a2 = ( SELECT b2\n" + + " FROM table_2 b\n" + + " WHERE b.yy = 'yy' )\n" + + ";"; + String expected = + "UPDATE test_table_1 a\n" + + "SET a.a1 = ( SELECT b1\n" + + " FROM test_table_2 b\n" + + " WHERE b.xx = 'xx' )\n" + + " , a.a2 = ( SELECT b2\n" + + " FROM test_table_2 b\n" + + " WHERE b.yy = 'yy' )\n" + + ";"; + //@formatter:on + + TablesNamesFinder finder = new TablesNamesFinder() { + @Override + public Void visit(Table tableName, S context) { + String schemaName = tableName.getSchemaName(); + if (schemaName != null && IGNORE_SCHEMAS.contains(schemaName.toLowerCase())) { + return super.visit(tableName, context); + } + String originTableName = tableName.getName(); + tableName.setName(prefix + originTableName); + if (originTableName.startsWith("`")) { + tableName.setName("`" + prefix + originTableName.replace("`", "") + "`"); + } + return super.visit(tableName, context); + } + }; + finder.init(false); + + Statement statement = CCJSqlParserUtil.parse(sql); + statement.accept(finder); + + TestUtils.assertStatementCanBeDeparsedAs(statement, expected, true); + } } From 821e92e8fb6e48e0c6179bc8d7e4b807292f6d2b Mon Sep 17 00:00:00 2001 From: Stefan Steinhauser Date: Sat, 20 Jul 2024 12:35:47 +0200 Subject: [PATCH 10/88] Avoid private tokens to be white listed and allow any word character in token value (#2044) * fix: Avoid private tokens to be white listed Closes JSQLParser/JSqlParser#2040 * feat: Allow all word characters as token value Closes JSQLParser/JSqlParser#2041 --------- Co-authored-by: Stefan Steinhauser --- .../parser/ParserKeywordsUtils.java | 67 +++++++++++++++++-- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 4 +- .../parser/ParserKeywordsUtilsTest.java | 2 +- 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 28acdd793..0c1d89787 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -228,18 +228,73 @@ public static TreeSet getAllKeywordsUsingRegex(File file) throws IOExcep Matcher tokenBlockmatcher = tokenBlockPattern.matcher(content); while (tokenBlockmatcher.find()) { String tokenBlock = tokenBlockmatcher.group(0); - Matcher tokenStringValueMatcher = tokenStringValuePattern.matcher(tokenBlock); - while (tokenStringValueMatcher.find()) { - String tokenValue = tokenStringValueMatcher.group(1); - // test if pure US-ASCII - if (CHARSET_ENCODER.canEncode(tokenValue) && tokenValue.matches("[A-Za-z]+")) { - allKeywords.add(tokenValue); + // remove single and multiline comments + tokenBlock = tokenBlock.replaceAll("(?sm)((\\/\\*.*?\\*\\/)|(\\/\\/.*?$))", ""); + for (String tokenDefinition : getTokenDefinitions(tokenBlock)) { + // check if token definition is private + if (tokenDefinition.matches("(?sm)^<\\s*[^#].*")) { + Matcher tokenStringValueMatcher = tokenStringValuePattern.matcher(tokenDefinition); + while (tokenStringValueMatcher.find()) { + String tokenValue = tokenStringValueMatcher.group(1); + // test if pure US-ASCII + if (CHARSET_ENCODER.canEncode(tokenValue) && tokenValue.matches("\\w+")) { + allKeywords.add(tokenValue); + } + } } } } return allKeywords; } + @SuppressWarnings({"PMD.EmptyWhileStmt"}) + private static List getTokenDefinitions(String tokenBlock) { + List tokenDefinitions = new ArrayList<>(); + int level = 0; + char openChar = '<'; + char closeChar = '>'; + char[] tokenBlockChars = tokenBlock.toCharArray(); + int tokenDefinitionStart = -1; + for (int i = 0; i < tokenBlockChars.length; ++i) { + if (isQuotationMark(i, tokenBlockChars)) { + // skip everything inside quotation marks + while (!isQuotationMark(++i, tokenBlockChars)) { + // skip until quotation ends + } + } + + char character = tokenBlockChars[i]; + if (character == openChar) { + if (level == 0) { + tokenDefinitionStart = i; + } + + ++level; + } else if (character == closeChar) { + --level; + + if (level == 0 && tokenDefinitionStart >= 0) { + tokenDefinitions.add(tokenBlock.substring(tokenDefinitionStart, i + 1)); + tokenDefinitionStart = -1; + } + } + } + + return tokenDefinitions; + } + + private static boolean isQuotationMark(int index, char[] str) { + if (str[index] == '\"') { + // check if quotation is escaped + if (index > 0 && str[index - 1] == '\\') { + return index > 1 && str[index - 2] == '\\'; + } + + return true; + } + + return false; + } public static void buildGrammarForRelObjectNameWithoutValue(File file) throws Exception { Pattern methodBlockPattern = Pattern.compile( diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 0c98e4a63..dcc66acbc 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1957,8 +1957,8 @@ The following tokens are allowed as Names for Schema, Table, Column and Aliases String RelObjectNameWithoutValue() : { Token tk = null; } { - ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GUARD" | tk="HASH" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LOOP" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRECISION" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } diff --git a/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java b/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java index 762620788..2c531e9e9 100644 --- a/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java +++ b/src/test/java/net/sf/jsqlparser/parser/ParserKeywordsUtilsTest.java @@ -52,7 +52,7 @@ class ParserKeywordsUtilsTest { private static void addTokenImage(TreeSet allKeywords, RStringLiteral literal) { - if (CHARSET_ENCODER.canEncode(literal.image) && literal.image.matches("[A-Za-z]+")) { + if (CHARSET_ENCODER.canEncode(literal.image) && literal.image.matches("\\w+")) { allKeywords.add(literal.image); } } From 08254afd69a5a1ff74fd3b4ef6c187ae392dfc90 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sat, 20 Jul 2024 18:00:12 +0700 Subject: [PATCH 11/88] doc: update readme --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3606bf56..cb6658cc6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# [JSqlParser 4.9 Website](https://jsqlparser.github.io/JSqlParser) drawing +# [JSqlParser 5.0 Website](https://jsqlparser.github.io/JSqlParser) drawing ![Build Status](https://github.com/JSQLParser/JSqlParser/actions/workflows/maven.yml/badge.svg) [![Build Status (Legacy)](https://travis-ci.com/JSQLParser/JSqlParser.svg?branch=master)](https://travis-ci.com/JSQLParser/JSqlParser) [![Coverage Status](https://coveralls.io/repos/JSQLParser/JSqlParser/badge.svg?branch=master)](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6f9a2d7eb98f45969749e101322634a1)](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade) @@ -46,7 +46,7 @@ Assertions.assertEquals("b", b.getColumnName()); } ``` -JSQLParser-4.9 is the last JDK8 compatible version. The upcoming JSQLParser-5.0 will depend on JDK11 and introduces API breaking changes to the AST Visitors. Please see the Migration Guide for the details. +JSQLParser-4.9 was the last JDK8 compatible version. The recent JSQLParser-5.0 depends on JDK11 and introduces API breaking changes to the AST Visitors. Please see the Migration Guide for the details. ## [Supported Grammar and Syntax](https://jsqlparser.github.io/JSqlParser/syntax.html) @@ -59,6 +59,14 @@ JSQLParser-4.9 is the last JDK8 compatible version. The upcoming JSQLParser-5.0 **JSqlParser** can also be used to create SQL Statements from Java Code with a fluent API (see [Samples](https://jsqlparser.github.io/JSqlParser/usage.html#build-a-sql-statements)). +## Sister Projects + +If you like JSqlParser then please check out its related projects: + +* [JSQLFormatter](https://manticore-projects.com/JSQLFormatter/index.html) for pretty printing and formatting SQL Text + +* [JSQLTranspiler](https://manticore-projects.com/JSQLTranspiler/index.html) for dialect specific rewriting, SQL Column resolution and Lineage + ## Alternatives to JSqlParser? [**General SQL Parser**](http://www.sqlparser.com/features/introduce.php?utm_source=github-jsqlparser&utm_medium=text-general) looks pretty good, with extended SQL syntax (like PL/SQL and T-SQL) and java + .NET APIs. The tool is commercial (license available online), with a free download option. From 0970312e81cfc7303b6e4275555150e4511a88d5 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sat, 20 Jul 2024 18:12:17 +0700 Subject: [PATCH 12/88] doc: fix the badges --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb6658cc6..083165f7c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # [JSqlParser 5.0 Website](https://jsqlparser.github.io/JSqlParser) drawing -![Build Status](https://github.com/JSQLParser/JSqlParser/actions/workflows/maven.yml/badge.svg) -[![Build Status (Legacy)](https://travis-ci.com/JSQLParser/JSqlParser.svg?branch=master)](https://travis-ci.com/JSQLParser/JSqlParser) [![Coverage Status](https://coveralls.io/repos/JSQLParser/JSqlParser/badge.svg?branch=master)](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6f9a2d7eb98f45969749e101322634a1)](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade) +[![Maven deploy snapshot](https://github.com/JSQLParser/JSqlParser/actions/workflows/maven_deploy.yml/badge.svg)](https://github.com/JSQLParser/JSqlParser/actions/workflows/maven_deploy.yml) +[![Gradle CI](https://github.com/JSQLParser/JSqlParser/actions/workflows/gradle.yml/badge.svg)](https://github.com/JSQLParser/JSqlParser/actions/workflows/gradle.yml) +[![Coverage Status](https://coveralls.io/repos/JSQLParser/JSqlParser/badge.svg?branch=master)](https://coveralls.io/r/JSQLParser/JSqlParser?branch=master) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/6f9a2d7eb98f45969749e101322634a1)](https://www.codacy.com/gh/JSQLParser/JSqlParser/dashboard?utm_source=github.com&utm_medium=referral&utm_content=JSQLParser/JSqlParser&utm_campaign=Badge_Grade) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser/badge.svg)](http://maven-badges.herokuapp.com/maven-central/com.github.jsqlparser/jsqlparser) [![Javadocs](https://www.javadoc.io/badge/com.github.jsqlparser/jsqlparser.svg)](https://www.javadoc.io/doc/com.github.jsqlparser/jsqlparser) [![Gitter](https://badges.gitter.im/JSQLParser/JSqlParser.svg)](https://gitter.im/JSQLParser/JSqlParser?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From 93c8210e218d7f5fa0ea52810c0124da7891f672 Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Tue, 23 Jul 2024 11:27:05 +0900 Subject: [PATCH 13/88] Resolve parsing error for CHARACTER SET and COLLATE in MySQL ALTER TABLE (issue 2027) (#2045) * fix: parsing alter text character set * style: remove unnecessary comment * fix: TEXT as a data type token --------- Co-authored-by: mj-db --- .../jsqlparser/parser/ParserKeywordsUtils.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 12 +++++++++--- .../jsqlparser/statement/alter/AlterTest.java | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 0c1d89787..4668146a3 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -312,7 +312,7 @@ public static void buildGrammarForRelObjectNameWithoutValue(File file) throws Ex + "{ Token tk = null; }\n" + "{\n" // @todo: find a way to avoid those hardcoded compound tokens - + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" + + " ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= \n" + " "); for (String keyword : allKeywords) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index dcc66acbc..46887786d 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -451,6 +451,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | <#TYPE_REAL: "REAL" | "FLOAT4" | "FLOAT"> | <#TYPE_DOUBLE: "DOUBLE" | "PRECISION" | "FLOAT8" | "FLOAT64"> - | <#TYPE_VARCHAR: "NVARCHAR" | "VARCHAR" | "NCHAR" | | "BPCHAR" | "STRING" | "TEXT" | | "VARYING"> + | <#TYPE_VARCHAR: "NVARCHAR" | "VARCHAR" | "NCHAR" | | "BPCHAR" | "TEXT" | "STRING" | | "VARYING"> | <#TYPE_TIME: "TIMETZ" > | <#TYPE_TIMESTAMP: "TIMESTAMP_NS" | "TIMESTAMP_MS" | "TIMESTAMP_S" > @@ -1957,8 +1958,8 @@ The following tokens are allowed as Names for Schema, Table, Column and Aliases String RelObjectNameWithoutValue() : { Token tk = null; } { - ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -6150,6 +6151,11 @@ ColDataType DataType(): } { ( + tk= { + type = tk.image; + return new ColDataType(type, precision, scale); + } + | LOOKAHEAD(2) tk= ( ("<" arrayType = ColDataType() ">") { colDataType.setDataType("ARRAY<" + arrayType.getDataType() + ">"); diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 24995bc3e..36f510dbf 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1023,4 +1023,22 @@ public void testIssue1875() throws JSQLParserException { "ALTER TABLE IF EXISTS usercenter.dict_surgeries ADD COLUMN IF NOT EXISTS operation_grade_id int8 NULL"; assertSqlCanBeParsedAndDeparsed(stmt); } + + @Test + public void testIssue2027() throws JSQLParserException{ + String sql = "ALTER TABLE `foo_bar` ADD COLUMN `baz` text"; + assertSqlCanBeParsedAndDeparsed(sql); + + String sqlText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + assertSqlCanBeParsedAndDeparsed(sqlText); + + String sqlTinyText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + assertSqlCanBeParsedAndDeparsed(sqlTinyText); + + String sqlMediumText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + assertSqlCanBeParsedAndDeparsed(sqlMediumText); + + String sqlLongText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + assertSqlCanBeParsedAndDeparsed(sqlLongText); + } } From 421e2894b226018018509eef139d83ebf676962d Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Tue, 23 Jul 2024 11:15:55 +0700 Subject: [PATCH 14/88] fix: add needed LOOKAHEAD(2) Signed-off-by: Andreas Reichel --- src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 46887786d..a9f977dd9 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6151,7 +6151,7 @@ ColDataType DataType(): } { ( - tk= { + LOOKAHEAD(2) tk= { type = tk.image; return new ColDataType(type, precision, scale); } From e842e18511c65f59f3bbc70f920b1d31f56362e3 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Tue, 23 Jul 2024 11:16:29 +0700 Subject: [PATCH 15/88] fix: license headers Signed-off-by: Andreas Reichel --- .../sf/jsqlparser/expression/NextValExpression.java | 11 ++++++++--- .../statement/create/sequence/CreateSequence.java | 11 ++++++++--- .../util/deparser/CreateSequenceDeParser.java | 11 ++++++++--- .../validation/validator/CreateSequenceValidator.java | 11 ++++++++--- .../validation/validator/CreateSynonymValidator.java | 11 ++++++++--- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java b/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java index 342ad1390..a56723851 100644 --- a/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/NextValExpression.java @@ -1,6 +1,11 @@ -/* - * - #%L JSQLParser library %% Copyright (C) 2004 - 2019 JSQLParser %% Dual licensed under GNU LGPL - * 2.1 or Apache License 2.0 #L% +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% */ package net.sf.jsqlparser.expression; diff --git a/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java b/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java index 7deff2125..0d1c2b7f7 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/sequence/CreateSequence.java @@ -1,6 +1,11 @@ -/* - * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL - * 2.1 or Apache License 2.0 #L% +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% */ package net.sf.jsqlparser.statement.create.sequence; diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java index a97a12cb3..08ea89473 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/CreateSequenceDeParser.java @@ -1,6 +1,11 @@ -/* - * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL - * 2.1 or Apache License 2.0 #L% +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% */ package net.sf.jsqlparser.util.deparser; diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java index 404c58ce2..f2b95d897 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSequenceValidator.java @@ -1,6 +1,11 @@ -/* - * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL - * 2.1 or Apache License 2.0 #L% +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% */ package net.sf.jsqlparser.util.validation.validator; diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java index 7ef2476ed..eb0f9d5c2 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/CreateSynonymValidator.java @@ -1,6 +1,11 @@ -/* - * #%L JSQLParser library %% Copyright (C) 2004 - 2020 JSQLParser %% Dual licensed under GNU LGPL - * 2.1 or Apache License 2.0 #L% +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% */ package net.sf.jsqlparser.util.validation.validator; From 5dcd5bf543d813e2f8f51be6fa7b400796cc39c8 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Tue, 23 Jul 2024 11:17:54 +0700 Subject: [PATCH 16/88] build: set JavaCC options in the Maven build Signed-off-by: Andreas Reichel --- pom.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b35de2067..51a273607 100644 --- a/pom.xml +++ b/pom.xml @@ -206,7 +206,6 @@ org.javacc.plugin javacc-maven-plugin 3.0.3 - javacc @@ -214,13 +213,18 @@ jjtree-javacc + + UTF-8 + false + 1.8 + net.java.dev.javacc javacc - 7.0.13 + [7.0.13,) From aca82f5926b2e955adada1cc50480b3e89bfc994 Mon Sep 17 00:00:00 2001 From: Nick Redfearn <97466325+nick-redfearn@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:52:27 +0100 Subject: [PATCH 17/88] fix truncate parsing to capture multiple tables (#2048) * fix truncate parsing to capture multiple tables * followup fixes including adding a lookahead * replacng tabs with spaces * increasing lookahead * fixing after getting maven working locally --- .../statement/truncate/Truncate.java | 26 ++++- .../util/deparser/StatementDeParser.java | 12 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 23 +++- .../truncate/TruncateMultipleTablesTest.java | 110 ++++++++++++++++++ .../statement/truncate/TruncateTest.java | 29 +++-- 5 files changed, 181 insertions(+), 19 deletions(-) create mode 100644 src/test/java/net/sf/jsqlparser/statement/truncate/TruncateMultipleTablesTest.java diff --git a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java index 4388f3ddd..58442d38e 100644 --- a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java +++ b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java @@ -9,6 +9,9 @@ */ package net.sf.jsqlparser.statement.truncate; +import static java.util.stream.Collectors.joining; + +import java.util.List; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitor; @@ -19,6 +22,7 @@ public class Truncate implements Statement { boolean tableToken; // to support TRUNCATE without TABLE boolean only; // to support TRUNCATE with ONLY private Table table; + private List tables; @Override public T accept(StatementVisitor statementVisitor, S context) { @@ -29,10 +33,18 @@ public Table getTable() { return table; } + public List
getTables() { + return tables; + } + public void setTable(Table table) { this.table = table; } + public void setTables(List
tables) { + this.tables = tables; + } + public boolean getCascade() { return cascade; } @@ -52,8 +64,13 @@ public String toString() { sb.append(" ONLY"); } sb.append(" "); - sb.append(table); - + if (tables != null && !tables.isEmpty()) { + sb.append(tables.stream() + .map(Table::toString) + .collect(joining(", "))); + } else { + sb.append(table); + } if (cascade) { sb.append(" CASCADE"); } @@ -86,6 +103,11 @@ public Truncate withTable(Table table) { return this; } + public Truncate withTables(List
tables) { + this.setTables(tables); + return this; + } + public Truncate withCascade(boolean cascade) { this.setCascade(cascade); return this; diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 30cf27f79..47ecd643d 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -9,9 +9,12 @@ */ package net.sf.jsqlparser.util.deparser; +import static java.util.stream.Collectors.joining; + import java.lang.reflect.InvocationTargetException; import java.util.stream.Collectors; +import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.Block; import net.sf.jsqlparser.statement.Commit; import net.sf.jsqlparser.statement.CreateFunctionalStatement; @@ -180,8 +183,13 @@ public StringBuilder visit(Truncate truncate, S context) { buffer.append(" ONLY"); } buffer.append(" "); - buffer.append(truncate.getTable()); - + if (truncate.getTables() != null && !truncate.getTables().isEmpty()) { + buffer.append(truncate.getTables().stream() + .map(Table::toString) + .collect(joining(", "))); + } else { + buffer.append(truncate.getTable()); + } if (truncate.getCascade()) { buffer.append(" CASCADE"); } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index a9f977dd9..d0e868446 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6617,6 +6617,9 @@ Truncate Truncate(): { Truncate truncate = new Truncate(); Table table; + List
tables = new ArrayList
(); + boolean only = false; + boolean cascade = false; } { /** @@ -6627,14 +6630,24 @@ Truncate Truncate(): * [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ] * */ - [LOOKAHEAD(2) {truncate.setTableToken(true);}] [ {truncate.setOnly(true);}] - table=Table() { truncate.setTable(table); truncate.setCascade(false); } [ {truncate.setCascade(true);} ] - { - return truncate; + + [LOOKAHEAD(2) {truncate.setTableToken(true);}] + [ { only = true; }] + table=Table() { tables.add(table); } (LOOKAHEAD(2) "," table=Table() { tables.add(table); } )* + [ { cascade = true; }] + { + if (only && tables.size() > 1 ) { + throw new ParseException("Cannot TRUNCATE ONLY with multiple tables"); + } else { + return truncate + .withTables(tables) + .withTable(table) + .withOnly(only) + .withCascade(cascade); + } } } - AlterExpression.ColumnDataType AlterExpressionColumnDataType(): { String columnName = null; diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateMultipleTablesTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateMultipleTablesTest.java new file mode 100644 index 000000000..18894c8ca --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateMultipleTablesTest.java @@ -0,0 +1,110 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2019 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.truncate; + +import static net.sf.jsqlparser.test.TestUtils.assertDeparse; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.StringReader; +import java.util.List; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserManager; +import net.sf.jsqlparser.schema.Table; +import org.junit.jupiter.api.Test; + +public class TruncateMultipleTablesTest { + + private CCJSqlParserManager parserManager = new CCJSqlParserManager(); + + @Test + public void testTruncate2Tables() throws Exception { + String statement = "TRUncATE TABLE myschema.mytab, myschema2.mytab2"; + Truncate truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("myschema2", truncate.getTable().getSchemaName()); + assertEquals("myschema2.mytab2", truncate.getTable().getFullyQualifiedName()); + assertEquals(statement.toUpperCase(), truncate.toString().toUpperCase()); + assertEquals("myschema.mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("myschema2.mytab2", truncate.getTables().get(1).getFullyQualifiedName()); + + statement = "TRUncATE TABLE mytab, my2ndtab"; + String toStringStatement = "TRUncATE TABLE mytab, my2ndtab"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("my2ndtab", truncate.getTable().getName()); + assertEquals(toStringStatement.toUpperCase(), truncate.toString().toUpperCase()); + assertEquals("mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("my2ndtab", truncate.getTables().get(1).getFullyQualifiedName()); + + statement = "TRUNCATE TABLE mytab, my2ndtab CASCADE"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertNull(truncate.getTables().get(0).getSchemaName()); + assertEquals("mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("my2ndtab", truncate.getTables().get(1).getFullyQualifiedName()); + assertTrue(truncate.getCascade()); + assertEquals(statement, truncate.toString()); + } + + @Test + public void testTruncatePostgresqlWithoutTableNames() throws Exception { + String statement = "TRUncATE myschema.mytab, myschema2.mytab2"; + Truncate truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("myschema2", truncate.getTable().getSchemaName()); + assertEquals("myschema2.mytab2", truncate.getTable().getFullyQualifiedName()); + assertEquals(statement.toUpperCase(), truncate.toString().toUpperCase()); + assertEquals("myschema.mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("myschema2.mytab2", truncate.getTables().get(1).getFullyQualifiedName()); + + statement = "TRUncATE mytab, my2ndtab"; + String toStringStatement = "TRUncATE mytab, my2ndtab"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("my2ndtab", truncate.getTable().getName()); + assertEquals(toStringStatement.toUpperCase(), truncate.toString().toUpperCase()); + assertEquals("mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("my2ndtab", truncate.getTables().get(1).getFullyQualifiedName()); + + statement = "TRUNCATE mytab, my2ndtab CASCADE"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertNull(truncate.getTables().get(0).getSchemaName()); + assertEquals("mytab", truncate.getTables().get(0).getFullyQualifiedName()); + assertEquals("my2ndtab", truncate.getTables().get(1).getFullyQualifiedName()); + assertTrue(truncate.getCascade()); + assertEquals(statement, truncate.toString()); + } + + @Test + public void testTruncateDeparse() throws JSQLParserException { + String statement = "TRUNCATE TABLE foo, bar"; + assertSqlCanBeParsedAndDeparsed(statement); + assertDeparse(new Truncate() + .withTables(List.of(new Table("foo"), new Table("bar"))) + .withTableToken(true), statement); + } + + @Test + public void testTruncateCascadeDeparse() throws JSQLParserException { + String statement = "TRUNCATE TABLE foo, bar CASCADE"; + assertSqlCanBeParsedAndDeparsed(statement); + assertDeparse(new Truncate() + .withTables(List.of(new Table("foo"), new Table("bar"))) + .withTableToken(true) + .withCascade(true), statement); + } + + @Test + public void testTruncateDoesNotAllowOnlyWithMultipleTables() { + String statement = "TRUNCATE TABLE ONLY foo, bar"; + assertThrows(JSQLParserException.class, + () -> parserManager.parse(new StringReader(statement))); + } + +} diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java index 036aa64ad..5d8db40f6 100644 --- a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java @@ -71,8 +71,8 @@ public void testTruncateDeparse() throws JSQLParserException { String statement = "TRUNCATE TABLE foo"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse(new Truncate() - .withTable(new Table("foo")) - .withTableToken(true), statement); + .withTable(new Table("foo")) + .withTableToken(true), statement); } @Test @@ -80,19 +80,28 @@ public void testTruncateCascadeDeparse() throws JSQLParserException { String statement = "TRUNCATE TABLE foo CASCADE"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse(new Truncate() - .withTable(new Table("foo")) - .withTableToken(true) - .withCascade(true), statement); + .withTable(new Table("foo")) + .withTableToken(true) + .withCascade(true), statement); } @Test public void testTruncateOnlyDeparse() throws JSQLParserException { - String statement = "TRUNCATE TABLE ONLY foo CASCADE"; + String statement = "TRUNCATE TABLE ONLY foo"; assertSqlCanBeParsedAndDeparsed(statement); assertDeparse(new Truncate() - .withTable(new Table("foo")) - .withCascade(true) - .withTableToken(true) - .withOnly(true), statement); + .withTable(new Table("foo")) + .withTableToken(true) + .withOnly(true), statement); + } + + @Test + public void testTruncateOnlyAndCascadeDeparse() throws JSQLParserException { + String statement = "TRUNCATE ONLY foo CASCADE"; + assertSqlCanBeParsedAndDeparsed(statement); + assertDeparse(new Truncate() + .withTable(new Table("foo")) + .withCascade(true) + .withOnly(true), statement); } } From dc14c4b4e1401f4f0c96b7238f4b07e8cee3008d Mon Sep 17 00:00:00 2001 From: nicky6s Date: Sat, 27 Jul 2024 19:53:54 +0100 Subject: [PATCH 18/88] fix insert default values statements not parsing (#2050) --- .../parser/ParserKeywordsUtils.java | 1 + .../jsqlparser/statement/insert/Insert.java | 19 ++++++- .../util/deparser/InsertDeParser.java | 5 ++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 6 ++- src/site/sphinx/keywords.rst | 4 +- .../statement/insert/InsertTest.java | 52 +++++++++++++++++++ .../statement/truncate/TruncateTest.java | 9 ++++ 7 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 4668146a3..7491a9c36 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -60,6 +60,7 @@ public class ParserKeywordsUtils { {"CREATE", RESTRICTED_ALIAS}, {"CROSS", RESTRICTED_SQL2016}, {"CURRENT", RESTRICTED_JSQLPARSER}, + {"DEFAULT", RESTRICTED_ALIAS}, {"DISTINCT", RESTRICTED_SQL2016}, {"DOUBLE", RESTRICTED_ALIAS}, {"ELSE", RESTRICTED_JSQLPARSER}, diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index cdb16be05..287d96574 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -37,6 +37,7 @@ public class Insert implements Statement { private OracleHint oracleHint = null; private ExpressionList columns; private Select select; + private boolean onlyDefaultValues = false; private List duplicateUpdateSets = null; private InsertModifierPriority modifierPriority = null; private boolean modifierIgnore = false; @@ -162,7 +163,6 @@ public void setModifierIgnore(boolean modifierIgnore) { this.modifierIgnore = modifierIgnore; } - @Deprecated public boolean isUseSet() { return setUpdateSets != null && !setUpdateSets.isEmpty(); @@ -176,6 +176,19 @@ public void setWithItemsList(List withItemsList) { this.withItemsList = withItemsList; } + public boolean isOnlyDefaultValues() { + return onlyDefaultValues; + } + + public void setOnlyDefaultValues(boolean onlyDefaultValues) { + this.onlyDefaultValues = onlyDefaultValues; + } + + public Insert withOnlyDefaultValues(boolean onlyDefaultValues) { + this.setOnlyDefaultValues(onlyDefaultValues); + return this; + } + public InsertConflictTarget getConflictTarget() { return conflictTarget; } @@ -230,6 +243,10 @@ public String toString() { sql.append("INTO "); sql.append(table).append(" "); + if (onlyDefaultValues) { + sql.append("DEFAULT VALUES"); + } + if (columns != null) { sql.append("("); for (int i = 0; i < columns.size(); i++) { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index 6156171dc..b3f8e4abb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -64,6 +64,11 @@ public void deParse(Insert insert) { buffer.append("INTO "); buffer.append(insert.getTable().toString()); + + if (insert.isOnlyDefaultValues()) { + buffer.append(" DEFAULT VALUES"); + } + if (insert.getColumns() != null) { buffer.append(" ("); for (Iterator iter = insert.getColumns().iterator(); iter.hasNext();) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index d0e868446..285b42185 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1602,6 +1602,8 @@ Insert Insert( List with ): [ outputClause = OutputClause() { insert.setOutputClause(outputClause); } ] ( + { insert.setOnlyDefaultValues(true); } + | ( updateSets = UpdateSets() { insert.withSetUpdateSets(updateSets); } ) @@ -1959,7 +1961,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFAULT" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -1973,7 +1975,7 @@ String RelObjectName() : (result = RelObjectNameWithoutValue() | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk= + | tk= | tk= ) { return tk!=null ? tk.image : result; } diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index 91437ece5..78c17aa0b 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -37,7 +37,9 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | CURRENT | Yes | Yes | +----------------------+-------------+-----------+ -| DISTINCT | Yes | Yes | +| DEFAULT | Yes | | ++----------------------+-------------+-----------+ +| DISTINCT | Yes | Yes | +----------------------+-------------+-----------+ | DOUBLE | Yes | | +----------------------+-------------+-----------+ diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 8e3704dd1..36ec76165 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.insert; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.DoubleValue; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.JdbcParameter; @@ -590,4 +591,55 @@ void testMultiColumnConflictTargetIssue955() throws JSQLParserException { + "on conflict(xxx0, xxx1) do update set xxx1=?, update_time=?"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + public void testDefaultValues() throws JSQLParserException { + String statement = "INSERT INTO mytable DEFAULT VALUES"; + //assertSqlCanBeParsedAndDeparsed(statement); + Insert insert = (Insert) parserManager.parse(new StringReader(statement)); + assertEquals("mytable", insert.getTable().getFullyQualifiedName()); + assertEquals("INSERT INTO MYTABLE DEFAULT VALUES", insert.toString().toUpperCase()); + assertTrue(insert.isOnlyDefaultValues()); + assertDeparse(new Insert() + .withTable(new Table("mytable")) + .withOnlyDefaultValues(true), statement); + } + + @Test + public void testDefaultValuesWithAlias() throws JSQLParserException { + String statement = "INSERT INTO mytable x DEFAULT VALUES"; + assertSqlCanBeParsedAndDeparsed(statement); + Insert insert = (Insert) parserManager.parse(new StringReader(statement)); + assertEquals("mytable", insert.getTable().getFullyQualifiedName()); + assertEquals("INSERT INTO MYTABLE X DEFAULT VALUES", insert.toString().toUpperCase()); + assertEquals("x", insert.getTable().getAlias().getName()); + assertTrue(insert.isOnlyDefaultValues()); + assertDeparse(new Insert() + .withTable(new Table("mytable") + .withAlias(new Alias("x").withUseAs(false))) + .withOnlyDefaultValues(true), statement); + } + + @Test + public void testDefaultValuesWithAliasAndAs() throws JSQLParserException { + String statement = "INSERT INTO mytable AS x DEFAULT VALUES"; + assertSqlCanBeParsedAndDeparsed(statement); + Insert insert = (Insert) parserManager.parse(new StringReader(statement)); + assertEquals("mytable", insert.getTable().getFullyQualifiedName()); + assertEquals("INSERT INTO MYTABLE AS X DEFAULT VALUES", insert.toString().toUpperCase()); + assertEquals("x", insert.getTable().getAlias().getName()); + assertTrue(insert.isOnlyDefaultValues()); + assertDeparse(new Insert() + .withTable(new Table("mytable") + .withAlias(new Alias("x").withUseAs(true))) + .withOnlyDefaultValues(true), statement); + } + + @Test + public void throwsParseWhenDefaultKeyowrdUsedAsAlias() { + String statement = "INSERT INTO mytable default DEFAULT VALUES"; + assertThrows(JSQLParserException.class, + () -> parserManager.parse(new StringReader(statement))); + } + } diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java index 5d8db40f6..698d2a5b8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java @@ -18,6 +18,7 @@ import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; @@ -104,4 +105,12 @@ public void testTruncateOnlyAndCascadeDeparse() throws JSQLParserException { .withCascade(true) .withOnly(true), statement); } + + @Test + public void throwsParseWhenOnlyUsedWithMultipleTables() { + String statement = "TRUNCATE TABLE ONLY foo, bar"; + assertThrows(JSQLParserException.class, + () -> parserManager.parse(new StringReader(statement))); + } + } From e9e157b65efd1987aca6d8ef5ba82cc54daa5ee4 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sun, 28 Jul 2024 10:25:22 +0700 Subject: [PATCH 19/88] style: fix minor Q/A exceptions Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../net/sf/jsqlparser/util/deparser/StatementDeParser.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 47ecd643d..9de8fb777 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -9,8 +9,6 @@ */ package net.sf.jsqlparser.util.deparser; -import static java.util.stream.Collectors.joining; - import java.lang.reflect.InvocationTargetException; import java.util.stream.Collectors; @@ -185,8 +183,8 @@ public StringBuilder visit(Truncate truncate, S context) { buffer.append(" "); if (truncate.getTables() != null && !truncate.getTables().isEmpty()) { buffer.append(truncate.getTables().stream() - .map(Table::toString) - .collect(joining(", "))); + .map(Table::toString) + .collect(Collectors.joining(", "))); } else { buffer.append(truncate.getTable()); } From 79dc30f01c2ae567ff00729c14c046b2efe9488d Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sun, 28 Jul 2024 10:29:14 +0700 Subject: [PATCH 20/88] style: fix minor Q/A exceptions Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../java/net/sf/jsqlparser/util/deparser/StatementDeParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 9de8fb777..17babd34e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -306,7 +306,7 @@ public StringBuilder visit(ShowTablesStatement showTables, S context) { public StringBuilder visit(Block block, S context) { buffer.append("BEGIN\n"); if (block.getStatements() != null) { - for (Statement stmt : block.getStatements().getStatements()) { + for (Statement stmt : block.getStatements()) { stmt.accept(this, context); buffer.append(";\n"); } From 21c605e3e2f5f52e5b581f6350f39c943af7978b Mon Sep 17 00:00:00 2001 From: nicky6s Date: Wed, 31 Jul 2024 20:19:08 +0100 Subject: [PATCH 21/88] chore adding extra details to unit test scenarios (#2051) * chore adding extra details to unit test scenarios * addressing review comments --- .../statement/delete/DeleteTest.java | 19 ++- .../statement/insert/InsertTest.java | 94 ++++++++--- .../statement/select/SelectTest.java | 155 ++++++++++++++---- .../statement/update/UpdateTest.java | 20 ++- 4 files changed, 227 insertions(+), 61 deletions(-) diff --git a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java index a528035c8..c9a3030aa 100644 --- a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java @@ -10,6 +10,8 @@ package net.sf.jsqlparser.statement.delete; import java.io.StringReader; +import java.util.List; + import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; @@ -22,6 +24,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; + +import net.sf.jsqlparser.statement.select.SelectItem; +import net.sf.jsqlparser.statement.select.WithItem; import org.junit.jupiter.api.Test; public class DeleteTest { @@ -118,8 +123,18 @@ public void testWith() throws JSQLParserException { + "DELETE FROM cfe.instrument_ref\n" + "WHERE id_instrument_ref = (SELECT id_instrument_ref\n" + " FROM a)"; - - assertSqlCanBeParsedAndDeparsed(statement, true); + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(statement, true); + List withItems = delete.getWithItemsList(); + assertEquals("cfe.instrument_ref", delete.getTable().getFullyQualifiedName()); + assertEquals(2, withItems.size()); + SelectItem selectItem1 = withItems.get(0).getSelect().getPlainSelect().getSelectItems().get(0); + assertEquals("1", selectItem1.getExpression().toString()); + assertEquals(" id_instrument_ref", selectItem1.getAlias().toString()); + assertEquals(" a", withItems.get(0).getAlias().toString()); + SelectItem selectItem2 = withItems.get(1).getSelect().getPlainSelect().getSelectItems().get(0); + assertEquals("1", selectItem2.getExpression().toString()); + assertEquals(" id_instrument_ref", selectItem2.getAlias().toString()); + assertEquals(" b", withItems.get(1).getAlias().toString()); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 36ec76165..3bec29069 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -16,23 +16,23 @@ import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.select.AllColumns; -import net.sf.jsqlparser.statement.select.PlainSelect; -import net.sf.jsqlparser.statement.select.Select; -import net.sf.jsqlparser.statement.select.Values; +import net.sf.jsqlparser.statement.select.*; import net.sf.jsqlparser.statement.update.UpdateSet; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import java.io.StringReader; +import java.util.List; +import static junit.framework.Assert.assertNull; import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -277,12 +277,26 @@ public void testInsertSelect() throws JSQLParserException { @Test public void testInsertWithSelect() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a", - true); - assertSqlCanBeParsedAndDeparsed( - "INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)", - true); + String sqlStr1 = "INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a"; + Insert insert1 = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr1, true); + List insertWithItems1 = insert1.getWithItemsList(); + List selectWithItems1 = insert1.getSelect().getWithItemsList(); + assertEquals("mytable", insert1.getTable().getFullyQualifiedName()); + assertNull(insertWithItems1); + assertEquals(1, selectWithItems1.size()); + assertEquals("SELECT mycolumn FROM mytable", selectWithItems1.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" a", selectWithItems1.get(0).getAlias().toString()); + + String sqlStr2 = "INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)"; + Insert insert2 = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr2, true); + List insertWithItems2 = insert2.getWithItemsList(); + assertEquals("mytable", insert2.getTable().getFullyQualifiedName()); + assertNull(insertWithItems2); + ParenthesedSelect select = (ParenthesedSelect) insert2.getSelect(); + List selectWithItems2 = select.getSelect().getWithItemsList(); + assertEquals(1, selectWithItems2.size()); + assertEquals("SELECT mycolumn FROM mytable", selectWithItems2.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" a", selectWithItems2.get(0).getAlias().toString()); } @Test @@ -348,9 +362,15 @@ public void testKeywordPrecisionIssue363() throws JSQLParserException { @Test public void testWithDeparsingIssue406() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "insert into mytab3 (a,b,c) select a,b,c from mytab where exists(with t as (select * from mytab2) select * from t)", - true); + String sqlStr = "insert into mytab3 (a,b,c) select a,b,c from mytab where exists(with t as (select * from mytab2) select * from t)"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List insertWithItems = insert.getWithItemsList(); + List selectWithItems = insert.getSelect().getWithItemsList(); + assertEquals("mytab3", insert.getTable().getFullyQualifiedName()); + assertNull(insertWithItems); + assertNull(selectWithItems); + ExistsExpression exists = (ExistsExpression) insert.getPlainSelect().getWhere(); + assertEquals("(WITH t AS (SELECT * FROM mytab2) SELECT * FROM t)", exists.getRightExpression().toString()); } @Test @@ -390,9 +410,16 @@ public void testInsertKeyWordIntervalIssue682() throws JSQLParserException { @Test public void testWithAtFront() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo", - true); + String sqlStr = "WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List insertWithItems = insert.getWithItemsList(); + assertEquals("lalelu", insert.getTable().getFullyQualifiedName()); + assertEquals(1, insertWithItems.size()); + assertEquals("SELECT attr FROM bar", insertWithItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" foo", insertWithItems.get(0).getAlias().toString()); + assertEquals("SELECT attr FROM foo", insert.getSelect().toString()); + assertEquals("foo", insert.getSelect().getPlainSelect().getFromItem().toString()); + assertEquals("[attr]", insert.getSelect().getPlainSelect().getSelectItems().toString()); } @Test @@ -427,8 +454,16 @@ public void testDisableKeywordIssue945() throws JSQLParserException { @Test public void testWithListIssue282() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH myctl AS (SELECT a, b FROM mytable) INSERT INTO mytable SELECT a, b FROM myctl"); + String sqlStr = "WITH myctl AS (SELECT a, b FROM mytable) INSERT INTO mytable SELECT a, b FROM myctl"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List insertWithItems = insert.getWithItemsList(); + assertEquals("mytable", insert.getTable().getFullyQualifiedName()); + assertEquals(1, insertWithItems.size()); + assertEquals("SELECT a, b FROM mytable", insertWithItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" myctl", insertWithItems.get(0).getAlias().toString()); + assertEquals("SELECT a, b FROM myctl", insert.getSelect().toString()); + assertEquals("myctl", insert.getSelect().getPlainSelect().getFromItem().toString()); + assertEquals("[a, b]", insert.getSelect().getPlainSelect().getSelectItems().toString()); } @Test @@ -468,8 +503,18 @@ public void testInsertUnionSelectIssue1491() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("insert into table1 (tf1,tf2,tf2)\n" + "((select sf1,sf2,sf3 from s1)" + "union " + "(select rf1,rf2,rf2 from r1))", true); + } - assertSqlCanBeParsedAndDeparsed("(with a as (select * from dual) select * from a)", true); + @Test + public void testWithSelectFromDual() throws JSQLParserException { + String sqlStr = "(with a as (select * from dual) select * from a)"; + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List withItems = parenthesedSelect.getSelect().getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("SELECT * FROM dual", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" a", withItems.get(0).getAlias().toString()); + assertEquals("a", parenthesedSelect.getPlainSelect().getFromItem().toString()); + assertEquals("[*]", parenthesedSelect.getPlainSelect().getSelectItems().toString()); } @Test @@ -528,6 +573,11 @@ public void insertOnConflictObjectsTest() throws JSQLParserException { String sqlStr = "WITH a ( a, b , c ) \n" + "AS (SELECT 1 , 2 , 3 )\n" + "insert into test\n" + "select * from a"; Insert insert = (Insert) CCJSqlParserUtil.parse(sqlStr); + List withItems = insert.getWithItemsList(); + assertEquals("test", insert.getTable().getFullyQualifiedName()); + assertEquals(1, withItems.size()); + assertEquals("[1, 2, 3]", withItems.get(0).getSelect().getPlainSelect().getSelectItems().toString()); + assertEquals(" a", withItems.get(0).getAlias().toString()); Expression whereExpression = CCJSqlParserUtil.parseExpression("a=1", false); Expression valueExpression = CCJSqlParserUtil.parseExpression("b/2", false); @@ -608,8 +658,7 @@ public void testDefaultValues() throws JSQLParserException { @Test public void testDefaultValuesWithAlias() throws JSQLParserException { String statement = "INSERT INTO mytable x DEFAULT VALUES"; - assertSqlCanBeParsedAndDeparsed(statement); - Insert insert = (Insert) parserManager.parse(new StringReader(statement)); + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(statement); assertEquals("mytable", insert.getTable().getFullyQualifiedName()); assertEquals("INSERT INTO MYTABLE X DEFAULT VALUES", insert.toString().toUpperCase()); assertEquals("x", insert.getTable().getAlias().getName()); @@ -623,8 +672,7 @@ public void testDefaultValuesWithAlias() throws JSQLParserException { @Test public void testDefaultValuesWithAliasAndAs() throws JSQLParserException { String statement = "INSERT INTO mytable AS x DEFAULT VALUES"; - assertSqlCanBeParsedAndDeparsed(statement); - Insert insert = (Insert) parserManager.parse(new StringReader(statement)); + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(statement); assertEquals("mytable", insert.getTable().getFullyQualifiedName()); assertEquals("INSERT INTO MYTABLE AS X DEFAULT VALUES", insert.toString().toUpperCase()); assertEquals("x", insert.getTable().getAlias().getName()); 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 4111ba34a..e000a6346 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -1701,13 +1701,24 @@ public void testWith() throws JSQLParserException { + "SELECT THIS_EMP.EMPNO, THIS_EMP.SALARY, DINFO.AVGSALARY, DINFO.EMPCOUNT, DINFOMAX.AVGMAX " + "FROM EMPLOYEE AS THIS_EMP INNER JOIN DINFO INNER JOIN DINFOMAX " + "WHERE THIS_EMP.JOB = 'SALESREP' AND THIS_EMP.WORKDEPT = DINFO.DEPTNO"; - assertSqlCanBeParsedAndDeparsed(statement); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(statement); + List withItems = select.getWithItemsList(); + assertEquals(2, withItems.size()); + assertEquals("SELECT OTHERS.WORKDEPT, AVG(OTHERS.SALARY), COUNT(*) FROM EMPLOYEE AS OTHERS GROUP BY OTHERS.WORKDEPT", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" DINFO", withItems.get(0).getAlias().toString()); + assertEquals("SELECT MAX(AVGSALARY) AS AVGMAX FROM DINFO", withItems.get(1).getSelect().getPlainSelect().toString()); + assertEquals(" DINFOMAX", withItems.get(1).getAlias().toString()); } @Test public void testWithRecursive() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH RECURSIVE t (n) AS ((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100)) SELECT sum(n) FROM t"); + String statement = "WITH RECURSIVE t (n) AS ((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100)) SELECT sum(n) FROM t"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(statement); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100))", withItems.get(0).getSelect().toString()); + assertEquals(" t", withItems.get(0).getAlias().toString()); + assertTrue(withItems.get(0).isRecursive()); } @Test @@ -2361,7 +2372,11 @@ public void testProblemSqlCombinedSets() throws Exception { public void testWithStatement() throws JSQLParserException { String stmt = "WITH test AS (SELECT mslink FROM feature) SELECT * FROM feature WHERE mslink IN (SELECT mslink FROM test)"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("SELECT mslink FROM feature", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" test", withItems.get(0).getAlias().toString()); } @Test @@ -2374,35 +2389,55 @@ public void testSubjoinWithJoins() throws JSQLParserException { public void testWithUnionProblem() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink FROM tablea) UNION (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT mslink FROM tablea) UNION (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals(" test", withItems.get(0).getAlias().toString()); } @Test public void testWithUnionAllProblem() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink FROM tablea) UNION ALL (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT mslink FROM tablea) UNION ALL (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals(" test", withItems.get(0).getAlias().toString()); } @Test public void testWithUnionProblem3() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink, CAST(tablea.fname AS varchar) FROM tablea INNER JOIN tableb ON tablea.mslink = tableb.mslink AND tableb.deleted = 0 WHERE tablea.fname IS NULL AND 1 = 0) UNION ALL (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT mslink, CAST(tablea.fname AS varchar) FROM tablea INNER JOIN tableb ON tablea.mslink = tableb.mslink AND tableb.deleted = 0 WHERE tablea.fname IS NULL AND 1 = 0) UNION ALL (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals(" test", withItems.get(0).getAlias().toString()); } @Test public void testWithUnionProblem4() throws JSQLParserException { String stmt = "WITH hist AS ((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0)) SELECT mslink, space(level * 4) + txt AS txt, nr, feature, path FROM hist WHERE EXISTS (SELECT feature FROM tablec WHERE mslink = 0 AND ((feature IN (1, 2) AND hist.feature = 3) OR (feature IN (4) AND hist.feature = 2)))"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", withItems.get(0).getSelect().toString()); + assertEquals(" hist", withItems.get(0).getAlias().toString()); } @Test public void testWithUnionProblem5() throws JSQLParserException { String stmt = "WITH hist AS ((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, 5 AS feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0)) SELECT * FROM hist"; - assertSqlCanBeParsedAndDeparsed(stmt); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, 5 AS feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", withItems.get(0).getSelect().toString()); + assertEquals(" hist", withItems.get(0).getAlias().toString()); } @Test @@ -3129,8 +3164,15 @@ public void testSelectOracleColl() throws JSQLParserException { @Test public void testSelectInnerWith() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "SELECT * FROM (WITH actor AS (SELECT 'a' aid FROM DUAL) SELECT aid FROM actor)"); + String stmt = "SELECT * FROM (WITH actor AS (SELECT 'a' aid FROM DUAL) SELECT aid FROM actor)"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems1 = select.getWithItemsList(); + assertNull(withItems1); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) select.getPlainSelect().getFromItem(); + List withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); + assertEquals(1, withItems2.size()); + assertEquals("(SELECT 'a' aid FROM DUAL)", withItems2.get(0).getSelect().toString()); + assertEquals(" actor", withItems2.get(0).getAlias().toString()); } // @Test @@ -3138,10 +3180,15 @@ public void testSelectInnerWith() throws JSQLParserException { // assertSqlCanBeParsedAndDeparsed("WITH actor AS (SELECT 'b' aid FROM DUAL) SELECT aid FROM // actor UNION WITH actor2 AS (SELECT 'a' aid FROM DUAL) SELECT aid FROM actor2"); // } + @Test public void testSelectInnerWithAndUnionIssue1084_2() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH actor AS (SELECT 'b' aid FROM DUAL) SELECT aid FROM actor UNION SELECT aid FROM actor2"); + String stmt = "WITH actor AS (SELECT 'b' aid FROM DUAL) SELECT aid FROM actor UNION SELECT aid FROM actor2"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("(SELECT 'b' aid FROM DUAL)", withItems.get(0).getSelect().toString()); + assertEquals(" actor", withItems.get(0).getAlias().toString()); } @Test @@ -4531,8 +4578,15 @@ public void testEmptyDoubleQuotes_2() throws JSQLParserException { @Test public void testInnerWithBlock() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "select 1 from (with mytable1 as (select 2 ) select 3 from mytable1 ) first", true); + String stmt = "select 1 from (with mytable1 as (select 2 ) select 3 from mytable1 ) first"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); + List withItems1 = select.getWithItemsList(); + assertNull(withItems1); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) select.getPlainSelect().getFromItem(); + List withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); + assertEquals(1, withItems2.size()); + assertEquals("(SELECT 2)", withItems2.get(0).getSelect().toString()); + assertEquals(" mytable1", withItems2.get(0).getAlias().toString()); } @Test @@ -4674,8 +4728,12 @@ public void testPartitionByWithBracketsIssue865() throws JSQLParserException { @Test public void testWithAsRecursiveIssue874() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH rn AS (SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1)) SELECT pname FROM t1, rn WHERE rn <= cases ORDER BY pname"); + String stmt = "WITH rn AS (SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1)) SELECT pname FROM t1, rn WHERE rn <= cases ORDER BY pname"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("(SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1))", withItems.get(0).getSelect().toString()); + assertEquals(" rn", withItems.get(0).getAlias().toString()); } @Test @@ -5112,8 +5170,12 @@ public void testProblematicDeparsingIssue1183_2() throws JSQLParserException { @Test public void testKeywordCostsIssue1185() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH costs AS (SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1) SELECT * FROM TESTSTMT"); + String stmt = "WITH costs AS (SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1) SELECT * FROM TESTSTMT"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("(SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1)", withItems.get(0).getSelect().toString()); + assertEquals(" costs", withItems.get(0).getAlias().toString()); } @Test @@ -5128,25 +5190,44 @@ public void testConditionsWithExtraBrackets_Issue1194() throws JSQLParserExcepti @Test public void testWithValueListWithExtraBrackets1135() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) select day, value from sample_data", - true); + String stmt = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) select day, value from sample_data"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals("VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))", withItems.get(0).getSelect().getValues().toString()); + assertEquals(" sample_data", withItems.get(0).getAlias().toString()); } @Test public void testWithValueListWithOutExtraBrackets1135() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("with sample_data(\"DAY\") as (values 0, 1, 2)\n" - + " select \"DAY\" from sample_data", true); - assertSqlCanBeParsedAndDeparsed( - "with sample_data(day, value) as (values (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)) select day, value from sample_data", - true); + String stmt1 = "with sample_data(\"DAY\") as (values 0, 1, 2)\n" + + " select \"DAY\" from sample_data"; + Select select1 = (Select) assertSqlCanBeParsedAndDeparsed(stmt1, true); + List withItems1 = select1.getWithItemsList(); + assertEquals(1, withItems1.size()); + assertEquals("VALUES 0, 1, 2", withItems1.get(0).getSelect().getValues().toString()); + assertEquals(" sample_data", withItems1.get(0).getAlias().toString()); + + String stmt2 = "with sample_data(day, value) as (values (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)) select day, value from sample_data"; + Select select2 = (Select) assertSqlCanBeParsedAndDeparsed(stmt2, true); + List withItems2 = select2.getWithItemsList(); + assertEquals(1, withItems2.size()); + assertEquals("VALUES (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)", withItems2.get(0).getSelect().getValues().toString()); + assertEquals(" sample_data", withItems2.get(0).getAlias().toString()); } @Test public void testWithInsideWithIssue1186() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "WITH TESTSTMT1 AS ( WITH TESTSTMT2 AS (SELECT * FROM MY_TABLE2) SELECT col1, col2 FROM TESTSTMT2) SELECT * FROM TESTSTMT", - true); + String stmt = "WITH TESTSTMT1 AS ( WITH TESTSTMT2 AS (SELECT * FROM MY_TABLE2) SELECT col1, col2 FROM TESTSTMT2) SELECT * FROM TESTSTMT"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals(" TESTSTMT1", withItems.get(0).getAlias().toString()); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItems.get(0).getSelect(); + List withItems2 = parenthesedSelect.getSelect().getWithItemsList(); + assertEquals(1, withItems2.size()); + assertEquals("(SELECT * FROM MY_TABLE2)", withItems2.get(0).getSelect().toString()); + assertEquals(" TESTSTMT2", withItems2.get(0).getAlias().toString()); } @Test @@ -5649,7 +5730,19 @@ void testSetOperationListWithBracketsIssue1737() throws JSQLParserException { void testNestedWithItems() throws JSQLParserException { String sqlStr = "with a as ( with b as ( with c as (select 1) select c.* from c) select b.* from b) select a.* from a"; - TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + assertEquals(" a", withItems.get(0).getAlias().toString()); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItems.get(0).getSelect(); + List withItems2 = parenthesedSelect.getSelect().getWithItemsList(); + assertEquals(1, withItems2.size()); + assertEquals(" b", withItems2.get(0).getAlias().toString()); + ParenthesedSelect parenthesedSelect2 = (ParenthesedSelect) withItems2.get(0).getSelect(); + List withItems3 = parenthesedSelect2.getSelect().getWithItemsList(); + assertEquals(1, withItems3.size()); + assertEquals("(SELECT 1)", withItems3.get(0).getSelect().toString()); + assertEquals(" c", withItems3.get(0).getAlias().toString()); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java index 342d1eea6..669d3e60e 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -19,10 +19,12 @@ import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; import java.io.StringReader; +import java.util.List; import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -229,8 +231,18 @@ public void testWith() throws JSQLParserException { + "SET id_instrument=null\n" + "WHERE id_instrument_ref = (SELECT id_instrument_ref\n" + " FROM a)"; - - assertSqlCanBeParsedAndDeparsed(statement, true); + Update update = (Update) assertSqlCanBeParsedAndDeparsed(statement, true); + List withItems = update.getWithItemsList(); + assertEquals("cfe.instrument_ref", update.getTable().getFullyQualifiedName()); + assertEquals(2, withItems.size()); + assertEquals("SELECT 1 id_instrument_ref", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals(" a", withItems.get(0).getAlias().toString()); + assertEquals("SELECT 1 id_instrument_ref", withItems.get(1).getSelect().getPlainSelect().toString()); + assertEquals(" b", withItems.get(1).getAlias().toString()); + assertEquals(1, update.getUpdateSets().size()); + assertEquals("id_instrument", update.getUpdateSets().get(0).getColumn(0).toString()); + assertEquals("NULL", update.getUpdateSets().get(0).getValue(0).toString()); + assertEquals("id_instrument_ref = (SELECT id_instrument_ref FROM a)", update.getWhere().toString()); } @Test @@ -268,9 +280,7 @@ public void testUpdateSetsIssue1316() throws JSQLParserException { + " , b.packageunit = '4101170402' -- this is supposed to be UpdateSet 3\n" + "WHERE b.payrefno = 'B370202091026000005'"; - assertSqlCanBeParsedAndDeparsed(sqlStr, true); - - Update update = (Update) CCJSqlParserUtil.parse(sqlStr); + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr, true); assertEquals(3, update.getUpdateSets().size()); assertEquals(3, update.getUpdateSets().get(0).getColumns().size()); From 82470e55aaf915778e07cb39f091fc2fb1c08192 Mon Sep 17 00:00:00 2001 From: nicky6s Date: Sun, 4 Aug 2024 17:45:56 +0100 Subject: [PATCH 22/88] feature/fix: parsing inserts/updates/delete within CTEs (#2055) * feature parsing inserts/updates/delete within CTEs * removing System lines * fixing codacy issues * reducing the looping in NestedBracketsPerformanceTest to just 6 * formatting fixes via spotlessApply --- .../expression/ExpressionVisitorAdapter.java | 2 +- .../statement/ParenthesedStatement.java | 31 +++ .../statement/StatementVisitor.java | 22 ++ .../statement/StatementVisitorAdapter.java | 21 ++ .../jsqlparser/statement/delete/Delete.java | 20 +- .../statement/delete/ParenthesedDelete.java | 62 +++++ .../jsqlparser/statement/insert/Insert.java | 12 +- .../statement/insert/ParenthesedInsert.java | 61 +++++ .../sf/jsqlparser/statement/merge/Merge.java | 20 +- .../statement/select/ParenthesedSelect.java | 10 +- .../jsqlparser/statement/select/Select.java | 16 +- .../statement/select/SelectVisitor.java | 4 +- .../select/SelectVisitorAdapter.java | 2 +- .../jsqlparser/statement/select/WithItem.java | 105 ++++++-- .../statement/update/ParenthesedUpdate.java | 62 +++++ .../jsqlparser/statement/update/Update.java | 20 +- .../sf/jsqlparser/util/AddAliasesVisitor.java | 2 +- .../util/ConnectExpressionsVisitor.java | 2 +- .../sf/jsqlparser/util/TablesNamesFinder.java | 44 ++- .../util/deparser/DeleteDeParser.java | 5 +- .../util/deparser/ExpressionDeParser.java | 2 +- .../util/deparser/InsertDeParser.java | 5 +- .../util/deparser/MergeDeParser.java | 6 +- .../util/deparser/SelectDeParser.java | 20 +- .../util/deparser/StatementDeParser.java | 49 +++- .../util/deparser/TableStatementDeParser.java | 2 +- .../util/deparser/UpdateDeParser.java | 5 +- .../validation/validator/SelectValidator.java | 7 +- .../validator/StatementValidator.java | 18 ++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 132 +++++++-- .../statement/delete/DeleteTest.java | 148 ++++++++++- .../statement/insert/InsertTest.java | 195 ++++++++++++-- .../select/NestedBracketsPerformanceTest.java | 6 +- .../statement/select/SelectTest.java | 250 ++++++++++++++---- .../statement/update/UpdateTest.java | 152 ++++++++++- .../util/deparser/StatementDeParserTest.java | 6 +- 36 files changed, 1313 insertions(+), 213 deletions(-) create mode 100644 src/main/java/net/sf/jsqlparser/statement/ParenthesedStatement.java create mode 100644 src/main/java/net/sf/jsqlparser/statement/delete/ParenthesedDelete.java create mode 100644 src/main/java/net/sf/jsqlparser/statement/insert/ParenthesedInsert.java create mode 100644 src/main/java/net/sf/jsqlparser/statement/update/ParenthesedUpdate.java diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index c49bf6aea..9e1ee104d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -711,7 +711,7 @@ public T visit(GeometryDistance geometryDistance, S context) { public T visit(Select select, S context) { if (selectVisitor != null) { if (select.getWithItemsList() != null) { - for (WithItem item : select.getWithItemsList()) { + for (WithItem item : select.getWithItemsList()) { item.accept(selectVisitor, context); } } diff --git a/src/main/java/net/sf/jsqlparser/statement/ParenthesedStatement.java b/src/main/java/net/sf/jsqlparser/statement/ParenthesedStatement.java new file mode 100644 index 000000000..bd76f2282 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/ParenthesedStatement.java @@ -0,0 +1,31 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2019 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement; + +import net.sf.jsqlparser.expression.Alias; + +public interface ParenthesedStatement extends Statement { + + T accept(StatementVisitor statementVisitor, S context); + + default void accept(StatementVisitor statementVisitor) { + this.accept(statementVisitor, null); + } + + Alias getAlias(); + + void setAlias(Alias alias); + + default ParenthesedStatement withAlias(Alias alias) { + setAlias(alias); + return this; + } + +} diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java index 8625f6576..efd7ee099 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java @@ -24,16 +24,19 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.create.view.CreateView; import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; @@ -302,4 +305,23 @@ default void visit(AlterSystemStatement alterSystemStatement) { default void visit(UnsupportedStatement unsupportedStatement) { this.visit(unsupportedStatement, null); } + + T visit(ParenthesedInsert parenthesedInsert, S context); + + default void visit(ParenthesedInsert parenthesedInsert) { + this.visit(parenthesedInsert, null); + } + + T visit(ParenthesedUpdate parenthesedUpdate, S context); + + default void visit(ParenthesedUpdate parenthesedUpdate) { + this.visit(parenthesedUpdate, null); + } + + T visit(ParenthesedDelete parenthesedDelete, S context); + + default void visit(ParenthesedDelete parenthesedDelete) { + this.visit(parenthesedDelete, null); + } + } diff --git a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java index 5ee05b852..0e6ab8698 100644 --- a/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java @@ -24,16 +24,19 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.create.view.CreateView; import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; @@ -64,18 +67,36 @@ public T visit(Delete delete, S context) { return null; } + @Override + public T visit(ParenthesedDelete delete, S context) { + + return null; + } + @Override public T visit(Update update, S context) { return null; } + @Override + public T visit(ParenthesedUpdate update, S context) { + + return null; + } + @Override public T visit(Insert insert, S context) { return null; } + @Override + public T visit(ParenthesedInsert insert, S context) { + + return null; + } + @Override public T visit(Drop drop, S context) { diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java index 931d486c7..0ff9b8868 100644 --- a/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java +++ b/src/main/java/net/sf/jsqlparser/statement/delete/Delete.java @@ -33,7 +33,7 @@ public class Delete implements Statement { - private List withItemsList; + private List> withItemsList; private Table table; private OracleHint oracleHint = null; private List
tables; @@ -67,28 +67,28 @@ public Delete setReturningClause(ReturningClause returningClause) { return this; } - public List getWithItemsList() { + public List> getWithItemsList() { return withItemsList; } - public void setWithItemsList(List withItemsList) { + public void setWithItemsList(List> withItemsList) { this.withItemsList = withItemsList; } - public Delete withWithItemsList(List withItemsList) { + public Delete withWithItemsList(List> withItemsList) { this.setWithItemsList(withItemsList); return this; } - public Delete addWithItemsList(WithItem... withItemsList) { - List collection = + public Delete addWithItemsList(WithItem... withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemsList); return this.withWithItemsList(collection); } - public Delete addWithItemsList(Collection withItemsList) { - List collection = + public Delete addWithItemsList(Collection> withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); collection.addAll(withItemsList); return this.withWithItemsList(collection); @@ -177,8 +177,8 @@ public String toString() { StringBuilder b = new StringBuilder(); if (withItemsList != null && !withItemsList.isEmpty()) { b.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { + WithItem withItem = iter.next(); b.append(withItem); if (iter.hasNext()) { b.append(","); diff --git a/src/main/java/net/sf/jsqlparser/statement/delete/ParenthesedDelete.java b/src/main/java/net/sf/jsqlparser/statement/delete/ParenthesedDelete.java new file mode 100644 index 000000000..ffdf57d4b --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/delete/ParenthesedDelete.java @@ -0,0 +1,62 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.delete; + +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.statement.ParenthesedStatement; +import net.sf.jsqlparser.statement.StatementVisitor; + +public class ParenthesedDelete extends Delete implements ParenthesedStatement { + + Alias alias; + Delete delete; + + @Override + public Alias getAlias() { + return alias; + } + + @Override + public void setAlias(Alias alias) { + this.alias = alias; + } + + public ParenthesedDelete withAlias(Alias alias) { + this.setAlias(alias); + return this; + } + + public Delete getDelete() { + return delete; + } + + public void setDelete(Delete delete) { + this.delete = delete; + } + + public ParenthesedDelete withDelete(Delete delete) { + setDelete(delete); + return this; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("(").append(delete).append(")"); + if (alias != null) { + builder.append(alias); + } + return builder.toString(); + } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java index 287d96574..4d52a5864 100644 --- a/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java +++ b/src/main/java/net/sf/jsqlparser/statement/insert/Insert.java @@ -43,7 +43,7 @@ public class Insert implements Statement { private boolean modifierIgnore = false; private ReturningClause returningClause; private List setUpdateSets = null; - private List withItemsList; + private List> withItemsList; private OutputClause outputClause; private InsertConflictTarget conflictTarget; private InsertConflictAction conflictAction; @@ -168,11 +168,11 @@ public boolean isUseSet() { return setUpdateSets != null && !setUpdateSets.isEmpty(); } - public List getWithItemsList() { + public List> getWithItemsList() { return withItemsList; } - public void setWithItemsList(List withItemsList) { + public void setWithItemsList(List> withItemsList) { this.withItemsList = withItemsList; } @@ -221,8 +221,8 @@ public String toString() { StringBuilder sql = new StringBuilder(); if (withItemsList != null && !withItemsList.isEmpty()) { sql.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { + WithItem withItem = iter.next(); sql.append(withItem); if (iter.hasNext()) { sql.append(","); @@ -293,7 +293,7 @@ public String toString() { return sql.toString(); } - public Insert withWithItemsList(List withList) { + public Insert withWithItemsList(List> withList) { this.withItemsList = withList; return this; } diff --git a/src/main/java/net/sf/jsqlparser/statement/insert/ParenthesedInsert.java b/src/main/java/net/sf/jsqlparser/statement/insert/ParenthesedInsert.java new file mode 100644 index 000000000..b9c83526c --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/insert/ParenthesedInsert.java @@ -0,0 +1,61 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.insert; + +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.statement.ParenthesedStatement; +import net.sf.jsqlparser.statement.StatementVisitor; + +public class ParenthesedInsert extends Insert implements ParenthesedStatement { + Alias alias; + Insert insert; + + @Override + public Alias getAlias() { + return alias; + } + + @Override + public void setAlias(Alias alias) { + this.alias = alias; + } + + public ParenthesedInsert withAlias(Alias alias) { + this.setAlias(alias); + return this; + } + + public Insert getInsert() { + return insert; + } + + public void setInsert(Insert insert) { + this.insert = insert; + } + + public ParenthesedInsert withInsert(Insert insert) { + setInsert(insert); + return this; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("(").append(insert).append(")"); + if (alias != null) { + builder.append(alias); + } + return builder.toString(); + } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java b/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java index 689bd5d8e..7a3baf7a4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java +++ b/src/main/java/net/sf/jsqlparser/statement/merge/Merge.java @@ -30,7 +30,7 @@ public class Merge implements Statement { - private List withItemsList; + private List> withItemsList; private Table table; private OracleHint oracleHint = null; private FromItem fromItem; @@ -75,28 +75,28 @@ private void deriveStandardClausesFromOperations() { .orElse(false); } - public List getWithItemsList() { + public List> getWithItemsList() { return withItemsList; } - public void setWithItemsList(List withItemsList) { + public void setWithItemsList(List> withItemsList) { this.withItemsList = withItemsList; } - public Merge withWithItemsList(List withItemsList) { + public Merge withWithItemsList(List> withItemsList) { this.setWithItemsList(withItemsList); return this; } - public Merge addWithItemsList(WithItem... withItemsList) { - List collection = + public Merge addWithItemsList(WithItem... withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemsList); return this.withWithItemsList(collection); } - public Merge addWithItemsList(Collection withItemsList) { - List collection = + public Merge addWithItemsList(Collection> withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); collection.addAll(withItemsList); return this.withWithItemsList(collection); @@ -220,8 +220,8 @@ public String toString() { StringBuilder b = new StringBuilder(); if (withItemsList != null && !withItemsList.isEmpty()) { b.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { + WithItem withItem = iter.next(); b.append(withItem); if (iter.hasNext()) { b.append(","); diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java index 0fc99972e..a33abf3a3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java @@ -12,11 +12,13 @@ import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.ParenthesedStatement; +import net.sf.jsqlparser.statement.StatementVisitor; import java.util.Collection; import java.util.List; -public class ParenthesedSelect extends Select implements FromItem { +public class ParenthesedSelect extends Select implements FromItem, ParenthesedStatement { Alias alias; Pivot pivot; UnPivot unPivot; @@ -151,12 +153,16 @@ public T accept(FromItemVisitor fromItemVisitor, S context) { return fromItemVisitor.visit(this, context); } + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } + public StringBuilder appendSelectBodyTo(StringBuilder builder) { builder.append("(").append(select).append(")"); if (alias != null) { builder.append(alias); } - if (pivot != null) { builder.append(" ").append(pivot); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/Select.java b/src/main/java/net/sf/jsqlparser/statement/select/Select.java index e6cc7393a..b0c8e9972 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/Select.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/Select.java @@ -25,7 +25,7 @@ public abstract class Select extends ASTNodeAccessImpl implements Statement, Expression { protected Table forUpdateTable = null; - List withItemsList; + List> withItemsList; Limit limitBy; Limit limit; Offset offset; @@ -126,27 +126,27 @@ public static StringBuilder appendStringListTo(StringBuilder builder, List li return builder; } - public List getWithItemsList() { + public List> getWithItemsList() { return withItemsList; } - public void setWithItemsList(List withItemsList) { + public void setWithItemsList(List> withItemsList) { this.withItemsList = withItemsList; } - public Select withWithItemsList(List withItemsList) { + public Select withWithItemsList(List> withItemsList) { this.setWithItemsList(withItemsList); return this; } - public Select addWithItemsList(Collection withItemsList) { - List collection = + public Select addWithItemsList(Collection> withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); collection.addAll(withItemsList); return this.withWithItemsList(collection); } - public Select addWithItemsList(WithItem... withItemsList) { + public Select addWithItemsList(WithItem... withItemsList) { return addWithItemsList(Arrays.asList(withItemsList)); } @@ -328,7 +328,7 @@ public void setSkipLocked(boolean skipLocked) { public StringBuilder appendTo(StringBuilder builder) { if (withItemsList != null && !withItemsList.isEmpty()) { builder.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { WithItem withItem = iter.next(); builder.append(withItem); if (iter.hasNext()) { diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java index d8ee278be..8a4e9667c 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitor.java @@ -29,9 +29,9 @@ default void visit(SetOperationList setOpList) { this.visit(setOpList, null); } - T visit(WithItem withItem, S context); + T visit(WithItem withItem, S context); - default void visit(WithItem withItem) { + default void visit(WithItem withItem) { this.visit(withItem, null); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java index 90fa3b8c2..d20fdfdd1 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectVisitorAdapter.java @@ -31,7 +31,7 @@ public T visit(SetOperationList setOpList, S context) { } @Override - public T visit(WithItem withItem, S context) { + public T visit(WithItem withItem, S context) { return withItem.getSelect().accept(this, context); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java index b3610a730..37b3663c2 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -9,18 +9,60 @@ */ package net.sf.jsqlparser.statement.select; +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.statement.ParenthesedStatement; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; -public class WithItem extends ParenthesedSelect { +public class WithItem { + private T statement; + private Alias alias; private List> withItemList; - private boolean recursive = false; + public WithItem(T statement, Alias alias) { + this.statement = statement; + this.alias = alias; + } + + public WithItem() { + this(null, (Alias) null); + } + + public T getParenthesedStatement() { + return statement; + } + + public void setParenthesedStatement(T statement) { + this.statement = statement; + } + + public WithItem withParenthesedStatement(T statement) { + this.setParenthesedStatement(statement); + return this; + } + + public Alias getAlias() { + return alias; + } + + public void setAlias(Alias alias) { + this.alias = alias; + } + + public WithItem withAlias(Alias alias) { + this.setAlias(alias); + return this; + } + public boolean isRecursive() { return recursive; } @@ -29,7 +71,6 @@ public void setRecursive(boolean recursive) { this.recursive = recursive; } - /** * The {@link SelectItem}s in this WITH (for example the A,B,C in "WITH mywith (A,B,C) AS ...") * @@ -44,47 +85,73 @@ public void setWithItemList(List> withItemList) { } @Override - @SuppressWarnings({"PMD.CyclomaticComplexity"}) - public StringBuilder appendSelectBodyTo(StringBuilder builder) { + public String toString() { + StringBuilder builder = new StringBuilder(); builder.append(recursive ? "RECURSIVE " : ""); - builder.append(alias.getName()); - builder.append( - (withItemList != null) ? " " + PlainSelect.getStringList(withItemList, true, true) - : ""); + if (alias != null) { + builder.append(alias.getName()); + } + if (withItemList != null) { + builder.append("("); + int size = withItemList.size(); + for (int i = 0; i < size; i++) { + builder.append(withItemList.get(i)).append(i < size - 1 ? "," : ""); + } + builder.append(")"); + } else { + builder.append(""); + } builder.append(" AS "); - - select.appendTo(builder); - - return builder; + builder.append(statement); + return builder.toString(); } - @Override public T accept(SelectVisitor selectVisitor, S context) { return selectVisitor.visit(this, context); } - - public WithItem withWithItemList(List> withItemList) { + public WithItem withWithItemList(List> withItemList) { this.setWithItemList(withItemList); return this; } - public WithItem withRecursive(boolean recursive) { + public WithItem withRecursive(boolean recursive) { this.setRecursive(recursive); return this; } - public WithItem addWithItemList(SelectItem... withItemList) { + public WithItem addWithItemList(SelectItem... withItemList) { List> collection = Optional.ofNullable(getWithItemList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemList); return this.withWithItemList(collection); } - public WithItem addWithItemList(Collection> withItemList) { + public WithItem addWithItemList(Collection> withItemList) { List> collection = Optional.ofNullable(getWithItemList()).orElseGet(ArrayList::new); collection.addAll(withItemList); return this.withWithItemList(collection); } + + public ParenthesedSelect getSelect() { + return (ParenthesedSelect) statement; + } + + public ParenthesedInsert getInsert() { + return (ParenthesedInsert) statement; + } + + public ParenthesedUpdate getUpdate() { + return (ParenthesedUpdate) statement; + } + + public ParenthesedDelete getDelete() { + return (ParenthesedDelete) statement; + } + + public void setSelect(ParenthesedSelect select) { + this.statement = (T) select; + } + } diff --git a/src/main/java/net/sf/jsqlparser/statement/update/ParenthesedUpdate.java b/src/main/java/net/sf/jsqlparser/statement/update/ParenthesedUpdate.java new file mode 100644 index 000000000..8dc95c2eb --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/update/ParenthesedUpdate.java @@ -0,0 +1,62 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2023 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.statement.update; + +import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.statement.ParenthesedStatement; +import net.sf.jsqlparser.statement.StatementVisitor; + +public class ParenthesedUpdate extends Update implements ParenthesedStatement { + + Alias alias; + Update update; + + @Override + public Alias getAlias() { + return alias; + } + + @Override + public void setAlias(Alias alias) { + this.alias = alias; + } + + public ParenthesedUpdate withAlias(Alias alias) { + this.setAlias(alias); + return this; + } + + public Update getUpdate() { + return update; + } + + public void setUpdate(Update update) { + this.update = update; + } + + public ParenthesedUpdate withUpdate(Update update) { + setUpdate(update); + return this; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("(").append(update).append(")"); + if (alias != null) { + builder.append(alias); + } + return builder.toString(); + } + + @Override + public T accept(StatementVisitor statementVisitor, S context) { + return statementVisitor.visit(this, context); + } +} diff --git a/src/main/java/net/sf/jsqlparser/statement/update/Update.java b/src/main/java/net/sf/jsqlparser/statement/update/Update.java index 64da8f64e..2d948afda 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -36,7 +36,7 @@ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class Update implements Statement { - private List withItemsList; + private List> withItemsList; private Table table; private Expression where; private List updateSets; @@ -82,28 +82,28 @@ public T accept(StatementVisitor statementVisitor, S context) { return statementVisitor.visit(this, context); } - public List getWithItemsList() { + public List> getWithItemsList() { return withItemsList; } - public void setWithItemsList(List withItemsList) { + public void setWithItemsList(List> withItemsList) { this.withItemsList = withItemsList; } - public Update withWithItemsList(List withItemsList) { + public Update withWithItemsList(List> withItemsList) { this.setWithItemsList(withItemsList); return this; } - public Update addWithItemsList(WithItem... withItemsList) { - List collection = + public Update addWithItemsList(WithItem... withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); Collections.addAll(collection, withItemsList); return this.withWithItemsList(collection); } - public Update addWithItemsList(Collection withItemsList) { - List collection = + public Update addWithItemsList(Collection> withItemsList) { + List> collection = Optional.ofNullable(getWithItemsList()).orElseGet(ArrayList::new); collection.addAll(withItemsList); return this.withWithItemsList(collection); @@ -282,8 +282,8 @@ public String toString() { if (withItemsList != null && !withItemsList.isEmpty()) { b.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { + WithItem withItem = iter.next(); b.append(withItem); if (iter.hasNext()) { b.append(","); diff --git a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java index 17e5ed428..80f6bb6dd 100644 --- a/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/AddAliasesVisitor.java @@ -100,7 +100,7 @@ public void setPrefix(String prefix) { } @Override - public T visit(WithItem withItem, S context) { + public T visit(WithItem withItem, S context) { throw new UnsupportedOperationException(NOT_SUPPORTED_YET); } diff --git a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java index 903b5d722..3f0377728 100644 --- a/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java +++ b/src/main/java/net/sf/jsqlparser/util/ConnectExpressionsVisitor.java @@ -99,7 +99,7 @@ public T visit(SetOperationList setOpList, S context) { } @Override - public T visit(WithItem withItem, S context) { + public T visit(WithItem withItem, S context) { return null; } diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 8635ecfc2..ad5e10495 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -144,10 +144,12 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.create.view.CreateView; import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; import net.sf.jsqlparser.statement.select.AllColumns; @@ -171,6 +173,7 @@ import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.update.UpdateSet; import net.sf.jsqlparser.statement.upsert.Upsert; @@ -246,9 +249,9 @@ public Set getTablesOrOtherSources(Statement statement) { @Override public Void visit(Select select, S context) { - List withItemsList = select.getWithItemsList(); + List> withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { - for (WithItem withItem : withItemsList) { + for (WithItem withItem : withItemsList) { withItem.accept((SelectVisitor) this, context); } } @@ -300,14 +303,14 @@ public Set getTables(Expression expr) { } @Override - public Void visit(WithItem withItem, S context) { + public Void visit(WithItem withItem, S context) { otherItemNames.add(withItem.getAlias().getName()); withItem.getSelect().accept((SelectVisitor) this, context); return null; } @Override - public void visit(WithItem withItem) { + public void visit(WithItem withItem) { SelectVisitor.super.visit(withItem); } @@ -316,9 +319,9 @@ public Void visit(ParenthesedSelect select, S context) { if (select.getAlias() != null) { otherItemNames.add(select.getAlias().getName()); } - List withItemsList = select.getWithItemsList(); + List> withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { - for (WithItem withItem : withItemsList) { + for (WithItem withItem : withItemsList) { withItem.accept((SelectVisitor) this, context); } } @@ -333,9 +336,9 @@ public void visit(ParenthesedSelect parenthesedSelect) { @Override public Void visit(PlainSelect plainSelect, S context) { - List withItemsList = plainSelect.getWithItemsList(); + List> withItemsList = plainSelect.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { - for (WithItem withItem : withItemsList) { + for (WithItem withItem : withItemsList) { withItem.accept((SelectVisitor) this, context); } } @@ -790,9 +793,9 @@ public Void visit(AnalyticExpression analytic, S context) { @Override public Void visit(SetOperationList list, S context) { - List withItemsList = list.getWithItemsList(); + List> withItemsList = list.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { - for (WithItem withItem : withItemsList) { + for (WithItem withItem : withItemsList) { withItem.accept((SelectVisitor) this, context); } } @@ -983,10 +986,15 @@ public void visit(Delete delete) { StatementVisitor.super.visit(delete); } + @Override + public Void visit(ParenthesedDelete delete, S context) { + return visit(delete.getDelete(), context); + } + @Override public Void visit(Update update, S context) { if (update.getWithItemsList() != null) { - for (WithItem withItem : update.getWithItemsList()) { + for (WithItem withItem : update.getWithItemsList()) { withItem.accept((SelectVisitor) this, context); } } @@ -1025,6 +1033,11 @@ public Void visit(Update update, S context) { return null; } + @Override + public Void visit(ParenthesedUpdate update, S context) { + return visit(update.getUpdate(), context); + } + @Override public void visit(Update update) { StatementVisitor.super.visit(update); @@ -1034,7 +1047,7 @@ public void visit(Update update) { public Void visit(Insert insert, S context) { visit(insert.getTable(), context); if (insert.getWithItemsList() != null) { - for (WithItem withItem : insert.getWithItemsList()) { + for (WithItem withItem : insert.getWithItemsList()) { withItem.accept((SelectVisitor) this, context); } } @@ -1044,6 +1057,11 @@ public Void visit(Insert insert, S context) { return null; } + @Override + public Void visit(ParenthesedInsert insert, S context) { + return visit(insert.getInsert(), context); + } + @Override public void visit(Insert insert) { StatementVisitor.super.visit(insert); @@ -1231,7 +1249,7 @@ public Void visit(HexValue hexValue, S context) { public Void visit(Merge merge, S context) { visit(merge.getTable(), context); if (merge.getWithItemsList() != null) { - for (WithItem withItem : merge.getWithItemsList()) { + for (WithItem withItem : merge.getWithItemsList()) { withItem.accept((SelectVisitor) this, context); } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java index 52e5a6671..36fe3c0c8 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java @@ -40,8 +40,9 @@ public DeleteDeParser(ExpressionVisitor expressionVisitor, public void deParse(Delete delete) { if (delete.getWithItemsList() != null && !delete.getWithItemsList().isEmpty()) { buffer.append("WITH "); - for (Iterator iter = delete.getWithItemsList().iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = delete.getWithItemsList().iterator(); iter + .hasNext();) { + WithItem withItem = iter.next(); buffer.append(withItem); if (iter.hasNext()) { buffer.append(","); 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 65ea93489..bb6b6a146 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -633,7 +633,7 @@ public StringBuilder visit(Select select, S context) { if (selectVisitor != null) { if (select.getWithItemsList() != null) { buffer.append("WITH "); - for (Iterator iter = select.getWithItemsList().iterator(); iter + for (Iterator> iter = select.getWithItemsList().iterator(); iter .hasNext();) { iter.next().accept(selectVisitor, null); if (iter.hasNext()) { diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java index b3f8e4abb..b9aa7bb65 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/InsertDeParser.java @@ -41,8 +41,9 @@ public InsertDeParser(ExpressionVisitor expressionVisitor, public void deParse(Insert insert) { if (insert.getWithItemsList() != null && !insert.getWithItemsList().isEmpty()) { buffer.append("WITH "); - for (Iterator iter = insert.getWithItemsList().iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = insert.getWithItemsList().iterator(); iter + .hasNext();) { + WithItem withItem = iter.next(); withItem.accept(this.selectVisitor, null); if (iter.hasNext()) { buffer.append(","); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java index 36cda69a4..09bb0cfc5 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/MergeDeParser.java @@ -30,11 +30,11 @@ public MergeDeParser(ExpressionDeParser expressionDeParser, SelectDeParser selec @Override public void deParse(Merge merge) { - List withItemsList = merge.getWithItemsList(); + List> withItemsList = merge.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { - iter.next().accept(expressionDeParser, null); + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { + iter.next().accept(selectDeParser, null); if (iter.hasNext()) { buffer.append(","); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index 705db155c..c56f396d4 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -93,10 +93,10 @@ public SelectDeParser(ExpressionVisitor expressionVisitor, @Override public StringBuilder visit(ParenthesedSelect select, S context) { - List withItemsList = select.getWithItemsList(); + List> withItemsList = select.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); - for (WithItem withItem : withItemsList) { + for (WithItem withItem : withItemsList) { withItem.accept((SelectVisitor) this, context); buffer.append(" "); } @@ -147,10 +147,10 @@ public void visit(Top top) { @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveMethodLength", "PMD.NPathComplexity"}) public StringBuilder visit(PlainSelect plainSelect, S context) { - List withItemsList = plainSelect.getWithItemsList(); + List> withItemsList = plainSelect.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { iter.next().accept((SelectVisitor) this, context); if (iter.hasNext()) { buffer.append(","); @@ -602,10 +602,10 @@ public void deparseLateralView(LateralView lateralView) { @Override public StringBuilder visit(SetOperationList list, S context) { - List withItemsList = list.getWithItemsList(); + List> withItemsList = list.getWithItemsList(); if (withItemsList != null && !withItemsList.isEmpty()) { buffer.append("WITH "); - for (Iterator iter = withItemsList.iterator(); iter.hasNext();) { + for (Iterator> iter = withItemsList.iterator(); iter.hasNext();) { iter.next().accept((SelectVisitor) this, context); if (iter.hasNext()) { buffer.append(","); @@ -640,7 +640,7 @@ public StringBuilder visit(SetOperationList list, S context) { } @Override - public StringBuilder visit(WithItem withItem, S context) { + public StringBuilder visit(WithItem withItem, S context) { if (withItem.isRecursive()) { buffer.append("RECURSIVE "); } @@ -650,7 +650,9 @@ public StringBuilder visit(WithItem withItem, S context) { .append(PlainSelect.getStringList(withItem.getWithItemList(), true, true)); } buffer.append(" AS "); - withItem.getSelect().accept(this, context); + StatementDeParser statementDeParser = + new StatementDeParser((ExpressionDeParser) expressionVisitor, this, buffer); + statementDeParser.deParse(withItem.getParenthesedStatement()); return buffer; } @@ -748,7 +750,7 @@ public void visit(SetOperationList list) { visit(list, null); } - public void visit(WithItem withItem) { + public void visit(WithItem withItem) { visit(withItem, null); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 17babd34e..d4cff2a58 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.util.deparser; import java.lang.reflect.InvocationTargetException; +import java.util.List; import java.util.stream.Collectors; import net.sf.jsqlparser.schema.Table; @@ -47,16 +48,21 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.create.view.CreateView; import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; -import net.sf.jsqlparser.statement.merge.*; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; +import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SelectVisitor; +import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; @@ -165,6 +171,47 @@ public StringBuilder visit(Insert insert, S context) { return buffer; } + @Override + public StringBuilder visit(ParenthesedInsert insert, S context) { + List> withItemsList = insert.getWithItemsList(); + addWithItemsToBuffer(withItemsList, context); + buffer.append("("); + insert.getInsert().accept(this, context); + buffer.append(")"); + return buffer; + } + + @Override + public StringBuilder visit(ParenthesedUpdate update, S context) { + List> withItemsList = update.getWithItemsList(); + addWithItemsToBuffer(withItemsList, context); + buffer.append("("); + update.getUpdate().accept(this, context); + buffer.append(")"); + return buffer; + } + + @Override + public StringBuilder visit(ParenthesedDelete delete, S context) { + List> withItemsList = delete.getWithItemsList(); + addWithItemsToBuffer(withItemsList, context); + buffer.append("("); + delete.getDelete().accept(this, context); + buffer.append(")"); + return buffer; + } + + private StringBuilder addWithItemsToBuffer(List> withItemsList, S context) { + if (withItemsList != null && !withItemsList.isEmpty()) { + buffer.append("WITH "); + for (WithItem withItem : withItemsList) { + withItem.accept((SelectVisitor) this, context); + buffer.append(" "); + } + } + return buffer; + } + @Override public StringBuilder visit(Select select, S context) { select.accept(selectDeParser, context); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java index be83df5bb..e187faaab 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/TableStatementDeParser.java @@ -67,7 +67,7 @@ public StringBuilder visit(SetOperationList setOperationList, S context) { } @Override - public StringBuilder visit(WithItem withItem, S context) { + public StringBuilder visit(WithItem withItem, S context) { return buffer; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java index 682c1c067..071ceeca5 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -40,8 +40,9 @@ public UpdateDeParser(ExpressionVisitor expressionVisitor, public void deParse(Update update) { if (update.getWithItemsList() != null && !update.getWithItemsList().isEmpty()) { buffer.append("WITH "); - for (Iterator iter = update.getWithItemsList().iterator(); iter.hasNext();) { - WithItem withItem = iter.next(); + for (Iterator> iter = update.getWithItemsList().iterator(); iter + .hasNext();) { + WithItem withItem = iter.next(); buffer.append(withItem); if (iter.hasNext()) { buffer.append(","); diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java index 4ed464ddc..a908adebd 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/SelectValidator.java @@ -303,7 +303,7 @@ public Void visit(SetOperationList setOperation, S context) { } @Override - public Void visit(WithItem withItem, S context) { + public Void visit(WithItem withItem, S context) { for (ValidationCapability c : getCapabilities()) { validateFeature(c, Feature.withItem); validateFeature(c, withItem.isRecursive(), Feature.withItemRecursive); @@ -311,7 +311,7 @@ public Void visit(WithItem withItem, S context) { if (isNotEmpty(withItem.getWithItemList())) { withItem.getWithItemList().forEach(wi -> wi.accept(this, context)); } - withItem.getSelect().accept(this, context); + withItem.getSelect().accept((SelectVisitor) this, context); return null; } @@ -393,7 +393,7 @@ public void visit(SetOperationList setOperation) { visit(setOperation, null); } - public void visit(WithItem withItem) { + public void visit(WithItem withItem) { visit(withItem, null); } @@ -416,4 +416,5 @@ public void visit(ParenthesedFromItem parenthesis) { public void visit(Values values) { visit(values, null); } + } diff --git a/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java index 44e2f1f79..3c84aa60e 100644 --- a/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java +++ b/src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java @@ -46,16 +46,19 @@ import net.sf.jsqlparser.statement.create.view.AlterView; import net.sf.jsqlparser.statement.create.view.CreateView; import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.delete.ParenthesedDelete; import net.sf.jsqlparser.statement.drop.Drop; import net.sf.jsqlparser.statement.execute.Execute; import net.sf.jsqlparser.statement.grant.Grant; import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.insert.ParenthesedInsert; import net.sf.jsqlparser.statement.merge.Merge; import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.show.ShowIndexStatement; import net.sf.jsqlparser.statement.show.ShowTablesStatement; import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.ParenthesedUpdate; import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.upsert.Upsert; import net.sf.jsqlparser.util.validation.ValidationCapability; @@ -103,6 +106,11 @@ public Void visit(Delete delete, S context) { return null; } + @Override + public Void visit(ParenthesedDelete delete, S context) { + return visit(delete.getDelete(), context); + } + @Override public Void visit(Drop drop, S context) { getValidator(DropValidator.class).validate(drop); @@ -115,6 +123,11 @@ public Void visit(Insert insert, S context) { return null; } + @Override + public Void visit(ParenthesedInsert insert, S context) { + return visit(insert.getInsert(), context); + } + @Override public Void visit(Select select, S context) { validateFeature(Feature.select); @@ -137,6 +150,11 @@ public Void visit(Update update, S context) { return null; } + @Override + public Void visit(ParenthesedUpdate update, S context) { + return visit(update.getUpdate(), context); + } + @Override public Void visit(Alter alter, S context) { getValidator(AlterValidator.class).validate(alter); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 285b42185..9cfb81eb6 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -743,7 +743,7 @@ Statement Statement() #Statement: Statement SingleStatement() : { Statement stm = null; - List with = null; + List> with = null; } { ( @@ -752,13 +752,13 @@ Statement SingleStatement() : ( stm = SelectWithWithItems( with ) | - stm = Insert( with ) + stm = InsertWithWithItems( with ) | - stm = Update( with ) + stm = UpdateWithWithItems( with ) | - stm = Delete( with ) + stm = DeleteWithWithItems( with ) | - stm = Merge( with) + stm = Merge( with ) ) ) | @@ -1455,12 +1455,22 @@ ReturningClause ReturningClause(): } } -Update Update( List with ): +Update UpdateWithWithItems( List> withItems ): +{ + Update update; +} +{ + update = Update() { update.setWithItemsList( withItems ); + return update; +} +} + +Update Update(): { Update update = new Update(); Table table = null; List startJoins = null; - + List> with = null; List updateSets; Expression where = null; FromItem fromItem = null; @@ -1558,10 +1568,21 @@ List UpdateSets(): } } -Insert Insert( List with ): +Insert InsertWithWithItems( List> withItems ): +{ + Insert insert; +} +{ + insert = Insert() { insert.setWithItemsList( withItems ); + return insert; +} +} + +Insert Insert(): { Insert insert = new Insert(); Table table = null; + List> with = null; Column tableColumn = null; ExpressionList columns = new ExpressionList(); Expression exp = null; @@ -1762,11 +1783,22 @@ Upsert Upsert(): } } -Delete Delete( List with ): +Delete DeleteWithWithItems( List> withItems ): +{ + Delete delete; +} +{ + delete = Delete() { delete.setWithItemsList( withItems ); + return delete; +} +} + +Delete Delete(): { Delete delete = new Delete(); Table table = null; List
tables = new ArrayList
(); + List> with = null; Table usingTable = null; List
usingList = new ArrayList
(); List joins = null; @@ -1815,7 +1847,7 @@ Delete Delete( List with ): } } -Statement Merge( List with ) : { +Statement Merge( List> with ) : { Merge merge = new Merge(); Table table; FromItem fromItem; @@ -2120,7 +2152,7 @@ SampleClause SampleClause(): } } -Select SelectWithWithItems( List withItems): +Select SelectWithWithItems( List> withItems): { Select select; } @@ -2133,7 +2165,7 @@ Select SelectWithWithItems( List withItems): Select Select() #Select: { Select select = null; - List with = null; + List> with = null; List orderByElements = null; Limit limit = null; Offset offset = null; @@ -2197,6 +2229,48 @@ ParenthesedSelect ParenthesedSelect() #ParenthesedSelect: } } +ParenthesedInsert ParenthesedInsert() #ParenthesedInsert: +{ + ParenthesedInsert parenthesedInsert = new ParenthesedInsert(); + Insert insert; +} +{ + "(" + insert = Insert() + ")" + { + return parenthesedInsert.withInsert(insert); + } +} + +ParenthesedUpdate ParenthesedUpdate() #ParenthesedUpdate: +{ + ParenthesedUpdate parenthesedUpdate = new ParenthesedUpdate(); + Update update; +} +{ + "(" + update = Update() + ")" + { + return parenthesedUpdate.withUpdate(update); + } +} + +ParenthesedDelete ParenthesedDelete() #ParenthesedDelete: +{ + ParenthesedDelete parenthesedDelete = new ParenthesedDelete(); + Delete delete; +} +{ + "(" + delete = Delete() + ")" + { + return parenthesedDelete.withDelete(delete); + } +} + LateralView LateralView() #LateralView: { boolean useOuter = false; @@ -2550,9 +2624,9 @@ Select SetOperationList(Select select) #SetOperationList: { } } -List WithList(): +List> WithList(): { - List withItemsList = new ArrayList(); + List> withItemsList = new ArrayList>(); WithItem with = null; } { @@ -2561,20 +2635,32 @@ List WithList(): { return withItemsList; } } -WithItem WithItem() #WithItem: +WithItem WithItem() #WithItem: { - WithItem withItem = new WithItem(); + boolean recursive = false; String name; - List> selectItems; - Select select; + List> selectItems = null; + ParenthesedStatement statement; } { - [ LOOKAHEAD(2) { withItem.setRecursive(true); } ] - name=RelObjectName() { withItem.setAlias( new Alias( name, false)); } - [ "(" selectItems=SelectItemsList() ")" { withItem.setWithItemList(selectItems); } ] - select = ParenthesedSelect() { withItem.setSelect(select); } + [ LOOKAHEAD(2) { recursive = true; } ] + name=RelObjectName() + [ "(" selectItems=SelectItemsList() ")" ] + + ( + LOOKAHEAD(2) statement = ParenthesedSelect() + | + LOOKAHEAD(2) statement = ParenthesedInsert() + | + LOOKAHEAD(2) statement = ParenthesedUpdate() + | + LOOKAHEAD(2) statement = ParenthesedDelete() + ) { - return withItem; + WithItem withItem = new WithItem(statement, new Alias(name, false)); + return withItem + .withRecursive(recursive) + .withWithItemList(selectItems); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java index c9a3030aa..a02137a19 100644 --- a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java @@ -25,8 +25,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.WithItem; +import net.sf.jsqlparser.statement.update.Update; import org.junit.jupiter.api.Test; public class DeleteTest { @@ -124,14 +127,16 @@ public void testWith() throws JSQLParserException { + "WHERE id_instrument_ref = (SELECT id_instrument_ref\n" + " FROM a)"; Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(statement, true); - List withItems = delete.getWithItemsList(); + List> withItems = delete.getWithItemsList(); assertEquals("cfe.instrument_ref", delete.getTable().getFullyQualifiedName()); assertEquals(2, withItems.size()); - SelectItem selectItem1 = withItems.get(0).getSelect().getPlainSelect().getSelectItems().get(0); + SelectItem selectItem1 = + withItems.get(0).getSelect().getPlainSelect().getSelectItems().get(0); assertEquals("1", selectItem1.getExpression().toString()); assertEquals(" id_instrument_ref", selectItem1.getAlias().toString()); assertEquals(" a", withItems.get(0).getAlias().toString()); - SelectItem selectItem2 = withItems.get(1).getSelect().getPlainSelect().getSelectItems().get(0); + SelectItem selectItem2 = + withItems.get(1).getSelect().getPlainSelect().getSelectItems().get(0); assertEquals("1", selectItem2.getExpression().toString()); assertEquals(" id_instrument_ref", selectItem2.getAlias().toString()); assertEquals(" b", withItems.get(1).getAlias().toString()); @@ -227,6 +232,143 @@ public void testDeleteOutputClause() throws JSQLParserException { " ON ph.ProductID = p.ProductID \n" + " WHERE p.ProductModelID BETWEEN 120 and 130", true); + } + @Test + void testInsertWithinCte() throws JSQLParserException { + String sqlStr = "WITH inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " RETURNING y " + + ") " + + "DELETE " + + " FROM z" + + " WHERE y IN (SELECT y FROM inserted)"; + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", delete.getTable().toString()); + List> withItems = delete.getWithItemsList(); + assertEquals(1, withItems.size()); + Insert insert = withItems.get(0).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b", insert.getSelect().toString()); + assertEquals(" RETURNING y", insert.getReturningClause().toString()); + assertEquals("INSERT INTO x (foo) SELECT bar FROM b RETURNING y", insert.toString()); + assertEquals(" inserted", withItems.get(0).getAlias().toString()); + } + + @Test + void testUpdateWithinCte() throws JSQLParserException { + String sqlStr = "WITH updated AS ( " + + " UPDATE x " + + " SET foo = 1 " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "DELETE " + + " FROM z" + + " WHERE y IN (SELECT y FROM updated)"; + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", delete.getTable().toString()); + List> withItems = delete.getWithItemsList(); + assertEquals(1, withItems.size()); + Update update = withItems.get(0).getUpdate().getUpdate(); + assertEquals("x", update.getTable().toString()); + assertEquals("foo", update.getUpdateSets().get(0).getColumn(0).toString()); + assertEquals("1", update.getUpdateSets().get(0).getValue(0).toString()); + assertEquals("bar = 2", update.getWhere().toString()); + assertEquals(" RETURNING y", update.getReturningClause().toString()); + assertEquals(" updated", withItems.get(0).getAlias().toString()); } + + @Test + void testDeleteWithinCte() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "DELETE " + + " FROM z" + + " WHERE y IN (SELECT y FROM deleted)"; + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", delete.getTable().toString()); + List> withItems = delete.getWithItemsList(); + assertEquals(1, withItems.size()); + Delete innerDelete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", innerDelete.getTable().toString()); + assertEquals("bar = 2", innerDelete.getWhere().toString()); + assertEquals(" RETURNING y", innerDelete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM deleted) " + + " RETURNING w " + + ") " + + "DELETE " + + " FROM z" + + " WHERE w IN (SELECT w FROM inserted)"; + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", delete.getTable().toString()); + List> withItems = delete.getWithItemsList(); + assertEquals(2, withItems.size()); + Delete innerDelete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", innerDelete.getTable().toString()); + assertEquals("bar = 2", innerDelete.getWhere().toString()); + assertEquals(" RETURNING y", innerDelete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM deleted)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM deleted) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + + @Test + void testSelectAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH selection AS ( " + + " SELECT y " + + " FROM z " + + " WHERE foo = 'bar' " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM selection) " + + " RETURNING w " + + ") " + + "DELETE " + + " FROM z" + + " WHERE w IN (SELECT w FROM inserted)"; + Delete delete = (Delete) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", delete.getTable().toString()); + List> withItems = delete.getWithItemsList(); + assertEquals(2, withItems.size()); + PlainSelect innerSelect = withItems.get(0).getSelect().getPlainSelect(); + assertEquals("SELECT y FROM z WHERE foo = 'bar'", innerSelect.toString()); + assertEquals(" selection", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM selection)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM selection) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + } diff --git a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java index 3bec29069..421f6b629 100644 --- a/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/insert/InsertTest.java @@ -23,7 +23,9 @@ import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.select.*; +import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.statement.update.UpdateSet; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -277,25 +279,29 @@ public void testInsertSelect() throws JSQLParserException { @Test public void testInsertWithSelect() throws JSQLParserException { - String sqlStr1 = "INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a"; + String sqlStr1 = + "INSERT INTO mytable (mycolumn) WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a"; Insert insert1 = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr1, true); - List insertWithItems1 = insert1.getWithItemsList(); - List selectWithItems1 = insert1.getSelect().getWithItemsList(); + List> insertWithItems1 = insert1.getWithItemsList(); + List> selectWithItems1 = insert1.getSelect().getWithItemsList(); assertEquals("mytable", insert1.getTable().getFullyQualifiedName()); assertNull(insertWithItems1); assertEquals(1, selectWithItems1.size()); - assertEquals("SELECT mycolumn FROM mytable", selectWithItems1.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT mycolumn FROM mytable", + selectWithItems1.get(0).getSelect().getPlainSelect().toString()); assertEquals(" a", selectWithItems1.get(0).getAlias().toString()); - String sqlStr2 = "INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)"; + String sqlStr2 = + "INSERT INTO mytable (mycolumn) (WITH a AS (SELECT mycolumn FROM mytable) SELECT mycolumn FROM a)"; Insert insert2 = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr2, true); - List insertWithItems2 = insert2.getWithItemsList(); + List> insertWithItems2 = insert2.getWithItemsList(); assertEquals("mytable", insert2.getTable().getFullyQualifiedName()); assertNull(insertWithItems2); ParenthesedSelect select = (ParenthesedSelect) insert2.getSelect(); - List selectWithItems2 = select.getSelect().getWithItemsList(); + List> selectWithItems2 = select.getSelect().getWithItemsList(); assertEquals(1, selectWithItems2.size()); - assertEquals("SELECT mycolumn FROM mytable", selectWithItems2.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT mycolumn FROM mytable", + selectWithItems2.get(0).getSelect().getPlainSelect().toString()); assertEquals(" a", selectWithItems2.get(0).getAlias().toString()); } @@ -362,15 +368,17 @@ public void testKeywordPrecisionIssue363() throws JSQLParserException { @Test public void testWithDeparsingIssue406() throws JSQLParserException { - String sqlStr = "insert into mytab3 (a,b,c) select a,b,c from mytab where exists(with t as (select * from mytab2) select * from t)"; + String sqlStr = + "insert into mytab3 (a,b,c) select a,b,c from mytab where exists(with t as (select * from mytab2) select * from t)"; Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - List insertWithItems = insert.getWithItemsList(); - List selectWithItems = insert.getSelect().getWithItemsList(); + List> insertWithItems = insert.getWithItemsList(); + List> selectWithItems = insert.getSelect().getWithItemsList(); assertEquals("mytab3", insert.getTable().getFullyQualifiedName()); assertNull(insertWithItems); assertNull(selectWithItems); ExistsExpression exists = (ExistsExpression) insert.getPlainSelect().getWhere(); - assertEquals("(WITH t AS (SELECT * FROM mytab2) SELECT * FROM t)", exists.getRightExpression().toString()); + assertEquals("(WITH t AS (SELECT * FROM mytab2) SELECT * FROM t)", + exists.getRightExpression().toString()); } @Test @@ -410,12 +418,14 @@ public void testInsertKeyWordIntervalIssue682() throws JSQLParserException { @Test public void testWithAtFront() throws JSQLParserException { - String sqlStr = "WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo"; + String sqlStr = + "WITH foo AS ( SELECT attr FROM bar ) INSERT INTO lalelu (attr) SELECT attr FROM foo"; Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - List insertWithItems = insert.getWithItemsList(); + List> insertWithItems = insert.getWithItemsList(); assertEquals("lalelu", insert.getTable().getFullyQualifiedName()); assertEquals(1, insertWithItems.size()); - assertEquals("SELECT attr FROM bar", insertWithItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT attr FROM bar", + insertWithItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" foo", insertWithItems.get(0).getAlias().toString()); assertEquals("SELECT attr FROM foo", insert.getSelect().toString()); assertEquals("foo", insert.getSelect().getPlainSelect().getFromItem().toString()); @@ -454,12 +464,14 @@ public void testDisableKeywordIssue945() throws JSQLParserException { @Test public void testWithListIssue282() throws JSQLParserException { - String sqlStr = "WITH myctl AS (SELECT a, b FROM mytable) INSERT INTO mytable SELECT a, b FROM myctl"; + String sqlStr = + "WITH myctl AS (SELECT a, b FROM mytable) INSERT INTO mytable SELECT a, b FROM myctl"; Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - List insertWithItems = insert.getWithItemsList(); + List> insertWithItems = insert.getWithItemsList(); assertEquals("mytable", insert.getTable().getFullyQualifiedName()); assertEquals(1, insertWithItems.size()); - assertEquals("SELECT a, b FROM mytable", insertWithItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT a, b FROM mytable", + insertWithItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" myctl", insertWithItems.get(0).getAlias().toString()); assertEquals("SELECT a, b FROM myctl", insert.getSelect().toString()); assertEquals("myctl", insert.getSelect().getPlainSelect().getFromItem().toString()); @@ -508,10 +520,12 @@ public void testInsertUnionSelectIssue1491() throws JSQLParserException { @Test public void testWithSelectFromDual() throws JSQLParserException { String sqlStr = "(with a as (select * from dual) select * from a)"; - ParenthesedSelect parenthesedSelect = (ParenthesedSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - List withItems = parenthesedSelect.getSelect().getWithItemsList(); + ParenthesedSelect parenthesedSelect = + (ParenthesedSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + List> withItems = parenthesedSelect.getSelect().getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("SELECT * FROM dual", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT * FROM dual", + withItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" a", withItems.get(0).getAlias().toString()); assertEquals("a", parenthesedSelect.getPlainSelect().getFromItem().toString()); assertEquals("[*]", parenthesedSelect.getPlainSelect().getSelectItems().toString()); @@ -573,10 +587,11 @@ public void insertOnConflictObjectsTest() throws JSQLParserException { String sqlStr = "WITH a ( a, b , c ) \n" + "AS (SELECT 1 , 2 , 3 )\n" + "insert into test\n" + "select * from a"; Insert insert = (Insert) CCJSqlParserUtil.parse(sqlStr); - List withItems = insert.getWithItemsList(); + List> withItems = insert.getWithItemsList(); assertEquals("test", insert.getTable().getFullyQualifiedName()); assertEquals(1, withItems.size()); - assertEquals("[1, 2, 3]", withItems.get(0).getSelect().getPlainSelect().getSelectItems().toString()); + assertEquals("[1, 2, 3]", + withItems.get(0).getSelect().getPlainSelect().getSelectItems().toString()); assertEquals(" a", withItems.get(0).getAlias().toString()); Expression whereExpression = CCJSqlParserUtil.parseExpression("a=1", false); @@ -645,7 +660,7 @@ void testMultiColumnConflictTargetIssue955() throws JSQLParserException { @Test public void testDefaultValues() throws JSQLParserException { String statement = "INSERT INTO mytable DEFAULT VALUES"; - //assertSqlCanBeParsedAndDeparsed(statement); + // assertSqlCanBeParsedAndDeparsed(statement); Insert insert = (Insert) parserManager.parse(new StringReader(statement)); assertEquals("mytable", insert.getTable().getFullyQualifiedName()); assertEquals("INSERT INTO MYTABLE DEFAULT VALUES", insert.toString().toUpperCase()); @@ -690,4 +705,136 @@ public void throwsParseWhenDefaultKeyowrdUsedAsAlias() { () -> parserManager.parse(new StringReader(statement))); } + @Test + void testInsertWithinCte() throws JSQLParserException { + String sqlStr = "WITH inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " RETURNING y " + + ") " + + "INSERT INTO z (blah) " + + "SELECT y FROM inserted"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", insert.getTable().toString()); + List> withItems = insert.getWithItemsList(); + assertEquals(1, withItems.size()); + Insert innerInsert = withItems.get(0).getInsert().getInsert(); + assertEquals("x", innerInsert.getTable().toString()); + assertEquals("SELECT bar FROM b", innerInsert.getSelect().toString()); + assertEquals(" RETURNING y", innerInsert.getReturningClause().toString()); + assertEquals("INSERT INTO x (foo) SELECT bar FROM b RETURNING y", innerInsert.toString()); + assertEquals(" inserted", withItems.get(0).getAlias().toString()); + } + + @Test + void testUpdateWithinCte() throws JSQLParserException { + String sqlStr = "WITH updated AS ( " + + " UPDATE x " + + " SET foo = 1 " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "INSERT INTO z (blah) " + + "SELECT y FROM updated"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", insert.getTable().toString()); + List> withItems = insert.getWithItemsList(); + assertEquals(1, withItems.size()); + Update update = withItems.get(0).getUpdate().getUpdate(); + assertEquals("x", update.getTable().toString()); + assertEquals("foo", update.getUpdateSets().get(0).getColumn(0).toString()); + assertEquals("1", update.getUpdateSets().get(0).getValue(0).toString()); + assertEquals("bar = 2", update.getWhere().toString()); + assertEquals(" RETURNING y", update.getReturningClause().toString()); + assertEquals(" updated", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteWithinCte() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "INSERT INTO z (blah) " + + "SELECT y FROM deleted"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", insert.getTable().toString()); + List> withItems = insert.getWithItemsList(); + assertEquals(1, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM deleted) " + + " RETURNING w " + + ") " + + "INSERT INTO z (blah) " + + "SELECT w FROM inserted"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", insert.getTable().toString()); + List> withItems = insert.getWithItemsList(); + assertEquals(2, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + Insert innerInsert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", innerInsert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM deleted)", + innerInsert.getSelect().toString()); + assertEquals(" RETURNING w", innerInsert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM deleted) RETURNING w", + innerInsert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + + @Test + void testSelectAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH selection AS ( " + + " SELECT y " + + " FROM z " + + " WHERE foo = 'bar' " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM selection) " + + " RETURNING w " + + ") " + + "INSERT INTO z (blah) " + + "SELECT w FROM inserted"; + Insert insert = (Insert) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", insert.getTable().toString()); + List> withItems = insert.getWithItemsList(); + assertEquals(2, withItems.size()); + PlainSelect select = withItems.get(0).getSelect().getPlainSelect(); + assertEquals("SELECT y FROM z WHERE foo = 'bar'", select.toString()); + assertEquals(" selection", withItems.get(0).getAlias().toString()); + Insert innerInsert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", innerInsert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM selection)", + innerInsert.getSelect().toString()); + assertEquals(" RETURNING w", innerInsert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM selection) RETURNING w", + innerInsert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java index 83a4fe7ae..51b041470 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java @@ -128,7 +128,8 @@ public void testRecursiveBracketExpressionIssue1019() { // @todo: implement methods to set the Parser Timeout explicitly and on demand @Test public void testRecursiveBracketExpressionIssue1019_2() throws JSQLParserException { - doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 8); + // Temporally set the maxDepth to be 6, was 8 before this + doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 6); } @Test @@ -167,7 +168,8 @@ public void testIssue1013_4() throws JSQLParserException { */ // @Test(timeout = 6000) public void testIncreaseOfParseTime() throws JSQLParserException { - doIncreaseOfParseTimeTesting("concat($1,'B')", "'A'", 50); + // Temporally set the maxDepth to be 6, was 50 before this + doIncreaseOfParseTimeTesting("concat($1,'B')", "'A'", 6); } private void doIncreaseOfParseTimeTesting(String template, String finalExpression, int maxDepth) 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 e000a6346..3e7cd9fd4 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -66,6 +66,9 @@ import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.StatementVisitorAdapter; import net.sf.jsqlparser.statement.Statements; +import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.update.Update; import net.sf.jsqlparser.test.TestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.SerializationUtils; @@ -1702,21 +1705,26 @@ public void testWith() throws JSQLParserException { + "FROM EMPLOYEE AS THIS_EMP INNER JOIN DINFO INNER JOIN DINFOMAX " + "WHERE THIS_EMP.JOB = 'SALESREP' AND THIS_EMP.WORKDEPT = DINFO.DEPTNO"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(statement); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(2, withItems.size()); - assertEquals("SELECT OTHERS.WORKDEPT, AVG(OTHERS.SALARY), COUNT(*) FROM EMPLOYEE AS OTHERS GROUP BY OTHERS.WORKDEPT", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals( + "SELECT OTHERS.WORKDEPT, AVG(OTHERS.SALARY), COUNT(*) FROM EMPLOYEE AS OTHERS GROUP BY OTHERS.WORKDEPT", + withItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" DINFO", withItems.get(0).getAlias().toString()); - assertEquals("SELECT MAX(AVGSALARY) AS AVGMAX FROM DINFO", withItems.get(1).getSelect().getPlainSelect().toString()); + assertEquals("SELECT MAX(AVGSALARY) AS AVGMAX FROM DINFO", + withItems.get(1).getSelect().getPlainSelect().toString()); assertEquals(" DINFOMAX", withItems.get(1).getAlias().toString()); } @Test public void testWithRecursive() throws JSQLParserException { - String statement = "WITH RECURSIVE t (n) AS ((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100)) SELECT sum(n) FROM t"; + String statement = + "WITH RECURSIVE t (n) AS ((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100)) SELECT sum(n) FROM t"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(statement); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100))", withItems.get(0).getSelect().toString()); + assertEquals("((SELECT 1) UNION ALL (SELECT n + 1 FROM t WHERE n < 100))", + withItems.get(0).getSelect().toString()); assertEquals(" t", withItems.get(0).getAlias().toString()); assertTrue(withItems.get(0).isRecursive()); } @@ -2373,9 +2381,10 @@ public void testWithStatement() throws JSQLParserException { String stmt = "WITH test AS (SELECT mslink FROM feature) SELECT * FROM feature WHERE mslink IN (SELECT mslink FROM test)"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("SELECT mslink FROM feature", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT mslink FROM feature", + withItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" test", withItems.get(0).getAlias().toString()); } @@ -2390,9 +2399,10 @@ public void testWithUnionProblem() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink FROM tablea) UNION (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT mslink FROM tablea) UNION (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals("((SELECT mslink FROM tablea) UNION (SELECT mslink FROM tableb))", + withItems.get(0).getSelect().toString()); assertEquals(" test", withItems.get(0).getAlias().toString()); } @@ -2401,9 +2411,10 @@ public void testWithUnionAllProblem() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink FROM tablea) UNION ALL (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT mslink FROM tablea) UNION ALL (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals("((SELECT mslink FROM tablea) UNION ALL (SELECT mslink FROM tableb))", + withItems.get(0).getSelect().toString()); assertEquals(" test", withItems.get(0).getAlias().toString()); } @@ -2412,9 +2423,11 @@ public void testWithUnionProblem3() throws JSQLParserException { String stmt = "WITH test AS ((SELECT mslink, CAST(tablea.fname AS varchar) FROM tablea INNER JOIN tableb ON tablea.mslink = tableb.mslink AND tableb.deleted = 0 WHERE tablea.fname IS NULL AND 1 = 0) UNION ALL (SELECT mslink FROM tableb)) SELECT * FROM tablea WHERE mslink IN (SELECT mslink FROM test)"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT mslink, CAST(tablea.fname AS varchar) FROM tablea INNER JOIN tableb ON tablea.mslink = tableb.mslink AND tableb.deleted = 0 WHERE tablea.fname IS NULL AND 1 = 0) UNION ALL (SELECT mslink FROM tableb))", withItems.get(0).getSelect().toString()); + assertEquals( + "((SELECT mslink, CAST(tablea.fname AS varchar) FROM tablea INNER JOIN tableb ON tablea.mslink = tableb.mslink AND tableb.deleted = 0 WHERE tablea.fname IS NULL AND 1 = 0) UNION ALL (SELECT mslink FROM tableb))", + withItems.get(0).getSelect().toString()); assertEquals(" test", withItems.get(0).getAlias().toString()); } @@ -2423,9 +2436,11 @@ public void testWithUnionProblem4() throws JSQLParserException { String stmt = "WITH hist AS ((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0)) SELECT mslink, space(level * 4) + txt AS txt, nr, feature, path FROM hist WHERE EXISTS (SELECT feature FROM tablec WHERE mslink = 0 AND ((feature IN (1, 2) AND hist.feature = 3) OR (feature IN (4) AND hist.feature = 2)))"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", withItems.get(0).getSelect().toString()); + assertEquals( + "((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", + withItems.get(0).getSelect().toString()); assertEquals(" hist", withItems.get(0).getAlias().toString()); } @@ -2434,9 +2449,11 @@ public void testWithUnionProblem5() throws JSQLParserException { String stmt = "WITH hist AS ((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, 5 AS feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0)) SELECT * FROM hist"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, 5 AS feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", withItems.get(0).getSelect().toString()); + assertEquals( + "((SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, 0 AS level, CAST(gl.mslink AS VARCHAR) AS path, ae.feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 WHERE gl.parent IS NULL AND gl.mslink <> 0) UNION ALL (SELECT gl.mslink, ba.gl_name AS txt, ba.gl_nummer AS nr, hist.level + 1 AS level, CAST(hist.path + '.' + CAST(gl.mslink AS VARCHAR) AS VARCHAR) AS path, 5 AS feature FROM tablea AS gl INNER JOIN tableb AS ba ON gl.mslink = ba.gl_mslink INNER JOIN tablec AS ae ON gl.mslink = ae.mslink AND ae.deleted = 0 INNER JOIN hist ON gl.parent = hist.mslink WHERE gl.mslink <> 0))", + withItems.get(0).getSelect().toString()); assertEquals(" hist", withItems.get(0).getAlias().toString()); } @@ -3164,12 +3181,14 @@ public void testSelectOracleColl() throws JSQLParserException { @Test public void testSelectInnerWith() throws JSQLParserException { - String stmt = "SELECT * FROM (WITH actor AS (SELECT 'a' aid FROM DUAL) SELECT aid FROM actor)"; + String stmt = + "SELECT * FROM (WITH actor AS (SELECT 'a' aid FROM DUAL) SELECT aid FROM actor)"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems1 = select.getWithItemsList(); + List> withItems1 = select.getWithItemsList(); assertNull(withItems1); - ParenthesedSelect parenthesedSelect = (ParenthesedSelect) select.getPlainSelect().getFromItem(); - List withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); + ParenthesedSelect parenthesedSelect = + (ParenthesedSelect) select.getPlainSelect().getFromItem(); + List> withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); assertEquals(1, withItems2.size()); assertEquals("(SELECT 'a' aid FROM DUAL)", withItems2.get(0).getSelect().toString()); assertEquals(" actor", withItems2.get(0).getAlias().toString()); @@ -3183,9 +3202,10 @@ public void testSelectInnerWith() throws JSQLParserException { @Test public void testSelectInnerWithAndUnionIssue1084_2() throws JSQLParserException { - String stmt = "WITH actor AS (SELECT 'b' aid FROM DUAL) SELECT aid FROM actor UNION SELECT aid FROM actor2"; + String stmt = + "WITH actor AS (SELECT 'b' aid FROM DUAL) SELECT aid FROM actor UNION SELECT aid FROM actor2"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); assertEquals("(SELECT 'b' aid FROM DUAL)", withItems.get(0).getSelect().toString()); assertEquals(" actor", withItems.get(0).getAlias().toString()); @@ -4580,10 +4600,11 @@ public void testEmptyDoubleQuotes_2() throws JSQLParserException { public void testInnerWithBlock() throws JSQLParserException { String stmt = "select 1 from (with mytable1 as (select 2 ) select 3 from mytable1 ) first"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); - List withItems1 = select.getWithItemsList(); + List> withItems1 = select.getWithItemsList(); assertNull(withItems1); - ParenthesedSelect parenthesedSelect = (ParenthesedSelect) select.getPlainSelect().getFromItem(); - List withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); + ParenthesedSelect parenthesedSelect = + (ParenthesedSelect) select.getPlainSelect().getFromItem(); + List> withItems2 = parenthesedSelect.getPlainSelect().getWithItemsList(); assertEquals(1, withItems2.size()); assertEquals("(SELECT 2)", withItems2.get(0).getSelect().toString()); assertEquals(" mytable1", withItems2.get(0).getAlias().toString()); @@ -4728,11 +4749,13 @@ public void testPartitionByWithBracketsIssue865() throws JSQLParserException { @Test public void testWithAsRecursiveIssue874() throws JSQLParserException { - String stmt = "WITH rn AS (SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1)) SELECT pname FROM t1, rn WHERE rn <= cases ORDER BY pname"; + String stmt = + "WITH rn AS (SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1)) SELECT pname FROM t1, rn WHERE rn <= cases ORDER BY pname"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("(SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1))", withItems.get(0).getSelect().toString()); + assertEquals("(SELECT rownum rn FROM dual CONNECT BY level <= (SELECT max(cases) FROM t1))", + withItems.get(0).getSelect().toString()); assertEquals(" rn", withItems.get(0).getAlias().toString()); } @@ -5170,11 +5193,13 @@ public void testProblematicDeparsingIssue1183_2() throws JSQLParserException { @Test public void testKeywordCostsIssue1185() throws JSQLParserException { - String stmt = "WITH costs AS (SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1) SELECT * FROM TESTSTMT"; + String stmt = + "WITH costs AS (SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1) SELECT * FROM TESTSTMT"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("(SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1)", withItems.get(0).getSelect().toString()); + assertEquals("(SELECT * FROM MY_TABLE1 AS ALIAS_TABLE1)", + withItems.get(0).getSelect().toString()); assertEquals(" costs", withItems.get(0).getAlias().toString()); } @@ -5190,11 +5215,13 @@ public void testConditionsWithExtraBrackets_Issue1194() throws JSQLParserExcepti @Test public void testWithValueListWithExtraBrackets1135() throws JSQLParserException { - String stmt = "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) select day, value from sample_data"; + String stmt = + "with sample_data(day, value) as (values ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))) select day, value from sample_data"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); - assertEquals("VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))", withItems.get(0).getSelect().getValues().toString()); + assertEquals("VALUES ((0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16))", + withItems.get(0).getSelect().getValues().toString()); assertEquals(" sample_data", withItems.get(0).getAlias().toString()); } @@ -5203,28 +5230,31 @@ public void testWithValueListWithOutExtraBrackets1135() throws JSQLParserExcepti String stmt1 = "with sample_data(\"DAY\") as (values 0, 1, 2)\n" + " select \"DAY\" from sample_data"; Select select1 = (Select) assertSqlCanBeParsedAndDeparsed(stmt1, true); - List withItems1 = select1.getWithItemsList(); + List> withItems1 = select1.getWithItemsList(); assertEquals(1, withItems1.size()); assertEquals("VALUES 0, 1, 2", withItems1.get(0).getSelect().getValues().toString()); assertEquals(" sample_data", withItems1.get(0).getAlias().toString()); - String stmt2 = "with sample_data(day, value) as (values (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)) select day, value from sample_data"; + String stmt2 = + "with sample_data(day, value) as (values (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)) select day, value from sample_data"; Select select2 = (Select) assertSqlCanBeParsedAndDeparsed(stmt2, true); - List withItems2 = select2.getWithItemsList(); + List> withItems2 = select2.getWithItemsList(); assertEquals(1, withItems2.size()); - assertEquals("VALUES (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)", withItems2.get(0).getSelect().getValues().toString()); + assertEquals("VALUES (0, 13), (1, 12), (2, 15), (3, 4), (4, 8), (5, 16)", + withItems2.get(0).getSelect().getValues().toString()); assertEquals(" sample_data", withItems2.get(0).getAlias().toString()); } @Test public void testWithInsideWithIssue1186() throws JSQLParserException { - String stmt = "WITH TESTSTMT1 AS ( WITH TESTSTMT2 AS (SELECT * FROM MY_TABLE2) SELECT col1, col2 FROM TESTSTMT2) SELECT * FROM TESTSTMT"; + String stmt = + "WITH TESTSTMT1 AS ( WITH TESTSTMT2 AS (SELECT * FROM MY_TABLE2) SELECT col1, col2 FROM TESTSTMT2) SELECT * FROM TESTSTMT"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(stmt, true); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); assertEquals(" TESTSTMT1", withItems.get(0).getAlias().toString()); ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItems.get(0).getSelect(); - List withItems2 = parenthesedSelect.getSelect().getWithItemsList(); + List> withItems2 = parenthesedSelect.getSelect().getWithItemsList(); assertEquals(1, withItems2.size()); assertEquals("(SELECT * FROM MY_TABLE2)", withItems2.get(0).getSelect().toString()); assertEquals(" TESTSTMT2", withItems2.get(0).getAlias().toString()); @@ -5731,15 +5761,15 @@ void testNestedWithItems() throws JSQLParserException { String sqlStr = "with a as ( with b as ( with c as (select 1) select c.* from c) select b.* from b) select a.* from a"; Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr, true); - List withItems = select.getWithItemsList(); + List> withItems = select.getWithItemsList(); assertEquals(1, withItems.size()); assertEquals(" a", withItems.get(0).getAlias().toString()); ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItems.get(0).getSelect(); - List withItems2 = parenthesedSelect.getSelect().getWithItemsList(); + List> withItems2 = parenthesedSelect.getSelect().getWithItemsList(); assertEquals(1, withItems2.size()); assertEquals(" b", withItems2.get(0).getAlias().toString()); ParenthesedSelect parenthesedSelect2 = (ParenthesedSelect) withItems2.get(0).getSelect(); - List withItems3 = parenthesedSelect2.getSelect().getWithItemsList(); + List> withItems3 = parenthesedSelect2.getSelect().getWithItemsList(); assertEquals(1, withItems3.size()); assertEquals("(SELECT 1)", withItems3.get(0).getSelect().toString()); assertEquals(" c", withItems3.get(0).getAlias().toString()); @@ -5929,4 +5959,132 @@ void testGroupByWithHaving() throws JSQLParserException { Statement stmt = assertSqlCanBeParsedAndDeparsed(sqlStr); Assertions.assertInstanceOf(Select.class, stmt); } + + @Test + void testInsertWithinCte() throws JSQLParserException { + String sqlStr = "WITH inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " RETURNING y " + + ") " + + "SELECT y " + + " FROM inserted"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr); + List> withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + Insert insert = withItems.get(0).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b", insert.getSelect().toString()); + assertEquals(" RETURNING y", insert.getReturningClause().toString()); + assertEquals("INSERT INTO x (foo) SELECT bar FROM b RETURNING y", insert.toString()); + assertEquals(" inserted", withItems.get(0).getAlias().toString()); + } + + @Test + void testUpdateWithinCte() throws JSQLParserException { + String sqlStr = "WITH updated AS ( " + + " UPDATE x " + + " SET foo = 1 " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "SELECT y " + + " FROM updated"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr); + List> withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + Update update = withItems.get(0).getUpdate().getUpdate(); + assertEquals("x", update.getTable().toString()); + assertEquals("foo", update.getUpdateSets().get(0).getColumn(0).toString()); + assertEquals("1", update.getUpdateSets().get(0).getValue(0).toString()); + assertEquals("bar = 2", update.getWhere().toString()); + assertEquals(" RETURNING y", update.getReturningClause().toString()); + assertEquals(" updated", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteWithinCte() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + "SELECT y " + + " FROM deleted"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr); + List> withItems = select.getWithItemsList(); + assertEquals(1, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM deleted) " + + " RETURNING w " + + ") " + + "SELECT w " + + " FROM inserted"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr); + List> withItems = select.getWithItemsList(); + assertEquals(2, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM deleted)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM deleted) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + + @Test + void testSelectAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH selection AS ( " + + " SELECT y " + + " FROM z " + + " WHERE foo = 'bar' " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM selection) " + + " RETURNING w " + + ") " + + "SELECT w " + + " FROM inserted"; + Select select = (Select) assertSqlCanBeParsedAndDeparsed(sqlStr); + List> withItems = select.getWithItemsList(); + assertEquals(2, withItems.size()); + PlainSelect innerSelect = withItems.get(0).getSelect().getPlainSelect(); + assertEquals("SELECT y FROM z WHERE foo = 'bar'", innerSelect.toString()); + assertEquals(" selection", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM selection)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM selection) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + } diff --git a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java index 669d3e60e..90d04c358 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -19,6 +19,9 @@ import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; @@ -232,17 +235,20 @@ public void testWith() throws JSQLParserException { + "WHERE id_instrument_ref = (SELECT id_instrument_ref\n" + " FROM a)"; Update update = (Update) assertSqlCanBeParsedAndDeparsed(statement, true); - List withItems = update.getWithItemsList(); + List> withItems = update.getWithItemsList(); assertEquals("cfe.instrument_ref", update.getTable().getFullyQualifiedName()); assertEquals(2, withItems.size()); - assertEquals("SELECT 1 id_instrument_ref", withItems.get(0).getSelect().getPlainSelect().toString()); + assertEquals("SELECT 1 id_instrument_ref", + withItems.get(0).getSelect().getPlainSelect().toString()); assertEquals(" a", withItems.get(0).getAlias().toString()); - assertEquals("SELECT 1 id_instrument_ref", withItems.get(1).getSelect().getPlainSelect().toString()); + assertEquals("SELECT 1 id_instrument_ref", + withItems.get(1).getSelect().getPlainSelect().toString()); assertEquals(" b", withItems.get(1).getAlias().toString()); assertEquals(1, update.getUpdateSets().size()); assertEquals("id_instrument", update.getUpdateSets().get(0).getColumn(0).toString()); assertEquals("NULL", update.getUpdateSets().get(0).getValue(0).toString()); - assertEquals("id_instrument_ref = (SELECT id_instrument_ref FROM a)", update.getWhere().toString()); + assertEquals("id_instrument_ref = (SELECT id_instrument_ref FROM a)", + update.getWhere().toString()); } @Test @@ -390,4 +396,142 @@ void testIssue1910() throws JSQLParserException { TestUtils.assertStatementCanBeDeparsedAs(update, "UPDATE sys_dept SET (deleted, created) = (1,2)", true); } + + @Test + void testInsertWithinCte() throws JSQLParserException { + String sqlStr = "WITH inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " RETURNING y " + + ") " + + " UPDATE z " + + " SET foo = 1 " + + " WHERE y IN (SELECT y FROM inserted) "; + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", update.getTable().toString()); + List> withItems = update.getWithItemsList(); + assertEquals(1, withItems.size()); + Insert insert = withItems.get(0).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b", insert.getSelect().toString()); + assertEquals(" RETURNING y", insert.getReturningClause().toString()); + assertEquals("INSERT INTO x (foo) SELECT bar FROM b RETURNING y", insert.toString()); + assertEquals(" inserted", withItems.get(0).getAlias().toString()); + } + + @Test + void testUpdateWithinCte() throws JSQLParserException { + String sqlStr = "WITH updated AS ( " + + " UPDATE x " + + " SET foo = 1 " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + " UPDATE z " + + " SET foo = 1 " + + " WHERE y IN (SELECT y FROM inserted) "; + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", update.getTable().toString()); + List> withItems = update.getWithItemsList(); + assertEquals(1, withItems.size()); + Update innerUpdate = withItems.get(0).getUpdate().getUpdate(); + assertEquals("x", innerUpdate.getTable().toString()); + assertEquals("foo", innerUpdate.getUpdateSets().get(0).getColumn(0).toString()); + assertEquals("1", innerUpdate.getUpdateSets().get(0).getValue(0).toString()); + assertEquals("bar = 2", innerUpdate.getWhere().toString()); + assertEquals(" RETURNING y", innerUpdate.getReturningClause().toString()); + assertEquals(" updated", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteWithinCte() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + " UPDATE z " + + " SET foo = 1 " + + " WHERE y IN (SELECT y FROM inserted) "; + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", update.getTable().toString()); + List> withItems = update.getWithItemsList(); + assertEquals(1, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + } + + @Test + void testDeleteAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH deleted AS ( " + + " DELETE FROM x " + + " WHERE bar = 2 " + + " RETURNING y " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM deleted) " + + " RETURNING w " + + ") " + + " UPDATE z " + + " SET foo = 1 " + + " WHERE y IN (SELECT y FROM inserted) "; + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", update.getTable().toString()); + List> withItems = update.getWithItemsList(); + assertEquals(2, withItems.size()); + Delete delete = withItems.get(0).getDelete().getDelete(); + assertEquals("x", delete.getTable().toString()); + assertEquals("bar = 2", delete.getWhere().toString()); + assertEquals(" RETURNING y", delete.getReturningClause().toString()); + assertEquals(" deleted", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM deleted)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM deleted) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + + @Test + void testSelectAndInsertWithin2Ctes() throws JSQLParserException { + String sqlStr = "WITH selection AS ( " + + " SELECT y " + + " FROM z " + + " WHERE foo = 'bar' " + + ") " + + ", inserted AS ( " + + " INSERT INTO x (foo) " + + " SELECT bar FROM b " + + " WHERE y IN (SELECT y FROM selection) " + + " RETURNING w " + + ") " + + " UPDATE z " + + " SET foo = 1 " + + " WHERE y IN (SELECT y FROM inserted) "; + Update update = (Update) assertSqlCanBeParsedAndDeparsed(sqlStr); + assertEquals("z", update.getTable().toString()); + List> withItems = update.getWithItemsList(); + assertEquals(2, withItems.size()); + PlainSelect select = withItems.get(0).getSelect().getPlainSelect(); + assertEquals("SELECT y FROM z WHERE foo = 'bar'", select.toString()); + assertEquals(" selection", withItems.get(0).getAlias().toString()); + Insert insert = withItems.get(1).getInsert().getInsert(); + assertEquals("x", insert.getTable().toString()); + assertEquals("SELECT bar FROM b WHERE y IN (SELECT y FROM selection)", + insert.getSelect().toString()); + assertEquals(" RETURNING w", insert.getReturningClause().toString()); + assertEquals( + "INSERT INTO x (foo) SELECT bar FROM b WHERE y IN (SELECT y FROM selection) RETURNING w", + insert.toString()); + assertEquals(" inserted", withItems.get(1).getAlias().toString()); + } + } diff --git a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java index b0f8029c0..35e8db743 100644 --- a/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java +++ b/src/test/java/net/sf/jsqlparser/util/deparser/StatementDeParserTest.java @@ -108,7 +108,7 @@ public void shouldUseProvidedDeparsersWhenDeParsingInsert() { duplicateUpdateSets.add(new UpdateSet(duplicateUpdateColumn2, duplicateUpdateExpression2)); PlainSelect select = mock(PlainSelect.class); - List withItemsList = new ArrayList(); + List> withItemsList = new ArrayList>(); WithItem withItem1 = spy(new WithItem()); WithItem withItem2 = spy(new WithItem()); ParenthesedSelect withItem1SubSelect = mock(ParenthesedSelect.class); @@ -140,7 +140,7 @@ public void shouldUseProvidedDeParsersWhenDeParsingSelect() { WithItem withItem2 = spy(new WithItem()); withItem2.setSelect(mock(ParenthesedSelect.class)); - List withItemsList = new ArrayList(); + List> withItemsList = new ArrayList>(); withItemsList.add(withItem1); withItemsList.add(withItem2); @@ -289,7 +289,7 @@ public void shouldUseProvidedDeparsersWhenDeParsingUpsertWithExpressionList() { Expression duplicateUpdateExpression1 = mock(Expression.class); Expression duplicateUpdateExpression2 = mock(Expression.class); PlainSelect select = mock(PlainSelect.class); - List withItemsList = new ArrayList(); + List> withItemsList = new ArrayList>(); WithItem withItem1 = spy(new WithItem()); WithItem withItem2 = spy(new WithItem()); ParenthesedSelect withItem1SubSelect = mock(ParenthesedSelect.class); From 11616a0206ed7c556c0aaad8b4aaa00dbd8987e1 Mon Sep 17 00:00:00 2001 From: nicky6s Date: Mon, 19 Aug 2024 08:50:32 +0100 Subject: [PATCH 23/88] chore removing system.out.println lines + minor clean up of unit test scripts (#2060) * chore removing system.out.println lines + minor clean up * formatting fixes via spotlessApply --- .../statement/StatementSeparatorTest.java | 3 --- .../jsqlparser/statement/alter/AlterTest.java | 21 +++++++++++-------- .../jsqlparser/statement/merge/MergeTest.java | 4 ---- .../statement/select/SelectTest.java | 7 ------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java b/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java index f8b766300..7edbdc515 100644 --- a/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/StatementSeparatorTest.java @@ -53,7 +53,6 @@ void testNewLineNotGoIssue() throws JSQLParserException { void testOracleBlock() throws JSQLParserException { String sqlStr = "BEGIN\n" + "\n" + "SELECT * FROM TABLE;\n" + "\n" + "END\n" + "/\n"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - System.out.println(statement); } @Test @@ -69,7 +68,6 @@ void testSOQLIncludes() throws JSQLParserException { String sqlStr = "select name,\ngoods from test_table where option includes ('option1', 'option2')"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - System.out.println(statement); } @Test @@ -77,6 +75,5 @@ void testSOQLExcludes() throws JSQLParserException { String sqlStr = "select name,\ngoods from test_table where option excludes ('option1', 'option2')"; Statement statement = TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); - System.out.println(statement); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 36f510dbf..2deb2abcc 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -71,15 +71,14 @@ public void testAlterTableAddColumn_ColumnKeyWordImplicit() throws JSQLParserExc @Test public void testAlterTableBackBrackets() throws JSQLParserException { String sql = "ALTER TABLE tablename add column (field string comment 'aaaaa')"; - Statement statement = CCJSqlParserUtil.parse(sql); - Alter alter = (Alter) statement; - System.out.println(alter.toString()); + Alter alter = (Alter) assertSqlCanBeParsedAndDeparsed(sql); + assertEquals("tablename", alter.getTable().toString()); String sql2 = "ALTER TABLE tablename add column (field string comment 'aaaaa', field2 string comment 'bbbbb');"; Statement statement2 = CCJSqlParserUtil.parse(sql2); Alter alter2 = (Alter) statement2; - System.out.println(alter2.toString()); + assertEquals("tablename", alter2.getTable().toString()); } @@ -1025,20 +1024,24 @@ public void testIssue1875() throws JSQLParserException { } @Test - public void testIssue2027() throws JSQLParserException{ + public void testIssue2027() throws JSQLParserException { String sql = "ALTER TABLE `foo_bar` ADD COLUMN `baz` text"; assertSqlCanBeParsedAndDeparsed(sql); - String sqlText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + String sqlText = + "ALTER TABLE `foo_bar` ADD COLUMN `baz` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; assertSqlCanBeParsedAndDeparsed(sqlText); - String sqlTinyText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + String sqlTinyText = + "ALTER TABLE `foo_bar` ADD COLUMN `baz` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; assertSqlCanBeParsedAndDeparsed(sqlTinyText); - String sqlMediumText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + String sqlMediumText = + "ALTER TABLE `foo_bar` ADD COLUMN `baz` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; assertSqlCanBeParsedAndDeparsed(sqlMediumText); - String sqlLongText = "ALTER TABLE `foo_bar` ADD COLUMN `baz` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; + String sqlLongText = + "ALTER TABLE `foo_bar` ADD COLUMN `baz` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; assertSqlCanBeParsedAndDeparsed(sqlLongText); } } diff --git a/src/test/java/net/sf/jsqlparser/statement/merge/MergeTest.java b/src/test/java/net/sf/jsqlparser/statement/merge/MergeTest.java index 678b8e7f8..470b8c163 100644 --- a/src/test/java/net/sf/jsqlparser/statement/merge/MergeTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/merge/MergeTest.java @@ -42,10 +42,6 @@ public void testOracleMergeIntoStatement() throws JSQLParserException { + " INSERT (B.employee_id, B.bonus)\n" + " VALUES (E.employee_id, E.salary * 0.05) "; - Statement statement = CCJSqlParserUtil.parse(sql); - - System.out.println(statement.toString()); - assertSqlCanBeParsedAndDeparsed(sql, true); } 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 3e7cd9fd4..6ef1fc163 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -4539,13 +4539,6 @@ public void testLongQualifiedNamesIssue763() throws JSQLParserException { "SELECT mongodb.test.test.intField, postgres.test.test.intField, postgres.test.test.datefield FROM mongodb.test.test JOIN postgres.postgres.test.test ON mongodb.test.test.intField = postgres.test.test.intField WHERE mongodb.test.test.intField = 123"); } - @Test - public void testLongQualifiedNamesIssue763_2() throws JSQLParserException { - Statement parse = CCJSqlParserUtil.parse(new StringReader( - "SELECT mongodb.test.test.intField, postgres.test.test.intField, postgres.test.test.datefield FROM mongodb.test.test JOIN postgres.postgres.test.test ON mongodb.test.test.intField = postgres.test.test.intField WHERE mongodb.test.test.intField = 123")); - System.out.println(parse.toString()); - } - @Test public void testSubQueryAliasIssue754() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( From d7bf249b94c97ffacef83c628c4c8c4cf32a8cce Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Mon, 19 Aug 2024 16:11:25 +0700 Subject: [PATCH 24/88] feat: `CREATE SCHEMA IF NOT EXISTS ...` - fixes #2061 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../statement/create/schema/CreateSchema.java | 13 +++++++++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 2 +- .../statement/create/schema/CreateSchemaTest.java | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java b/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java index 0a17ddb8c..ea4cdc64d 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/schema/CreateSchema.java @@ -24,6 +24,7 @@ public class CreateSchema implements Statement { private String schemaName; private List schemaPath; private List statements = new ArrayList<>(); + private boolean hasIfNotExists = false; @Override public T accept(StatementVisitor statementVisitor, S context) { @@ -103,8 +104,20 @@ public List getStatements() { return statements; } + public boolean hasIfNotExists() { + return hasIfNotExists; + } + + public CreateSchema setIfNotExists(boolean hasIfNotExists) { + this.hasIfNotExists = hasIfNotExists; + return this; + } + public String toString() { String sql = "CREATE SCHEMA"; + if (hasIfNotExists) { + sql += " IF NOT EXISTS"; + } if (schemaName != null) { sql += " " + schemaName; } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 9cfb81eb6..48d532cda 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5946,7 +5946,7 @@ CreateSchema CreateSchema(): List statements = new ArrayList(); } { - + [ { schema.setIfNotExists(true); } ] [ ( tk= | tk=) { schema.setSchemaName(tk.image); } ] [ (tk= | tk=) { schema.setAuthorization(tk.image); } diff --git a/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java b/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java index c002bbd01..5e100d125 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/schema/CreateSchemaTest.java @@ -34,4 +34,10 @@ public void testSimpleCreateWithAuth() throws JSQLParserException { assertDeparse(new CreateSchema().withSchemaName("myschema").withAuthorization("myauth"), statement); } + + @Test + void testIfNotExistsIssue2061() throws JSQLParserException { + String sqlStr = "CREATE SCHEMA IF NOT EXISTS sales_kpi"; + assertSqlCanBeParsedAndDeparsed(sqlStr); + } } From cd0689e0120fc8e662d8dd9c25544a3ad35737b6 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Mon, 19 Aug 2024 16:59:53 +0700 Subject: [PATCH 25/88] fix: remove obsolete `SimpleFunction` - fixes #2059 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 56 ++----------------- .../jsqlparser/expression/FunctionTest.java | 8 +++ 2 files changed, 12 insertions(+), 52 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 48d532cda..a49e3c61f 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5587,7 +5587,6 @@ Function Function() #Function: { ( "{" function = InternalFunction(true) "}" - | LOOKAHEAD( SimpleFunction(), { getAsBoolean(Feature.allowComplexParsing) }) function = SimpleFunction() | LOOKAHEAD(3) function = SpecialStringFunctionWithNamedParameters() | function = InternalFunction(false) ) @@ -5623,57 +5622,6 @@ Function SpecialStringFunctionWithNamedParameters() : } } -// a simplified function with only one parameter -// useful for parsing nested functions fast -Function SimpleFunction(): -{ - Function function = new Function(); - ObjectNames name; - Expression expr=null; - Expression attributeExpression = null; - Column attributeColumn = null; -} -{ - name = RelObjectNames() - "(" - [ - ( - "*" { expr = new AllColumns(); } - | - LOOKAHEAD( AllTableColumns() ) expr=AllTableColumns() - | - LOOKAHEAD( 3 ) expr = ParenthesedSelect() - | - LOOKAHEAD( SimpleFunction() ) expr = SimpleFunction() - | - LOOKAHEAD( RegularCondition() ) expr = RegularCondition() - | - LOOKAHEAD( SimpleExpressionList() ) expr = SimpleExpressionList() - ) - ] - ")" - { - function.setName(name.getNames()); - if (expr!=null) { - function.setParameters(expr); - } - } - - [ LOOKAHEAD(2) "." ( - // tricky lookahead since we do need to support the following constructs - // schema.f1().f2() - Function with Function Column - // schema.f1().f2.f3 - Function with Attribute Column - LOOKAHEAD( Function() ) attributeExpression=Function() { function.setAttribute(attributeExpression); } - | - attributeColumn=Column() { function.setAttribute(attributeColumn); } - ) - ] - - { - return function; - } -} - Function InternalFunction(boolean escaped): { Token prefixToken = null; @@ -5701,6 +5649,10 @@ Function InternalFunction(boolean escaped): ) ] ( + "*" { expr = new AllColumns(); expressionList = new ExpressionList(expr); } + | + LOOKAHEAD( AllTableColumns() ) expr=AllTableColumns() { expressionList = new ExpressionList(expr); } + | LOOKAHEAD(3) expressionList=ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] | expr = Select() { expressionList = new ExpressionList(expr); } diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java index cd0f17278..e2e36dc7d 100644 --- a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java @@ -75,4 +75,12 @@ void testSubSelectArrayWithoutKeywordParameter() throws JSQLParserException { " UNNEST(addresses) AS email"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testSimpleFunctionIssue2059() throws JSQLParserException { + String sqlStr = "select count(*) from zzz"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true, parser -> { + parser.withAllowComplexParsing(false); + }); + } } From 6298e79be75ba0da6fdbbfa1dd6ad69a820d77fc Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Mon, 19 Aug 2024 17:49:52 +0700 Subject: [PATCH 26/88] build: exclude Parser classes from coverage to avoid 'too large' exception Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 144479930..2e68982b1 100644 --- a/build.gradle +++ b/build.gradle @@ -187,6 +187,10 @@ test { environment = [ 'EXPORT_TEST_TO_FILE': 'True' ] useJUnitPlatform() + jacoco { + excludes = ['net/sf/jsqlparser/parser/CCJSqlParserTokenManager'] + } + // set heap size for the test JVM(s) minHeapSize = "128m" maxHeapSize = "1G" From 728b286f0948aba9d3b86bd0786f9a3627e65361 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Tue, 20 Aug 2024 00:18:53 +0700 Subject: [PATCH 27/88] feat: methods for returning unquoted names and identifiers Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../java/net/sf/jsqlparser/schema/Column.java | 9 +++++++++ .../net/sf/jsqlparser/schema/Database.java | 5 +++++ .../sf/jsqlparser/schema/MultiPartName.java | 17 +++++++++++++++++ .../net/sf/jsqlparser/schema/Sequence.java | 5 +++++ .../java/net/sf/jsqlparser/schema/Server.java | 5 +++++ .../net/sf/jsqlparser/schema/Synonym.java | 5 +++++ .../java/net/sf/jsqlparser/schema/Table.java | 19 ++++++++++++++++++- 7 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/schema/Column.java b/src/main/java/net/sf/jsqlparser/schema/Column.java index 55b5a31a9..51db18013 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Column.java +++ b/src/main/java/net/sf/jsqlparser/schema/Column.java @@ -100,6 +100,10 @@ public String getColumnName() { return columnName; } + public String getUnquotedColumnName() { + return unquote(columnName); + } + public void setColumnName(String string) { columnName = string; } @@ -117,6 +121,11 @@ public String getFullyQualifiedName() { return getFullyQualifiedName(false); } + @Override + public String getUnquotedName() { + return unquote(columnName); + } + public String getFullyQualifiedName(boolean aliases) { StringBuilder fqn = new StringBuilder(); diff --git a/src/main/java/net/sf/jsqlparser/schema/Database.java b/src/main/java/net/sf/jsqlparser/schema/Database.java index 00f65f8e8..1bbf659bb 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Database.java +++ b/src/main/java/net/sf/jsqlparser/schema/Database.java @@ -57,6 +57,11 @@ public String getFullyQualifiedName() { return fqn; } + @Override + public String getUnquotedName() { + return unquote(databaseName); + } + @Override public String toString() { return getFullyQualifiedName(); diff --git a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java index 57960855b..c80c40a4a 100644 --- a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java +++ b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java @@ -9,7 +9,24 @@ */ package net.sf.jsqlparser.schema; +import java.util.regex.Pattern; + public interface MultiPartName { + Pattern LEADING_TRAILING_QUOTES_PATTERN = Pattern.compile("^[\"\\[`]+|[\"\\]`]+$"); + + /** + * Removes leading and trailing quotes from a SQL quoted identifier + * + * @param quotedIdentifier the quoted identifier + * @return the pure identifier without quotes + */ + default String unquote(String quotedIdentifier) { + return quotedIdentifier != null + ? LEADING_TRAILING_QUOTES_PATTERN.matcher(quotedIdentifier).replaceAll("") + : null; + } String getFullyQualifiedName(); + + String getUnquotedName(); } diff --git a/src/main/java/net/sf/jsqlparser/schema/Sequence.java b/src/main/java/net/sf/jsqlparser/schema/Sequence.java index d58f04ab7..b3626dbf8 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Sequence.java +++ b/src/main/java/net/sf/jsqlparser/schema/Sequence.java @@ -121,6 +121,11 @@ public String getFullyQualifiedName() { return fqn.toString(); } + @Override + public String getUnquotedName() { + return unquote(partItems.get(NAME_IDX)); + } + @Override public String toString() { StringBuilder sql = new StringBuilder(getFullyQualifiedName()); diff --git a/src/main/java/net/sf/jsqlparser/schema/Server.java b/src/main/java/net/sf/jsqlparser/schema/Server.java index d04c5c69b..647394287 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Server.java +++ b/src/main/java/net/sf/jsqlparser/schema/Server.java @@ -69,6 +69,11 @@ public String getFullyQualifiedName() { } } + @Override + public String getUnquotedName() { + return unquote(serverName); + } + @Override public String toString() { return getFullyQualifiedName(); diff --git a/src/main/java/net/sf/jsqlparser/schema/Synonym.java b/src/main/java/net/sf/jsqlparser/schema/Synonym.java index ae938d357..6c67a96bd 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Synonym.java +++ b/src/main/java/net/sf/jsqlparser/schema/Synonym.java @@ -106,6 +106,11 @@ public String getFullyQualifiedName() { return fqn.toString(); } + @Override + public String getUnquotedName() { + return unquote(partItems.get(NAME_IDX)); + } + @Override public String toString() { StringBuilder sql = new StringBuilder(getFullyQualifiedName()); diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 1c8a3e5a6..616616002 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -103,6 +103,14 @@ public Database getDatabase() { return new Database(getIndex(DATABASE_IDX)); } + public String getDatabaseName() { + return getIndex(DATABASE_IDX); + } + + public String getUnquotedDatabaseName() { + return unquote(getDatabaseName()); + } + public void setDatabase(Database database) { setIndex(DATABASE_IDX, database.getDatabaseName()); if (database.getServer() != null) { @@ -124,6 +132,10 @@ public String getSchemaName() { return getIndex(SCHEMA_IDX); } + public String getUnquotedSchemaName() { + return unquote(getSchemaName()); + } + public Table setSchemaName(String schemaName) { this.setIndex(SCHEMA_IDX, schemaName); return this; @@ -145,6 +157,7 @@ public String getName() { return name; } + public void setName(String name) { setIndex(NAME_IDX, name); } @@ -207,7 +220,6 @@ public String getFullyQualifiedName() { partItems.remove(partItems.size() - 1); } - for (int i = partItems.size() - 1; i >= 0; i--) { String part = partItems.get(i); if (part == null) { @@ -222,6 +234,11 @@ public String getFullyQualifiedName() { return fqn.toString(); } + @Override + public String getUnquotedName() { + return unquote(getName()); + } + @Override public T accept(FromItemVisitor fromItemVisitor, S context) { return fromItemVisitor.visit(this, context); From 7e7acba1b7d8e5430bb694967c7a0d82cb0f56e2 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Tue, 20 Aug 2024 00:44:42 +0700 Subject: [PATCH 28/88] feat: methods for returning unquoted names and identifiers Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- src/main/java/net/sf/jsqlparser/expression/Alias.java | 5 +++++ src/main/java/net/sf/jsqlparser/schema/Column.java | 4 ++-- src/main/java/net/sf/jsqlparser/schema/Database.java | 2 +- .../java/net/sf/jsqlparser/schema/MultiPartName.java | 2 +- src/main/java/net/sf/jsqlparser/schema/Sequence.java | 2 +- src/main/java/net/sf/jsqlparser/schema/Server.java | 2 +- src/main/java/net/sf/jsqlparser/schema/Synonym.java | 2 +- src/main/java/net/sf/jsqlparser/schema/Table.java | 6 +++--- .../net/sf/jsqlparser/statement/select/SelectItem.java | 8 ++++++++ .../net/sf/jsqlparser/statement/select/WithItem.java | 10 ++++++++-- 10 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/Alias.java b/src/main/java/net/sf/jsqlparser/expression/Alias.java index cd50e12cc..3011b0985 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Alias.java +++ b/src/main/java/net/sf/jsqlparser/expression/Alias.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.Optional; +import net.sf.jsqlparser.schema.MultiPartName; import net.sf.jsqlparser.statement.create.table.ColDataType; public class Alias implements Serializable { @@ -38,6 +39,10 @@ public String getName() { return name; } + public String getUnquotedName() { + return MultiPartName.unquote(name); + } + public void setName(String name) { this.name = name; } diff --git a/src/main/java/net/sf/jsqlparser/schema/Column.java b/src/main/java/net/sf/jsqlparser/schema/Column.java index 51db18013..18544012c 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Column.java +++ b/src/main/java/net/sf/jsqlparser/schema/Column.java @@ -101,7 +101,7 @@ public String getColumnName() { } public String getUnquotedColumnName() { - return unquote(columnName); + return MultiPartName.unquote(columnName); } public void setColumnName(String string) { @@ -123,7 +123,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(columnName); + return MultiPartName.unquote(columnName); } public String getFullyQualifiedName(boolean aliases) { diff --git a/src/main/java/net/sf/jsqlparser/schema/Database.java b/src/main/java/net/sf/jsqlparser/schema/Database.java index 1bbf659bb..c566b744f 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Database.java +++ b/src/main/java/net/sf/jsqlparser/schema/Database.java @@ -59,7 +59,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(databaseName); + return MultiPartName.unquote(databaseName); } @Override diff --git a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java index c80c40a4a..3e644a705 100644 --- a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java +++ b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java @@ -20,7 +20,7 @@ public interface MultiPartName { * @param quotedIdentifier the quoted identifier * @return the pure identifier without quotes */ - default String unquote(String quotedIdentifier) { + static String unquote(String quotedIdentifier) { return quotedIdentifier != null ? LEADING_TRAILING_QUOTES_PATTERN.matcher(quotedIdentifier).replaceAll("") : null; diff --git a/src/main/java/net/sf/jsqlparser/schema/Sequence.java b/src/main/java/net/sf/jsqlparser/schema/Sequence.java index b3626dbf8..2f813c1d7 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Sequence.java +++ b/src/main/java/net/sf/jsqlparser/schema/Sequence.java @@ -123,7 +123,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(partItems.get(NAME_IDX)); + return MultiPartName.unquote(partItems.get(NAME_IDX)); } @Override diff --git a/src/main/java/net/sf/jsqlparser/schema/Server.java b/src/main/java/net/sf/jsqlparser/schema/Server.java index 647394287..9ac9bd2d2 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Server.java +++ b/src/main/java/net/sf/jsqlparser/schema/Server.java @@ -71,7 +71,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(serverName); + return MultiPartName.unquote(serverName); } @Override diff --git a/src/main/java/net/sf/jsqlparser/schema/Synonym.java b/src/main/java/net/sf/jsqlparser/schema/Synonym.java index 6c67a96bd..b052588c8 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Synonym.java +++ b/src/main/java/net/sf/jsqlparser/schema/Synonym.java @@ -108,7 +108,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(partItems.get(NAME_IDX)); + return MultiPartName.unquote(partItems.get(NAME_IDX)); } @Override diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 616616002..2d8ab6744 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -108,7 +108,7 @@ public String getDatabaseName() { } public String getUnquotedDatabaseName() { - return unquote(getDatabaseName()); + return MultiPartName.unquote(getDatabaseName()); } public void setDatabase(Database database) { @@ -133,7 +133,7 @@ public String getSchemaName() { } public String getUnquotedSchemaName() { - return unquote(getSchemaName()); + return MultiPartName.unquote(getSchemaName()); } public Table setSchemaName(String schemaName) { @@ -236,7 +236,7 @@ public String getFullyQualifiedName() { @Override public String getUnquotedName() { - return unquote(getName()); + return MultiPartName.unquote(getName()); } @Override diff --git a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java index 4f8112d17..d2eb11fd6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/SelectItem.java @@ -67,6 +67,14 @@ public Alias getAlias() { return alias; } + public String getAliasName() { + return alias != null ? alias.getName() : null; + } + + public String getUnquotedAliasName() { + return alias != null ? alias.getUnquotedName() : null; + } + public void setAlias(Alias alias) { this.alias = alias; } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java index 37b3663c2..2b2c4cba5 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -54,6 +54,14 @@ public Alias getAlias() { return alias; } + public String getAliasName() { + return alias != null ? alias.getName() : null; + } + + public String getUnquotedAliasName() { + return alias != null ? alias.getUnquotedName() : null; + } + public void setAlias(Alias alias) { this.alias = alias; } @@ -98,8 +106,6 @@ public String toString() { builder.append(withItemList.get(i)).append(i < size - 1 ? "," : ""); } builder.append(")"); - } else { - builder.append(""); } builder.append(" AS "); builder.append(statement); From 93ca6610425fc8ac99095ba74161c69095682f06 Mon Sep 17 00:00:00 2001 From: Stefan Steinhauser Date: Tue, 20 Aug 2024 10:16:27 +0200 Subject: [PATCH 29/88] Exasol support (#2046) * feat: Support REGEXP_LIKE as LikeExpression Implement support of REGEXP_LIKE as LikeExpression as described here: https://docs.exasol.com/db/latest/sql_references/predicates/not_regexp_like.htm * feat: Support sub select as part of function parameters Allow unparenthesesed sub selects being part of multiple function parameters * fix: Readd mistakenly removed K_TEXT_LITERAL * revert: Revert code formatting changes * fix: Fix choice conflicts * refactor: Rename test methods * refactor: Apply on changed files * feat: Introduce allowUnparenthesizedSubSelects feature * refactor: Apply formatApply * test: add test for the standard grammar, expected to fail * test: make the performance tests more robust regarding the time-outs * style: reformat code Signed-off-by: Andreas Reichel * fix: Revert default keyword changes * fix: Revert default keyword changes --------- Signed-off-by: Andreas Reichel Co-authored-by: Stefan Steinhauser Co-authored-by: Andreas Reichel --- build.gradle | 12 ++-- .../operators/relational/LikeExpression.java | 2 +- .../jsqlparser/parser/AbstractJSqlParser.java | 8 +++ .../sf/jsqlparser/parser/feature/Feature.java | 5 ++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 16 ++++-- src/site/sphinx/keywords.rst | 2 +- .../jsqlparser/expression/FunctionTest.java | 7 +++ .../select/NestedBracketsPerformanceTest.java | 56 ++++++++++++------- .../statement/select/SelectTest.java | 27 ++++++++- .../validator/ExpressionValidatorTest.java | 6 ++ 10 files changed, 104 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index 2e68982b1..fdfa2993f 100644 --- a/build.gradle +++ b/build.gradle @@ -194,6 +194,10 @@ test { // set heap size for the test JVM(s) minHeapSize = "128m" maxHeapSize = "1G" + + jacoco { + excludes = ['net/sf/jsqlparser/parser/CCJSqlParserTokenManager'] + } } coveralls { @@ -201,14 +205,6 @@ coveralls { } jacocoTestReport { - // Jacoco can't handle the TokenManager class - afterEvaluate { - classDirectories.setFrom(files(classDirectories.files.collect { - fileTree(dir: it, exclude: [ - "**CCJSqlParserTokenManager**" - ]) - })) - } dependsOn test // tests are required to run before generating the report reports { xml.required = false diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java index cf55678ce..08ac4888c 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java @@ -117,7 +117,7 @@ public LikeExpression withRightExpression(Expression arg0) { } public enum KeyWord { - LIKE, ILIKE, RLIKE, REGEXP, SIMILAR_TO; + LIKE, ILIKE, RLIKE, REGEXP_LIKE, REGEXP, SIMILAR_TO; public static KeyWord from(String keyword) { return Enum.valueOf(KeyWord.class, keyword.toUpperCase().replaceAll("\\s+", "_")); diff --git a/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java b/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java index 3c414d852..a39ac7e32 100644 --- a/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java +++ b/src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java @@ -65,6 +65,14 @@ public P withBackslashEscapeCharacter(boolean allowBackslashEscapeCharacter) { return withFeature(Feature.allowBackslashEscapeCharacter, allowBackslashEscapeCharacter); } + public P withUnparenthesizedSubSelects() { + return withFeature(Feature.allowUnparenthesizedSubSelects, true); + } + + public P withUnparenthesizedSubSelects(boolean allowUnparenthesizedSubSelects) { + return withFeature(Feature.allowUnparenthesizedSubSelects, allowUnparenthesizedSubSelects); + } + public P withFeature(Feature f, boolean enabled) { getConfiguration().setValue(f, enabled); return me(); diff --git a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java index 244a3887e..75b5c78a5 100644 --- a/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java +++ b/src/main/java/net/sf/jsqlparser/parser/feature/Feature.java @@ -787,6 +787,11 @@ public enum Feature { * allows Backslash '\' as Escape Character */ allowBackslashEscapeCharacter(false), + + /** + * allows sub selects without parentheses, e.g. `select * from dual where 1 = select 1` + */ + allowUnparenthesizedSubSelects(false), ; private final Object value; diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index a49e3c61f..dbd2a1d5c 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -396,6 +396,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -1993,7 +1994,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -2382,7 +2383,7 @@ List LateralViews(): } { lateralView = LateralView() { lateralViews.add(lateralView); } - ( lateralView = LateralView() { lateralViews.add(lateralView); } )* + ( LOOKAHEAD(2) lateralView = LateralView() { lateralViews.add(lateralView); } )* { return lateralViews; @@ -2487,11 +2488,11 @@ PlainSelect PlainSelect() #PlainSelect: [ LOOKAHEAD(2) intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ] [ LOOKAHEAD(2) fromItem=FromItem() - [ lateralViews=LateralViews() ] + [ LOOKAHEAD(2) lateralViews=LateralViews() ] [ LOOKAHEAD(2) joins=JoinsList() ] ] [ LOOKAHEAD(3) { plainSelect.setUsingOnly(true); } fromItem=FromItem() - [ lateralViews=LateralViews() ] + [ LOOKAHEAD(2) lateralViews=LateralViews() ] [ LOOKAHEAD(2) joins=JoinsList() ] ] @@ -4004,6 +4005,7 @@ Expression LikeExpression(Expression leftExpression) #LikeExpression: token = | token = | token = + | token = | token = | token = ) { result.setLikeKeyWord( LikeExpression.KeyWord.from(token.image)); } @@ -4613,7 +4615,9 @@ Expression PrimaryExpression() #PrimaryExpression: | "{ts" token= "}" { retval = new TimestampValue(token.image); } - | LOOKAHEAD( ParenthesedSelect() , {!interrupted} ) retval=ParenthesedSelect() + | LOOKAHEAD( Select() , { getAsBoolean(Feature.allowUnparenthesizedSubSelects) && !interrupted } ) retval=Select() + + | LOOKAHEAD( ParenthesedSelect() , { !getAsBoolean(Feature.allowUnparenthesizedSubSelects) && !interrupted } ) retval=ParenthesedSelect() | ( @@ -5655,7 +5659,7 @@ Function InternalFunction(boolean escaped): | LOOKAHEAD(3) expressionList=ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] | - expr = Select() { expressionList = new ExpressionList(expr); } + LOOKAHEAD({ !getAsBoolean(Feature.allowUnparenthesizedSubSelects) }) expr = Select() { expressionList = new ExpressionList(expr); } ) ] diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index 78c17aa0b..551a9b320 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -39,7 +39,7 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | DEFAULT | Yes | | +----------------------+-------------+-----------+ -| DISTINCT | Yes | Yes | +| DISTINCT | Yes | Yes | +----------------------+-------------+-----------+ | DOUBLE | Yes | | +----------------------+-------------+-----------+ diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java index e2e36dc7d..72f703c38 100644 --- a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java @@ -76,6 +76,13 @@ void testSubSelectArrayWithoutKeywordParameter() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + @Test + void testSubSelectParameterWithoutParentheses() throws JSQLParserException { + String sqlStr = "SELECT COALESCE(SELECT mycolumn FROM mytable, 0)"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true, + parser -> parser.withUnparenthesizedSubSelects(true)); + } + @Test void testSimpleFunctionIssue2059() throws JSQLParserException { String sqlStr = "select count(*) from zzz"; diff --git a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java index 51b041470..240e10bf9 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/NestedBracketsPerformanceTest.java @@ -18,8 +18,10 @@ import java.util.logging.Logger; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; +import org.junit.jupiter.api.Assertions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.function.Executable; /** * @@ -35,14 +37,15 @@ public class NestedBracketsPerformanceTest { public void testIssue766() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "SELECT concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat(concat('1','2'),'3'),'4'),'5'),'6'),'7'),'8'),'9'),'10'),'11'),'12'),'13'),'14'),'15'),'16'),'17'),'18'),'19'),'20'),'21'),col1 FROM tbl t1", - true); + true, parser -> parser.withTimeOut(60000)); } @Test @Timeout(2000) public void testIssue766_2() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "SELECT concat(concat(concat('1', '2'), '3'), '4'), col1 FROM tbl t1"); + "SELECT concat(concat(concat('1', '2'), '3'), '4'), col1 FROM tbl t1", true, + parser -> parser.withTimeOut(60000)); } @Test @@ -50,7 +53,7 @@ public void testIssue766_2() throws JSQLParserException { public void testIssue235() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( "SELECT CASE WHEN ( CASE WHEN ( CASE WHEN ( CASE WHEN ( 1 ) THEN 0 END ) THEN 0 END ) THEN 0 END ) THEN 0 END FROM a", - true); + true, parser -> parser.withTimeOut(60000)); } @Test @@ -71,7 +74,7 @@ public void testNestedCaseWhenWithoutBracketsIssue1162() throws JSQLParserExcept + "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" + "ELSE CASE\n" + "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" + "ELSE CASE WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT' ELSE '0' END END END END END END END END END END END END END END COLUMNALIAS\n" - + "FROM TABLE1", true); + + "FROM TABLE1", true, parser -> parser.withTimeOut(60000)); } @Test @@ -92,26 +95,31 @@ public void testNestedCaseWhenWithBracketsIssue1162() throws JSQLParserException + "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" + "ELSE (CASE\n" + "WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT'\n" + "ELSE (CASE WHEN WDGFLD.PORTTYPE = 1 THEN 'INPUT PORT' ELSE '0' END) END) END) END) END) END) END) END) END) END) END) END) END) END COLUMNALIAS\n" - + "FROM TABLE1", true); + + "FROM TABLE1", true, parser -> parser.withTimeOut(60000)); } @Test - @Timeout(2000) - @Disabled + @Timeout(10000) public void testIssue496() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed( - "select isNull(charLen(TEST_ID,0)+ isNull(charLen(TEST_DVC,0)+ isNull(charLen(TEST_NO,0)+ isNull(charLen(ATEST_ID,0)+ isNull(charLen(TESTNO,0)+ isNull(charLen(TEST_CTNT,0)+ isNull(charLen(TEST_MESG_CTNT,0)+ isNull(charLen(TEST_DTM,0)+ isNull(charLen(TEST_DTT,0)+ isNull(charLen(TEST_ADTT,0)+ isNull(charLen(TEST_TCD,0)+ isNull(charLen(TEST_PD,0)+ isNull(charLen(TEST_VAL,0)+ isNull(charLen(TEST_YN,0)+ isNull(charLen(TEST_DTACM,0)+ isNull(charLen(TEST_MST,0) from test_info_m", - true); + Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + assertSqlCanBeParsedAndDeparsed( + "select isNull(charLen(TEST_ID,0)+ isNull(charLen(TEST_DVC,0)+ isNull(charLen(TEST_NO,0)+ isNull(charLen(ATEST_ID,0)+ isNull(charLen(TESTNO,0)+ isNull(charLen(TEST_CTNT,0)+ isNull(charLen(TEST_MESG_CTNT,0)+ isNull(charLen(TEST_DTM,0)+ isNull(charLen(TEST_DTT,0)+ isNull(charLen(TEST_ADTT,0)+ isNull(charLen(TEST_TCD,0)+ isNull(charLen(TEST_PD,0)+ isNull(charLen(TEST_VAL,0)+ isNull(charLen(TEST_YN,0)+ isNull(charLen(TEST_DTACM,0)+ isNull(charLen(TEST_MST,0) from test_info_m", + true, parser -> parser.withTimeOut(6000)); + } + }); + } @Test - // @Todo Investigate performance deterioration since JSQLParser 5.0pre development + @Timeout(2000) public void testIssue856() throws JSQLParserException { String sql = "SELECT " + buildRecursiveBracketExpression( "if(month(today()) = 3, sum(\"Table5\".\"Month 002\"), $1)", "0", 3) + " FROM mytbl"; - assertSqlCanBeParsedAndDeparsed(sql); + assertSqlCanBeParsedAndDeparsed(sql, true, parser -> parser.withTimeOut(60000)); } @Test @@ -127,6 +135,7 @@ public void testRecursiveBracketExpressionIssue1019() { // maxDepth = 10 collides with the Parser Timeout = 6 seconds // @todo: implement methods to set the Parser Timeout explicitly and on demand @Test + @Timeout(20000) public void testRecursiveBracketExpressionIssue1019_2() throws JSQLParserException { // Temporally set the maxDepth to be 6, was 8 before this doIncreaseOfParseTimeTesting("IF(1=1, $1, 2)", "1", 6); @@ -135,18 +144,22 @@ public void testRecursiveBracketExpressionIssue1019_2() throws JSQLParserExcepti @Test @Timeout(2000) public void testIssue1013() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT ((((((((((((((((tblA)))))))))))))))) FROM mytable"); + assertSqlCanBeParsedAndDeparsed("SELECT ((((((((((((((((tblA)))))))))))))))) FROM mytable", + true, parser -> parser.withTimeOut(60000)); } @Test @Timeout(2000) public void testIssue1013_2() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT * FROM ((((((((((((((((tblA))))))))))))))))"); + assertSqlCanBeParsedAndDeparsed("SELECT * FROM ((((((((((((((((tblA))))))))))))))))", true, + parser -> parser.withTimeOut(60000)); } @Test + @Timeout(2000) public void testIssue1013_3() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("SELECT * FROM (((tblA)))"); + assertSqlCanBeParsedAndDeparsed("SELECT * FROM (((tblA)))", true, + parser -> parser.withTimeOut(60000)); } @Test @@ -158,7 +171,7 @@ public void testIssue1013_4() throws JSQLParserException { } String sql = "SELECT * FROM " + s; LOG.info("testing " + sql); - assertSqlCanBeParsedAndDeparsed(sql); + assertSqlCanBeParsedAndDeparsed(sql, true, parser -> parser.withTimeOut(60000)); } /** @@ -166,7 +179,8 @@ public void testIssue1013_4() throws JSQLParserException { * * @throws JSQLParserException */ - // @Test(timeout = 6000) + @Test + @Timeout(2000) public void testIncreaseOfParseTime() throws JSQLParserException { // Temporally set the maxDepth to be 6, was 50 before this doIncreaseOfParseTimeTesting("concat($1,'B')", "'A'", 6); @@ -180,7 +194,7 @@ private void doIncreaseOfParseTimeTesting(String template, String finalExpressio String sql = "SELECT " + buildRecursiveBracketExpression(template, finalExpression, i) + " FROM mytbl"; long startTime = System.currentTimeMillis(); - assertSqlCanBeParsedAndDeparsed(sql, true); + assertSqlCanBeParsedAndDeparsed(sql, true, parser -> parser.withTimeOut(60000)); long durationTime = System.currentTimeMillis() - startTime; if (i > 0) { @@ -199,6 +213,7 @@ private void doIncreaseOfParseTimeTesting(String template, String finalExpressio } @Test + @Timeout(2000) public void testRecursiveBracketExpression() { assertEquals("concat('A','B')", buildRecursiveBracketExpression("concat($1,'B')", "'A'", 0)); @@ -227,10 +242,11 @@ public void testIssue1103() throws JSQLParserException { + "ROUND(ROUND(ROUND(ROUND(ROUND(ROUND(ROUND(ROUND(0\n" + ",0),0),0),0),0),0),0),0)\n" + ",0),0),0),0),0),0),0),0)\n" + ",0),0),0),0),0),0),0),0)\n" + ",0),0),0),0),0),0),0),0)", - true); + true, parser -> parser.withTimeOut(60000)); } @Test + @Timeout(2000) public void testDeepFunctionParameters() throws JSQLParserException { String sqlStr = "SELECT a.*\n" + " , To_Char( a.eingangsdat, 'MM.YY' ) AS eingmonat\n" @@ -354,7 +370,7 @@ public void testDeepFunctionParameters() throws JSQLParserException { + " FROM beschfehler\n" + " WHERE beschfehler_id = a.beschwkat_id ), 0 ) > 0\n"; - assertSqlCanBeParsedAndDeparsed(sqlStr, true); + assertSqlCanBeParsedAndDeparsed(sqlStr, true, parser -> parser.withTimeOut(60000)); } @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 6ef1fc163..1f0c3b931 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -2896,6 +2896,12 @@ public void testRlike() throws JSQLParserException { "SELECT * FROM mytable WHERE first_name RLIKE '^Ste(v|ph)en$'"); } + @Test + public void testRegexpLike() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT * FROM mytable WHERE first_name REGEXP_LIKE '^Ste(v|ph)en$'"); + } + @Test public void testBooleanFunction1() throws JSQLParserException { String stmt = "SELECT * FROM mytable WHERE test_func(col1)"; @@ -5953,6 +5959,26 @@ void testGroupByWithHaving() throws JSQLParserException { Assertions.assertInstanceOf(Select.class, stmt); } + @ParameterizedTest + @ValueSource(strings = { + "SELECT SELECT 1", + "SELECT 1 WHERE 1 = SELECT 1", + "SELECT 1 WHERE 1 IN SELECT 1" + }) + public void testUnparenthesizedSubSelect(String sqlStr) throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true, + parser -> parser.withUnparenthesizedSubSelects(true)); + + Assertions.assertThrowsExactly(JSQLParserException.class, new Executable() { + @Override + public void execute() throws Throwable { + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true, + parser -> parser.withUnparenthesizedSubSelects(false)); + } + + }); + } + @Test void testInsertWithinCte() throws JSQLParserException { String sqlStr = "WITH inserted AS ( " + @@ -6079,5 +6105,4 @@ void testSelectAndInsertWithin2Ctes() throws JSQLParserException { insert.toString()); assertEquals(" inserted", withItems.get(1).getAlias().toString()); } - } diff --git a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java index 56453ae29..edba27f66 100644 --- a/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java +++ b/src/test/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidatorTest.java @@ -189,6 +189,12 @@ public void testRlike() throws JSQLParserException { EXPRESSIONS); } + @Test + public void testRegexpLike() throws JSQLParserException { + validateNoErrors("SELECT * FROM mytable WHERE first_name REGEXP_LIKE '^Ste(v|ph)en$'", 1, + EXPRESSIONS); + } + @Test public void testSimilarTo() throws JSQLParserException { validateNoErrors( From a8791279827d723b4a5c2ab655f51098814317eb Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Tue, 20 Aug 2024 19:28:44 +0700 Subject: [PATCH 30/88] feature: allow parsing BigQuery single pair quotes, e. g. "catalog.schema.tablename" - fixes https://github.com/starlake-ai/jsqltranspiler/issues/31 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .github/workflows/maven_deploy.yml | 6 ++- .github/workflows/sphinx.yml | 2 +- .gitignore | 1 + build.gradle | 4 -- gradle.properties | 4 +- .../sf/jsqlparser/schema/MultiPartName.java | 4 ++ .../java/net/sf/jsqlparser/schema/Table.java | 46 +++++++++++++------ .../net/sf/jsqlparser/schema/TableTest.java | 30 +++++++++++- 8 files changed, 72 insertions(+), 25 deletions(-) diff --git a/.github/workflows/maven_deploy.yml b/.github/workflows/maven_deploy.yml index 740e80cb1..e63de93eb 100644 --- a/.github/workflows/maven_deploy.yml +++ b/.github/workflows/maven_deploy.yml @@ -14,9 +14,11 @@ jobs: name: Java ${{ matrix.java }} building ... steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Java ${{ matrix.java }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: 'temurin' diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index ad8bde188..5fb5f9bd3 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: pip install furo myst_parser sphinx-prompt sphinx_substitution_extensions sphinx_issues sphinx_inline_tabs pygments - name: Checkout project sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: ref: master fetch-depth: 0 diff --git a/.gitignore b/.gitignore index 20db77d7c..a2b625283 100755 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Generated by maven /target /build +/out # Sphinx Theme related stuff, which shall be downloaded separately /src/site/sphinx/_themes diff --git a/build.gradle b/build.gradle index fdfa2993f..c5d77bf30 100644 --- a/build.gradle +++ b/build.gradle @@ -187,10 +187,6 @@ test { environment = [ 'EXPORT_TEST_TO_FILE': 'True' ] useJUnitPlatform() - jacoco { - excludes = ['net/sf/jsqlparser/parser/CCJSqlParserTokenManager'] - } - // set heap size for the test JVM(s) minHeapSize = "128m" maxHeapSize = "1G" diff --git a/gradle.properties b/gradle.properties index 522c7558e..0716ad888 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,13 +2,13 @@ # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx1G -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -org.gradle.caching=true +org.gradle.caching=false # Modularise your project and enable parallel build org.gradle.parallel=true # Enable configure on demand. -org.gradle.configureondemand=true +org.gradle.configureondemand=false # see https://docs.gradle.org/current/userguide/upgrading_version_8.html#xml_parsing_now_requires_recent_parsers systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl diff --git a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java index 3e644a705..5e3ad5bde 100644 --- a/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java +++ b/src/main/java/net/sf/jsqlparser/schema/MultiPartName.java @@ -26,6 +26,10 @@ static String unquote(String quotedIdentifier) { : null; } + static boolean isQuoted(String identifier) { + return LEADING_TRAILING_QUOTES_PATTERN.matcher(identifier).find(); + } + String getFullyQualifiedName(); String getUnquotedName(); diff --git a/src/main/java/net/sf/jsqlparser/schema/Table.java b/src/main/java/net/sf/jsqlparser/schema/Table.java index 2d8ab6744..e41930bae 100644 --- a/src/main/java/net/sf/jsqlparser/schema/Table.java +++ b/src/main/java/net/sf/jsqlparser/schema/Table.java @@ -63,36 +63,44 @@ public Table(String name) { } public Table(String schemaName, String name) { - setName(name); setSchemaName(schemaName); + setName(name); } public Table(Database database, String schemaName, String name) { - setName(name); - setSchemaName(schemaName); setDatabase(database); + setSchemaName(schemaName); + setName(name); } public Table(String catalogName, String schemaName, String tableName) { - setName(tableName); setSchemaName(schemaName); setDatabase(new Database(catalogName)); + setName(tableName); } public Table(List partItems) { - this.partItems = new ArrayList<>(partItems); - Collections.reverse(this.partItems); + if (partItems.size() == 1) { + setName(partItems.get(0)); + } else { + this.partItems = new ArrayList<>(partItems); + Collections.reverse(this.partItems); + } } public Table(List partItems, List partDelimiters) { - if (partDelimiters.size() != partItems.size() - 1) { - throw new IllegalArgumentException( - "the length of the delimiters list must be 1 less than nameParts"); + if (partItems.size() == 1) { + setName(partItems.get(0)); + } else { + if (partDelimiters.size() != partItems.size() - 1) { + throw new IllegalArgumentException( + "the length of the delimiters list must be 1 less than nameParts"); + } + this.partItems = new ArrayList<>(partItems); + this.partDelimiters = new ArrayList<>(partDelimiters); + Collections.reverse(this.partItems); + Collections.reverse(this.partDelimiters); } - this.partItems = new ArrayList<>(partItems); - this.partDelimiters = new ArrayList<>(partDelimiters); - Collections.reverse(this.partItems); - Collections.reverse(this.partDelimiters); } public String getCatalogName() { @@ -159,7 +167,17 @@ public String getName() { public void setName(String name) { - setIndex(NAME_IDX, name); + // BigQuery seems to allow things like: `catalogName.schemaName.tableName` in only one pair + // of quotes + if (MultiPartName.isQuoted(name) && name.contains(".")) { + partItems.clear(); + for (String unquotedIdentifier : MultiPartName.unquote(name).split("\\.")) { + partItems.add("\"" + unquotedIdentifier + "\""); + } + Collections.reverse(partItems); + } else { + setIndex(NAME_IDX, name); + } } public String getDBLinkName() { diff --git a/src/test/java/net/sf/jsqlparser/schema/TableTest.java b/src/test/java/net/sf/jsqlparser/schema/TableTest.java index 5a3817251..0f9ff2071 100644 --- a/src/test/java/net/sf/jsqlparser/schema/TableTest.java +++ b/src/test/java/net/sf/jsqlparser/schema/TableTest.java @@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; /** * @@ -65,9 +66,7 @@ public StringBuilder visit(Table tableName, S parameters) { return null; } }; - deparser.visit((PlainSelect) select, null); - } @Test @@ -86,4 +85,31 @@ public void testConstructorDelimitersInappropriateSize() { .hasMessageContaining( "the length of the delimiters list must be 1 less than nameParts"); } + + @Test + void testBigQueryFullQuotedName() throws JSQLParserException { + String sqlStr = "select * from `d.s.t`"; + PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + Table table = (Table) select.getFromItem(); + + assertEquals("\"d\"", table.getCatalogName()); + assertEquals("\"s\"", table.getSchemaName()); + assertEquals("\"t\"", table.getName()); + + assertEquals("d", table.getUnquotedDatabaseName()); + assertEquals("s", table.getUnquotedSchemaName()); + assertEquals("t", table.getUnquotedName()); + + sqlStr = "select * from `s.t`"; + select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr); + table = (Table) select.getFromItem(); + + assertNull(table.getCatalogName()); + assertEquals("\"s\"", table.getSchemaName()); + assertEquals("\"t\"", table.getName()); + + assertNull(table.getUnquotedDatabaseName()); + assertEquals("s", table.getUnquotedSchemaName()); + assertEquals("t", table.getUnquotedName()); + } } From 340d855db9b36e3041ade2a45a3557a46cc07aa2 Mon Sep 17 00:00:00 2001 From: Tobias Warneke Date: Tue, 20 Aug 2024 23:01:45 +0200 Subject: [PATCH 31/88] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 51a273607..91c8b0a3a 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2/ - sonatype-nexus-snapshots + sonatype-nexus-snapshots https://oss.sonatype.org/content/repositories/snapshots/ From 33ba5eb521c4daef37340b7204616c3f3452036b Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Wed, 21 Aug 2024 12:32:08 +0700 Subject: [PATCH 32/88] fix: `TableNameFinder` for `Alter Table` - fixes #2062 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../sf/jsqlparser/util/TablesNamesFinder.java | 9 +++--- .../util/TablesNamesFinderTest.java | 28 +++++++++++++------ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index ad5e10495..37746e42d 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -383,8 +383,8 @@ protected String extractTableName(Table table) { } @Override - public Void visit(Table tableName, S context) { - String tableWholeName = extractTableName(tableName); + public Void visit(Table table, S context) { + String tableWholeName = extractTableName(table); if (!otherItemNames.contains(tableWholeName)) { tables.add(tableWholeName); } @@ -1149,13 +1149,12 @@ public void visit(CreateView createView) { @Override public Void visit(Alter alter, S context) { - throwUnsupported(alter); - return null; + return alter.getTable().accept(this, context); } @Override public void visit(Alter alter) { - StatementVisitor.super.visit(alter); + alter.getTable().accept(this, null); } @Override diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index f3025e02e..4ad08efb0 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -539,19 +539,19 @@ void testTableRenamingIssue2028() throws JSQLParserException { ";"; //@formatter:on - TablesNamesFinder finder = new TablesNamesFinder() { + TablesNamesFinder finder = new TablesNamesFinder<>() { @Override - public Void visit(Table tableName, S context) { - String schemaName = tableName.getSchemaName(); + public Void visit(Table table, S context) { + String schemaName = table.getSchemaName(); if (schemaName != null && IGNORE_SCHEMAS.contains(schemaName.toLowerCase())) { - return super.visit(tableName, context); + return super.visit(table, context); } - String originTableName = tableName.getName(); - tableName.setName(prefix + originTableName); + String originTableName = table.getName(); + table.setName(prefix + originTableName); if (originTableName.startsWith("`")) { - tableName.setName("`" + prefix + originTableName.replace("`", "") + "`"); + table.setName("`" + prefix + originTableName.replace("`", "") + "`"); } - return super.visit(tableName, context); + return super.visit(table, context); } }; finder.init(false); @@ -561,5 +561,17 @@ public Void visit(Table tableName, S context) { TestUtils.assertStatementCanBeDeparsedAs(statement, expected, true); } + + @Test + void testAlterTableIssue2062() throws JSQLParserException { + String sqlStr = "ALTER TABLE the_cool_db.the_table\n" + + " ADD test VARCHAR (40)\n" + + ";"; + Set tables = TablesNamesFinder.findTablesOrOtherSources(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("the_cool_db.the_table"); + + tables = TablesNamesFinder.findTables(sqlStr); + assertThat(tables).containsExactlyInAnyOrder("the_cool_db.the_table"); + } } From ad132ee298d7bfe39673a322e2f692d6185c3317 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Fri, 23 Aug 2024 21:01:06 +0700 Subject: [PATCH 33/88] feat: add DuckDB `SUMMARIZE table | select` - fixes #2064 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../statement/ExplainStatement.java | 53 +++++++++++++++---- .../util/deparser/StatementDeParser.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 28 +++++----- src/site/sphinx/keywords.rst | 2 +- .../statement/ExplainStatementTest.java | 20 +++++++ .../util/TablesNamesFinderTest.java | 12 +++++ 6 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 src/test/java/net/sf/jsqlparser/statement/ExplainStatementTest.java diff --git a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java index 55e5c679e..fbbef33d4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java +++ b/src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java @@ -11,6 +11,7 @@ import java.io.Serializable; import java.util.LinkedHashMap; +import java.util.List; import java.util.stream.Collectors; import net.sf.jsqlparser.schema.Table; @@ -20,17 +21,40 @@ * An {@code EXPLAIN} statement */ public class ExplainStatement implements Statement { - + private String keyword; private Select select; private LinkedHashMap options; private Table table; + public ExplainStatement(String keyword) { + this.keyword = keyword; + } + public ExplainStatement() { - // empty constructor + this("EXPLAIN"); } - public ExplainStatement(Select select) { + public ExplainStatement(String keyword, Table table) { + this.keyword = keyword; + this.table = table; + this.select = null; + } + + public ExplainStatement(String keyword, Select select, List
usingList; private List joins; private Expression where; + private PreferringClause preferringClause; private Limit limit; private List orderByElements; private boolean hasFrom = true; @@ -123,6 +125,14 @@ public void setWhere(Expression expression) { where = expression; } + public PreferringClause getPreferringClause() { + return preferringClause; + } + + public void setPreferringClause(PreferringClause preferringClause) { + this.preferringClause = preferringClause; + } + public OracleHint getOracleHint() { return oracleHint; } @@ -239,6 +249,10 @@ public String toString() { b.append(" WHERE ").append(where); } + if (preferringClause != null) { + b.append(" ").append(preferringClause); + } + if (orderByElements != null) { b.append(PlainSelect.orderByToString(orderByElements)); } @@ -289,6 +303,11 @@ public Delete withWhere(Expression where) { return this; } + public Delete withPreferringClause(PreferringClause preferringClause) { + this.setPreferringClause(preferringClause); + return this; + } + public Delete withHasFrom(boolean hasFrom) { this.setHasFrom(hasFrom); return this; diff --git a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java index 414a60945..1e84123c4 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java @@ -13,6 +13,7 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.OracleHierarchicalExpression; import net.sf.jsqlparser.expression.OracleHint; +import net.sf.jsqlparser.expression.PreferringClause; import net.sf.jsqlparser.expression.WindowDefinition; import net.sf.jsqlparser.schema.Table; @@ -46,6 +47,7 @@ public class PlainSelect extends Select { private First first; private Top top; private OracleHierarchicalExpression oracleHierarchical = null; + private PreferringClause preferringClause = null; private OracleHint oracleHint = null; private boolean mySqlSqlCalcFoundRows = false; private MySqlSqlCacheFlags mySqlCacheFlag = null; @@ -424,6 +426,14 @@ public void setOracleHierarchical(OracleHierarchicalExpression oracleHierarchica this.oracleHierarchical = oracleHierarchical; } + public PreferringClause getPreferringClause() { + return preferringClause; + } + + public void setPreferringClause(PreferringClause preferringClause) { + this.preferringClause = preferringClause; + } + public OracleHint getOracleHint() { return oracleHint; } @@ -555,6 +565,9 @@ public StringBuilder appendSelectBodyTo(StringBuilder builder) { if (oracleHierarchical != null) { builder.append(oracleHierarchical); } + if (preferringClause != null) { + builder.append(" ").append(preferringClause); + } if (groupBy != null) { builder.append(" ").append(groupBy); } @@ -676,6 +689,11 @@ public PlainSelect withOracleHierarchical(OracleHierarchicalExpression oracleHie return this; } + public PlainSelect withPreferringClause(PreferringClause preferringClause) { + this.setPreferringClause(preferringClause); + return this; + } + public PlainSelect withOracleHint(OracleHint oracleHint) { this.setOracleHint(oracleHint); return this; diff --git a/src/main/java/net/sf/jsqlparser/statement/update/Update.java b/src/main/java/net/sf/jsqlparser/statement/update/Update.java index 2d948afda..b09854fe6 100644 --- a/src/main/java/net/sf/jsqlparser/statement/update/Update.java +++ b/src/main/java/net/sf/jsqlparser/statement/update/Update.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.OracleHint; +import net.sf.jsqlparser.expression.PreferringClause; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.OutputClause; @@ -39,6 +40,7 @@ public class Update implements Statement { private List> withItemsList; private Table table; private Expression where; + private PreferringClause preferringClause; private List updateSets; private FromItem fromItem; private List joins; @@ -125,6 +127,14 @@ public void setWhere(Expression expression) { where = expression; } + public PreferringClause getPreferringClause() { + return preferringClause; + } + + public void setPreferringClause(PreferringClause preferringClause) { + this.preferringClause = preferringClause; + } + public OracleHint getOracleHint() { return oracleHint; } @@ -336,6 +346,9 @@ public String toString() { b.append(" WHERE "); b.append(where); } + if (preferringClause != null) { + b.append(" ").append(preferringClause); + } if (orderByElements != null) { b.append(PlainSelect.orderByToString(orderByElements)); } @@ -400,6 +413,11 @@ public Update withWhere(Expression where) { return this; } + public Update withPreferringClause(PreferringClause preferringClause) { + this.setPreferringClause(preferringClause); + return this; + } + public Update withColumns(List columns) { this.setColumns(columns); return this; diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 37746e42d..60335a9d9 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -28,7 +28,9 @@ import net.sf.jsqlparser.expression.ExtractExpression; import net.sf.jsqlparser.expression.Function; import net.sf.jsqlparser.expression.HexValue; +import net.sf.jsqlparser.expression.HighExpression; import net.sf.jsqlparser.expression.IntervalExpression; +import net.sf.jsqlparser.expression.Inverse; import net.sf.jsqlparser.expression.JdbcNamedParameter; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.JsonAggregateFunction; @@ -38,6 +40,7 @@ import net.sf.jsqlparser.expression.KeepExpression; import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.LowExpression; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; import net.sf.jsqlparser.expression.NotExpression; @@ -102,6 +105,8 @@ import net.sf.jsqlparser.expression.operators.relational.MinorThan; import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; +import net.sf.jsqlparser.expression.operators.relational.Plus; +import net.sf.jsqlparser.expression.operators.relational.PriorTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression; import net.sf.jsqlparser.expression.operators.relational.TSQLLeftJoin; @@ -1589,6 +1594,36 @@ public Void visit(LambdaExpression lambdaExpression, S context) { return null; } + @Override + public Void visit(HighExpression highExpression, S context) { + highExpression.getExpression().accept(this, context); + return null; + } + + @Override + public Void visit(LowExpression lowExpression, S context) { + lowExpression.getExpression().accept(this, context); + return null; + } + + @Override + public Void visit(Plus plus, S context) { + visitBinaryExpression(plus); + return null; + } + + @Override + public Void visit(PriorTo priorTo, S context) { + visitBinaryExpression(priorTo); + return null; + } + + @Override + public Void visit(Inverse inverse, S context) { + inverse.getExpression().accept(this, context); + return null; + } + @Override public Void visit(VariableAssignment variableAssignment, S context) { variableAssignment.getVariable().accept(this, context); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java index 36fe3c0c8..11e6eb001 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/DeleteDeParser.java @@ -95,6 +95,9 @@ public void deParse(Delete delete) { deparseWhereClause(delete); + if (delete.getPreferringClause() != null) { + buffer.append(" ").append(delete.getPreferringClause()); + } if (delete.getOrderByElements() != null) { new OrderByDeParser(expressionVisitor, buffer).deParse(delete.getOrderByElements()); } 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 bb6b6a146..17f38d86b 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -28,7 +28,9 @@ import net.sf.jsqlparser.expression.ExtractExpression; import net.sf.jsqlparser.expression.Function; import net.sf.jsqlparser.expression.HexValue; +import net.sf.jsqlparser.expression.HighExpression; import net.sf.jsqlparser.expression.IntervalExpression; +import net.sf.jsqlparser.expression.Inverse; import net.sf.jsqlparser.expression.JdbcNamedParameter; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.JsonAggregateFunction; @@ -37,6 +39,7 @@ import net.sf.jsqlparser.expression.KeepExpression; import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.LowExpression; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; import net.sf.jsqlparser.expression.NotExpression; @@ -103,6 +106,8 @@ import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression; +import net.sf.jsqlparser.expression.operators.relational.Plus; +import net.sf.jsqlparser.expression.operators.relational.PriorTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression; import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; @@ -1712,4 +1717,29 @@ public StringBuilder visit(LambdaExpression lambdaExpression, S context) { lambdaExpression.getExpression().accept(this, context); return buffer; } + + @Override + public StringBuilder visit(HighExpression highExpression, S context) { + return buffer.append(highExpression.toString()); + } + + @Override + public StringBuilder visit(LowExpression lowExpression, S context) { + return buffer.append(lowExpression.toString()); + } + + @Override + public StringBuilder visit(Plus plus, S context) { + return buffer.append(plus.toString()); + } + + @Override + public StringBuilder visit(PriorTo priorTo, S context) { + return buffer.append(priorTo.toString()); + } + + @Override + public StringBuilder visit(Inverse inverse, S context) { + return buffer.append(inverse.toString()); + } } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index 81a265d8b..9fb1673e9 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -260,6 +260,10 @@ public StringBuilder visit(PlainSelect plainSelect, S context) { plainSelect.getOracleHierarchical().accept(expressionVisitor, context); } + if (plainSelect.getPreferringClause() != null) { + buffer.append(" ").append(plainSelect.getPreferringClause().toString()); + } + if (plainSelect.getGroupBy() != null) { buffer.append(" "); new GroupByDeParser(expressionVisitor, buffer).deParse(plainSelect.getGroupBy()); diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java index 071ceeca5..a16deec83 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/UpdateDeParser.java @@ -93,6 +93,9 @@ public void deParse(Update update) { deparseWhereClause(update); + if (update.getPreferringClause() != null) { + buffer.append(" ").append(update.getPreferringClause()); + } if (update.getOrderByElements() != null) { new OrderByDeParser(expressionVisitor, buffer).deParse(update.getOrderByElements()); } 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 ae82e703a..6c662d26e 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 @@ -27,7 +27,9 @@ import net.sf.jsqlparser.expression.ExtractExpression; import net.sf.jsqlparser.expression.Function; import net.sf.jsqlparser.expression.HexValue; +import net.sf.jsqlparser.expression.HighExpression; import net.sf.jsqlparser.expression.IntervalExpression; +import net.sf.jsqlparser.expression.Inverse; import net.sf.jsqlparser.expression.JdbcNamedParameter; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.JsonAggregateFunction; @@ -36,6 +38,7 @@ import net.sf.jsqlparser.expression.KeepExpression; import net.sf.jsqlparser.expression.LambdaExpression; import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.LowExpression; import net.sf.jsqlparser.expression.MySQLGroupConcat; import net.sf.jsqlparser.expression.NextValExpression; import net.sf.jsqlparser.expression.NotExpression; @@ -104,6 +107,8 @@ import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression; +import net.sf.jsqlparser.expression.operators.relational.Plus; +import net.sf.jsqlparser.expression.operators.relational.PriorTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression; import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; @@ -1101,6 +1106,36 @@ public Void visit(LambdaExpression lambdaExpression, S context) { return null; } + @Override + public Void visit(HighExpression highExpression, S context) { + highExpression.getExpression().accept(this, context); + return null; + } + + @Override + public Void visit(LowExpression lowExpression, S context) { + lowExpression.getExpression().accept(this, context); + return null; + } + + @Override + public Void visit(Plus plus, S context) { + visitBinaryExpression(plus, " PLUS "); + return null; + } + + @Override + public Void visit(PriorTo priorTo, S context) { + visitBinaryExpression(priorTo, " PLUS "); + return null; + } + + @Override + public Void visit(Inverse inverse, S context) { + inverse.getExpression().accept(this, context); + return null; + } + public void visit(TimeKeyExpression timeKeyExpression) { visit(timeKeyExpression, null); } @@ -1210,4 +1245,24 @@ public void visit(LambdaExpression lambdaExpression) { visit(lambdaExpression, null); } + public void visit(HighExpression highExpression) { + visit(highExpression, null); + } + + public void visit(LowExpression lowExpression) { + visit(lowExpression, null); + } + + public void visit(Plus plus) { + visit(plus, null); + } + + public void visit(PriorTo priorTo) { + visit(priorTo, null); + } + + public void visit(Inverse inverse) { + visit(inverse, null); + } + } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 7dd9706bd..984f4c10c 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -279,6 +279,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -301,6 +302,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -324,6 +326,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -377,6 +380,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| +| | | | @@ -1486,6 +1491,7 @@ Update Update(): List> with = null; List updateSets; Expression where = null; + PreferringClause preferringClause = null; FromItem fromItem = null; List joins = null; Limit limit = null; @@ -1512,6 +1518,7 @@ Update Update(): [ LOOKAHEAD(2) joins=JoinsList() ] ] [ where=WhereClause() { update.setWhere(where); } ] + [ preferringClause=PreferringClause() { update.setPreferringClause(preferringClause); } ] [ orderByElements = OrderByElements() { update.setOrderByElements(orderByElements); } ] [ limit = PlainLimit() { update.setLimit(limit); } ] @@ -1816,6 +1823,7 @@ Delete Delete(): List
usingList = new ArrayList
(); List joins = null; Expression where = null; + PreferringClause preferringClause = null; Limit limit = null; List orderByElements; boolean hasFrom = false; @@ -1841,6 +1849,7 @@ Delete Delete(): [ usingTable=TableWithAlias() { usingList.add(usingTable); } ("," usingTable=TableWithAlias() { usingList.add(usingTable); } )*] [where=WhereClause() { delete.setWhere(where); } ] + [preferringClause=PreferringClause() { delete.setPreferringClause(preferringClause);} ] [orderByElements = OrderByElements() { delete.setOrderByElements(orderByElements); } ] [limit=PlainLimit() {delete.setLimit(limit); } ] @@ -2439,6 +2448,9 @@ PlainSelect PlainSelect() #PlainSelect: Skip skip = null; First first = null; OracleHierarchicalExpression oracleHierarchicalQueryClause = null; + PreferringClause preferringClause = null; + ExpressionList expressionList = null; + boolean partitionByBrackets = false; List
intoTables = null; Table updateTable = null; Wait wait = null; @@ -2514,6 +2526,17 @@ PlainSelect PlainSelect() #PlainSelect: [ LOOKAHEAD(2) ksqlWindow=KSQLWindowClause() { plainSelect.setKsqlWindow(ksqlWindow); } ] [ LOOKAHEAD(2) where=WhereClause() { plainSelect.setWhere(where); }] [ LOOKAHEAD(2) oracleHierarchicalQueryClause=OracleHierarchicalQueryClause() { plainSelect.setOracleHierarchical(oracleHierarchicalQueryClause); } ] + [ LOOKAHEAD(2) preferringClause=PreferringClause() { plainSelect.setPreferringClause(preferringClause); } + [LOOKAHEAD(2) + ( + (LOOKAHEAD(ComplexExpressionList()) expressionList=ComplexExpressionList() + | "(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")" ) + ) + { + preferringClause.setPartitionExpressionList(expressionList, partitionByBrackets); + } + ] + ] // Oracle supports "HAVING" before "GROUP BY", we will simply parse that but won't pay special attention to the order [ LOOKAHEAD(2) having=Having() { plainSelect.setHaving(having); }] [ LOOKAHEAD(2) groupBy=GroupByColumnReferences() { plainSelect.setGroupByElement(groupBy); }] @@ -3301,6 +3324,145 @@ OracleHierarchicalExpression OracleHierarchicalQueryClause(): } } +PreferringClause PreferringClause(): +{ + Expression result = null; +} +{ + + result=PreferenceTerm() + + { + PreferringClause preferring = new PreferringClause(result); + return preferring; + } +} + +Expression PreferenceTerm(): +{ + Expression retval = null; +} +{ + // recursively build preferenceterm inside Plus + // like Expression -> XorExpression -> OrExpression -> ... + + retval=Plus() + + { + return retval; + } +} + +Expression Plus(): +{ + Expression left, right, result; +} +{ + left=PriorTo() { result = left; } + ( + LOOKAHEAD(2) + + right=PriorTo() + { + result = new Plus(left, right); + left = result; + } + )* + { + return result; + } +} + +Expression PriorTo(): +{ + Expression left, right, result; +} +{ + ( + LOOKAHEAD(PreferenceTermTerminal(), {!interrupted}) left=PreferenceTermTerminal() + | "(" left=PreferenceTerm() ")" { left = new ParenthesedExpressionList(left); } + ) + { result = left; } + + ( + LOOKAHEAD(2) + + ( + LOOKAHEAD(PreferenceTermTerminal(), {!interrupted}) right=PreferenceTermTerminal() + | "(" right=PreferenceTerm() ")" { left = new ParenthesedExpressionList(right); } + ) + { + result = new PriorTo(left, right); + left = result; + } + )* + { + return result; + } +} + +Expression PreferenceTermTerminal(): +{ + Expression retval; +} +{ + ( + retval=HighExpression() + | retval=LowExpression() + | retval=Inverse() + | retval=Condition() + ) + + { + return retval; + } +} + +Expression HighExpression() #HighExpression: +{ + Expression result; +} +{ + + result=Expression() + + { + HighExpression high = new HighExpression(result); + linkAST(high,jjtThis); + return high; + } +} + +Expression LowExpression() #LowExpression: +{ + Expression result; +} +{ + + result=Expression() + + { + LowExpression low = new LowExpression(result); + linkAST(low,jjtThis); + return low; + } +} + +Expression Inverse() #Inverse: +{ + Expression result; +} +{ + + "(" result=PreferenceTerm() ")" + + { + Inverse inverse = new Inverse(result); + linkAST(inverse,jjtThis); + return inverse; + } +} + GroupByElement GroupByColumnReferences(): { Expression columnReference; diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index a8500b393..133ce39cd 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -75,6 +75,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | HAVING | Yes | Yes | +----------------------+-------------+-----------+ +| HIGH | Yes | Yes | ++----------------------+-------------+-----------+ | IF | Yes | Yes | +----------------------+-------------+-----------+ | IIF | Yes | | @@ -95,6 +97,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | INTO | Yes | Yes | +----------------------+-------------+-----------+ +| INVERSE | Yes | Yes | ++----------------------+-------------+-----------+ | IS | Yes | Yes | +----------------------+-------------+-----------+ | JOIN | Yes | Yes | @@ -107,6 +111,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | LIMIT | Yes | Yes | +----------------------+-------------+-----------+ +| LOW | Yes | Yes | ++----------------------+-------------+-----------+ | MINUS | Yes | Yes | +----------------------+-------------+-----------+ | NATURAL | Yes | Yes | @@ -137,6 +143,10 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | PIVOT | Yes | Yes | +----------------------+-------------+-----------+ +| PLUS | Yes | Yes | ++----------------------+-------------+-----------+ +| PREFERRING | Yes | Yes | ++----------------------+-------------+-----------+ | PROCEDURE | Yes | | +----------------------+-------------+-----------+ | PUBLIC | Yes | | diff --git a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java index a02137a19..aaa7e57cc 100644 --- a/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/delete/DeleteTest.java @@ -31,6 +31,8 @@ import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.statement.update.Update; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class DeleteTest { @@ -371,4 +373,18 @@ void testSelectAndInsertWithin2Ctes() throws JSQLParserException { assertEquals(" inserted", withItems.get(1).getAlias().toString()); } + @ParameterizedTest + @ValueSource(strings = { + "DELETE FROM mytable PREFERRING HIGH mycolumn", + "DELETE FROM mytable PREFERRING LOW mycolumn", + "DELETE FROM mytable PREFERRING 1 = 1", + "DELETE FROM mytable PREFERRING (HIGH mycolumn)", + "DELETE FROM mytable PREFERRING INVERSE (HIGH mycolumn)", + "DELETE FROM mytable PREFERRING HIGH mycolumn1 PRIOR TO LOW mycolumn2", + "DELETE FROM mytable PREFERRING HIGH mycolumn1 PLUS LOW mycolumn2" + }) + public void testPreferringClause(String sqlStr) throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed(sqlStr); + } + } 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 ca8039843..fd407ee47 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -5983,6 +5983,21 @@ public void execute() throws Throwable { }); } + @ParameterizedTest + @ValueSource(strings = { + "SELECT * FROM mytable PREFERRING HIGH mycolumn", + "SELECT * FROM mytable PREFERRING LOW mycolumn", + "SELECT * FROM mytable PREFERRING 1 = 1", + "SELECT * FROM mytable PREFERRING (HIGH mycolumn)", + "SELECT * FROM mytable PREFERRING INVERSE (HIGH mycolumn)", + "SELECT * FROM mytable PREFERRING HIGH mycolumn1 PRIOR TO LOW mycolumn2", + "SELECT * FROM mytable PREFERRING HIGH mycolumn1 PLUS LOW mycolumn2", + "SELECT * FROM mytable PREFERRING HIGH mycolumn PARTITION BY mycolumn" + }) + public void testPreferringClause(String sqlStr) throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr); + } + @Test void testInsertWithinCte() throws JSQLParserException { String sqlStr = "WITH inserted AS ( " + diff --git a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java index 90d04c358..75ff452b0 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -25,6 +25,8 @@ import net.sf.jsqlparser.statement.select.WithItem; import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.io.StringReader; import java.util.List; @@ -534,4 +536,18 @@ void testSelectAndInsertWithin2Ctes() throws JSQLParserException { assertEquals(" inserted", withItems.get(1).getAlias().toString()); } + @ParameterizedTest + @ValueSource(strings = { + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING HIGH mycolumn", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING LOW mycolumn", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING 1 = 1", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING (HIGH mycolumn)", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING INVERSE (HIGH mycolumn)", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING HIGH mycolumn1 PRIOR TO LOW mycolumn2", + "UPDATE mytable SET mycolumn1 = mycolumn2 PREFERRING HIGH mycolumn1 PLUS LOW mycolumn2" + }) + public void testPreferringClause(String sqlStr) throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed(sqlStr); + } + } From 90adf829153e00fe47ea9d24c17403eaec805c2e Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 19 Sep 2024 08:37:23 +0700 Subject: [PATCH 43/88] feat: `CosineSimilarity` Expression - fixes #2005 Signed-off-by: Andreas Reichel --- .../expression/ExpressionVisitor.java | 3 ++ .../expression/ExpressionVisitorAdapter.java | 8 ++++++ .../relational/CosineSimilarity.java | 28 +++++++++++++++++++ .../sf/jsqlparser/util/TablesNamesFinder.java | 8 ++++++ .../util/deparser/ExpressionDeParser.java | 8 ++++++ .../validator/ExpressionValidator.java | 8 ++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 1 + .../relational/ComparisonOperatorTest.java | 8 ++++++ 8 files changed, 72 insertions(+) create mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index a9a4632a6..e02ff0262 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -27,6 +27,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.ContainedBy; import net.sf.jsqlparser.expression.operators.relational.Contains; +import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; @@ -665,4 +666,6 @@ default void visit(PriorTo priorTo) { default void visit(Inverse inverse) { this.visit(inverse, null); } + + T visit(CosineSimilarity cosineSimilarity, S context); } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 714d76dba..5a4b34345 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -27,6 +27,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.ContainedBy; import net.sf.jsqlparser.expression.operators.relational.Contains; +import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; @@ -792,4 +793,11 @@ public T visit(Inverse inverse, S context) { return inverse.getExpression().accept(this, context); } + @Override + public T visit(CosineSimilarity cosineSimilarity, S context) { + cosineSimilarity.getLeftExpression().accept(this, context); + cosineSimilarity.getRightExpression().accept(this, context); + return null; + } + } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java new file mode 100644 index 000000000..00aad962d --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/CosineSimilarity.java @@ -0,0 +1,28 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2022 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.ExpressionVisitor; + +public class CosineSimilarity extends ComparisonOperator { + + public CosineSimilarity() { + super("<=>"); + } + + public CosineSimilarity(String operator) { + super(operator); + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 60335a9d9..1e0f93968 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -84,6 +84,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.ContainedBy; import net.sf.jsqlparser.expression.operators.relational.Contains; +import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; @@ -1624,6 +1625,13 @@ public Void visit(Inverse inverse, S context) { return null; } + @Override + public Void visit(CosineSimilarity cosineSimilarity, S context) { + cosineSimilarity.getLeftExpression().accept(this, context); + cosineSimilarity.getRightExpression().accept(this, context); + return null; + } + @Override public Void visit(VariableAssignment variableAssignment, S context) { variableAssignment.getVariable().accept(this, context); 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 17f38d86b..4d6036cb5 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -84,6 +84,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.ContainedBy; import net.sf.jsqlparser.expression.operators.relational.Contains; +import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; @@ -1742,4 +1743,11 @@ public StringBuilder visit(PriorTo priorTo, S context) { public StringBuilder visit(Inverse inverse, S context) { return buffer.append(inverse.toString()); } + + @Override + public StringBuilder visit(CosineSimilarity cosineSimilarity, S context) { + deparse(cosineSimilarity, + " " + cosineSimilarity.getStringExpression() + " ", context); + return buffer; + } } 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 6c662d26e..5278c3010 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 @@ -85,6 +85,7 @@ import net.sf.jsqlparser.expression.operators.relational.Between; import net.sf.jsqlparser.expression.operators.relational.ContainedBy; import net.sf.jsqlparser.expression.operators.relational.Contains; +import net.sf.jsqlparser.expression.operators.relational.CosineSimilarity; import net.sf.jsqlparser.expression.operators.relational.DoubleAnd; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExcludesExpression; @@ -1265,4 +1266,11 @@ public void visit(Inverse inverse) { visit(inverse, null); } + @Override + public Void visit(CosineSimilarity cosineSimilarity, S context) { + cosineSimilarity.getLeftExpression().accept(this, context); + cosineSimilarity.getRightExpression().accept(this, context); + return null; + } + } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 984f4c10c..2e257c8b0 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -4008,6 +4008,7 @@ Expression RegularCondition() #RegularCondition: | "-#" { result = new JsonOperator("-#"); } | "<->" { result = new GeometryDistance("<->"); } | "<#>" { result = new GeometryDistance("<#>"); } + | "<=>" { result = new CosineSimilarity(); } ) ( LOOKAHEAD(2) rightExpression=ComparisonItem() { oraclePrior = EqualsTo.ORACLE_PRIOR_END; } diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/ComparisonOperatorTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/ComparisonOperatorTest.java index a2687d664..7be79658a 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/ComparisonOperatorTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/ComparisonOperatorTest.java @@ -35,4 +35,12 @@ public void testContainedBy() throws JSQLParserException { TestUtils.assertSqlCanBeParsedAndDeparsed("SELECT * FROM foo WHERE a <& b"); Assertions.assertInstanceOf(ContainedBy.class, CCJSqlParserUtil.parseExpression("a <& b")); } + + @Test + void testCosineSimilarity() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "SELECT (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;"); + Assertions.assertInstanceOf(CosineSimilarity.class, + CCJSqlParserUtil.parseExpression("embedding <=> '[3,1,2]'")); + } } From 3d4883523e255e964aacefd57720a0b5db8fb378 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 19 Sep 2024 09:28:51 +0700 Subject: [PATCH 44/88] feat: `JsonExpression` supports Expressions rather than Char/Long only - fixes #2054 Signed-off-by: Andreas Reichel --- .../jsqlparser/expression/JsonExpression.java | 22 +++++------ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 38 +++++++++++-------- .../expression/JsonExpressionTest.java | 25 ++++++++++++ .../statement/select/PostgresTest.java | 3 +- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java b/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java index 5b0f97b4c..f258e855c 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonExpression.java @@ -18,7 +18,7 @@ import java.util.Map; public class JsonExpression extends ASTNodeAccessImpl implements Expression { - private final List> idents = new ArrayList<>(); + private final List> idents = new ArrayList<>(); private Expression expr; public JsonExpression() { @@ -29,7 +29,7 @@ public JsonExpression(Expression expr) { this.expr = expr; } - public JsonExpression(Expression expr, List> idents) { + public JsonExpression(Expression expr, List> idents) { this.expr = expr; this.idents.addAll(idents); } @@ -47,26 +47,26 @@ public void setExpression(Expression expr) { this.expr = expr; } - public void addIdent(String ident, String operator) { + public void addIdent(Expression ident, String operator) { idents.add(new AbstractMap.SimpleEntry<>(ident, operator)); } - public void addAllIdents(Collection> idents) { + public void addAllIdents(Collection> idents) { this.idents.addAll(idents); } - public List> getIdentList() { + public List> getIdentList() { return idents; } - public Map.Entry getIdent(int index) { + public Map.Entry getIdent(int index) { return idents.get(index); } @Deprecated - public List getIdents() { - ArrayList l = new ArrayList<>(); - for (Map.Entry ident : idents) { + public List getIdents() { + ArrayList l = new ArrayList<>(); + for (Map.Entry ident : idents) { l.add(ident.getKey()); } @@ -76,7 +76,7 @@ public List getIdents() { @Deprecated public List getOperators() { ArrayList l = new ArrayList<>(); - for (Map.Entry ident : idents) { + for (Map.Entry ident : idents) { l.add(ident.getValue()); } return l; @@ -86,7 +86,7 @@ public List getOperators() { public String toString() { StringBuilder b = new StringBuilder(); b.append(expr.toString()); - for (Map.Entry ident : idents) { + for (Map.Entry ident : idents) { b.append(ident.getValue()).append(ident.getKey()); } return b.toString(); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 2e257c8b0..3393d6f76 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -4706,6 +4706,7 @@ Expression ArrayExpression(Expression obj): { Expression PrimaryExpression() #PrimaryExpression: { Expression retval = null; + Expression expression = null; CastExpression castExpr = null; TimezoneExpression timezoneExpr = null; Expression timezoneRightExpr = null; @@ -4718,7 +4719,7 @@ Expression PrimaryExpression() #PrimaryExpression: boolean dateExpressionAllowed = true; ExpressionList list; - final List> jsonIdents = new ArrayList>(); + final List> jsonIdents = new ArrayList>(); } { [ { not=true; } | "!" { not=true; exclamationMarkNot=true; } ] @@ -4846,14 +4847,17 @@ Expression PrimaryExpression() #PrimaryExpression: [ LOOKAHEAD(2) ( LOOKAHEAD(2) ( - "->" ( token= | token=) { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"->")); } + token="->" expression=Expression() | - "->>" (token= | token=) { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"->>")); } + token="->>" expression=Expression() | - "#>" token= { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"#>")); } + token="#>" expression=Expression() | - "#>>" token= { jsonIdents.add(new AbstractMap.SimpleEntry(token.image,"#>>")); } + token="#>>" expression=Expression() ) + { + jsonIdents.add(new AbstractMap.SimpleEntry(expression, token.image )); + } )+ retval = JsonExpression(retval, jsonIdents) ] @@ -5083,8 +5087,9 @@ StructType StructType() #StruckType: } } -JsonExpression JsonExpression(Expression expr, List> idents) : { +JsonExpression JsonExpression(Expression expr, List> idents) : { JsonExpression result = new JsonExpression(expr, idents); + Expression expression; Token token; ColDataType type = null; CastExpression castExpr = null; @@ -5111,15 +5116,18 @@ JsonExpression JsonExpression(Expression expr, List> i } ( - LOOKAHEAD(2) ( - "->" (token= | token=) {result.addIdent(token.image,"->");} - | - "->>" (token= | token=) {result.addIdent(token.image,"->>");} - | - "#>" token= {result.addIdent(token.image,"#>");} - | - "#>>" token= {result.addIdent(token.image,"#>>");} - ) + LOOKAHEAD(2) ( + token="->" expression=Expression() + | + token="->>" expression=Expression() + | + token="#>" expression=Expression() + | + token="#>>" expression=Expression() + ) + { + result.addIdent( expression, token.image ); + } )* )* diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java index 860a69382..60336b62f 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java @@ -11,6 +11,8 @@ import net.sf.jsqlparser.JSQLParserException; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; @@ -108,4 +110,27 @@ void testParenthesedJsonExpressionsIssue1792() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @ParameterizedTest + @ValueSource(strings = { + "SELECT ( JSONB_AGG(variables) " + + " FILTER (WHERE variables IS NOT NULL) " + + " OVER (PARTITION BY deviceid ORDER BY time)->>-1 )::JSONB AS variables\n" + + "FROM devices\n" + + ";", + "SELECT ( JSONB_AGG(variables) " + + " FILTER (WHERE variables IS NOT NULL) " + + " OVER (PARTITION BY deviceid ORDER BY time)->>(0-1) )::JSONB AS variables\n" + + + "FROM devices\n" + + ";", + "SELECT ( JSONB_AGG(variables) " + + " FILTER (WHERE variables IS NOT NULL) " + + " OVER (PARTITION BY deviceid ORDER BY time)->>(jsonb_array_length(JSONB_AGG(variables) FILTER (WHERE variables IS NOT NULL) OVER (PARTITION BY deviceid ORDER BY time))-1) )::JSONB AS variables\n" + + + "FROM devices\n" + + ";"}) + void testIssue2054(String sqlStr) throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } diff --git a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java index 56d36d854..06d1e3d54 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.JsonExpression; +import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.Statements; @@ -58,7 +59,7 @@ public void testJSonExpressionIssue1696() throws JSQLParserException { PlainSelect plainSelect = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); SelectItem selectExpressionItem = plainSelect.getSelectItems().get(0); - Assertions.assertEquals("'key'", + Assertions.assertEquals(new StringValue("key"), selectExpressionItem.getExpression(JsonExpression.class).getIdent(0).getKey()); } From 5cf281f1de4f9d355874d0b5cc6ecb53b9adf8ca Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 19 Sep 2024 10:26:52 +0700 Subject: [PATCH 45/88] feat: `ON OVERFLOW` support for the `ListAgg` function (Oracle, DB2) - fixes #2003 Signed-off-by: Andreas Reichel --- .../expression/AnalyticExpression.java | 16 ++++++++++ .../sf/jsqlparser/expression/Function.java | 15 +++++++++ .../util/deparser/ExpressionDeParser.java | 9 ++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 32 ++++++++++++++----- .../jsqlparser/expression/FunctionTest.java | 18 +++++++++++ 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java index 4cbb4e1d0..f2a531ab6 100644 --- a/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java @@ -40,6 +40,8 @@ public class AnalyticExpression extends ASTNodeAccessImpl implements Expression private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters private Expression filterExpression = null; private List funcOrderBy = null; + private String onOverflowTruncate = null; + private String windowName = null; // refers to an external window definition (paritionBy, // orderBy, windowElement) private WindowDefinition windowDef = new WindowDefinition(); @@ -78,6 +80,7 @@ public AnalyticExpression(Function function) { this.ignoreNullsOutside = function.isIgnoreNullsOutside(); this.nullHandling = function.getNullHandling(); this.funcOrderBy = function.getOrderByElements(); + this.onOverflowTruncate = function.getOnOverflowTruncate(); this.limit = function.getLimit(); this.keep = function.getKeep(); } @@ -96,6 +99,15 @@ public void setOrderByElements(List orderByElements) { windowDef.orderBy.setOrderByElements(orderByElements); } + public String getOnOverflowTruncate() { + return onOverflowTruncate; + } + + public AnalyticExpression setOnOverflowTruncate(String onOverflowTruncate) { + this.onOverflowTruncate = onOverflowTruncate; + return this; + } + public KeepExpression getKeep() { return keep; } @@ -294,6 +306,10 @@ public String toString() { b.append(funcOrderBy.stream().map(OrderByElement::toString).collect(joining(", "))); } + if (onOverflowTruncate != null) { + b.append(" ON OVERFLOW ").append(onOverflowTruncate); + } + if (limit != null) { b.append(limit); } diff --git a/src/main/java/net/sf/jsqlparser/expression/Function.java b/src/main/java/net/sf/jsqlparser/expression/Function.java index ffe2a0128..bdf0bb08b 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Function.java +++ b/src/main/java/net/sf/jsqlparser/expression/Function.java @@ -38,6 +38,7 @@ public class Function extends ASTNodeAccessImpl implements Expression { private boolean ignoreNullsOutside = false; // IGNORE NULLS outside function parameters private Limit limit = null; private KeepExpression keep = null; + private String onOverflowTruncate = null; public Function() {} @@ -302,6 +303,11 @@ public String toString() { if (limit != null) { b.append(limit); } + + if (onOverflowTruncate != null) { + b.append(" ON OVERFLOW ").append(onOverflowTruncate); + } + b.append(")"); params = b.toString(); } else { @@ -399,6 +405,15 @@ public void setOrderByElements(List orderByElements) { this.orderByElements = orderByElements; } + public String getOnOverflowTruncate() { + return onOverflowTruncate; + } + + public Function setOnOverflowTruncate(String onOverflowTruncate) { + this.onOverflowTruncate = onOverflowTruncate; + return this; + } + public E getAttribute(Class type) { return type.cast(getAttribute()); } 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 4d6036cb5..2575b642f 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -857,6 +857,11 @@ public StringBuilder visit(Function function, S context) { orderByDeParser.deParseElement(orderByElement); } } + + if (function.getOnOverflowTruncate() != null) { + buffer.append(" ON OVERFLOW ").append(function.getOnOverflowTruncate()); + } + if (function.getLimit() != null) { new LimitDeparser(this, buffer).deParse(function.getLimit()); } @@ -1127,6 +1132,10 @@ public StringBuilder visit(AnalyticExpression analyticExpression, S context) .collect(joining(", "))); } + if (analyticExpression.getOnOverflowTruncate() != null) { + buffer.append(" ON OVERFLOW ").append(analyticExpression.getOnOverflowTruncate()); + } + if (analyticExpression.getLimit() != null) { new LimitDeparser(this, buffer).deParse(analyticExpression.getLimit()); } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 3393d6f76..61b4fc125 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -212,6 +212,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -241,12 +242,13 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| -| -| -| -| -| +| +| +| +| +| +| +| | /* Salesforce SOQL */ | | @@ -370,6 +372,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -2015,7 +2018,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -5823,6 +5826,8 @@ Function InternalFunction(boolean escaped): Expression attributeExpression = null; Column attributeColumn = null; List orderByList; + String onOverflowTruncate = null; + Token overflowToken = null; Limit limit; } { @@ -5843,7 +5848,18 @@ Function InternalFunction(boolean escaped): | LOOKAHEAD( AllTableColumns() ) expr=AllTableColumns() { expressionList = new ExpressionList(expr); } | - LOOKAHEAD(3) expressionList=ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] + LOOKAHEAD(3) expressionList=ExpressionList() + [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] + + // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/LISTAGG.html + [ + ( overflowToken= | overflowToken= ) { onOverflowTruncate=overflowToken.image; } + [ + overflowToken = { onOverflowTruncate+= " " + overflowToken.image; } + [ ( overflowToken= | overflowToken= ) { onOverflowTruncate+=" " + overflowToken.image + " COUNT"; }] + ] + ] { retval.setOnOverflowTruncate(onOverflowTruncate); } + | LOOKAHEAD({ !getAsBoolean(Feature.allowUnparenthesizedSubSelects) }) expr = Select() { expressionList = new ExpressionList(expr); } ) diff --git a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java index 72f703c38..0433222d3 100644 --- a/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/FunctionTest.java @@ -13,6 +13,8 @@ import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; class FunctionTest { @Test @@ -90,4 +92,20 @@ void testSimpleFunctionIssue2059() throws JSQLParserException { parser.withAllowComplexParsing(false); }); } + + @ParameterizedTest + @ValueSource(strings = { + "select LISTAGG(field, ',' on overflow truncate '...') from dual", + "select LISTAGG(field, ',' on overflow truncate '...' with count) from dual", + "select LISTAGG(field, ',' on overflow truncate '...' without count) from dual", + "select LISTAGG(field, ',' on overflow error) from dual", "SELECT department, \n" + + " LISTAGG(name, ', ' ON OVERFLOW TRUNCATE '... (truncated)' WITH COUNT) WITHIN GROUP (ORDER BY name)\n" + + + " AS employee_names\n" + + "FROM employees\n" + + "GROUP BY department;" + }) + void testListAggOnOverflow(String sqlStr) throws Exception { + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } From 30469248935ecb9a93ea662effed7c7167285801 Mon Sep 17 00:00:00 2001 From: hannes92 Date: Thu, 3 Oct 2024 01:57:04 +0200 Subject: [PATCH 46/88] Failure to parse query with PRIOR in select list (#2083) * Added support for PRIOR operator to be used in select list * Fixed copy paste issue --- .../expression/ConnectByPriorOperator.java | 63 +++++++++++++++++++ .../expression/ExpressionVisitor.java | 6 ++ .../expression/ExpressionVisitorAdapter.java | 5 ++ .../parser/ParserKeywordsUtils.java | 1 + .../sf/jsqlparser/util/TablesNamesFinder.java | 7 +++ .../util/deparser/ExpressionDeParser.java | 8 +++ .../validator/ExpressionValidator.java | 7 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 13 ++++ .../select/oracle-tests/connect_by08.sql | 15 +++++ .../select/oracle-tests/connect_by09.sql | 15 +++++ .../select/oracle-tests/connect_by10.sql | 15 +++++ 11 files changed, 155 insertions(+) create mode 100644 src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java create mode 100644 src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by08.sql create mode 100644 src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by09.sql create mode 100644 src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by10.sql diff --git a/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java b/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java new file mode 100644 index 000000000..98421e2bb --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/ConnectByPriorOperator.java @@ -0,0 +1,63 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2021 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +/* + * Copyright (C) 2021 JSQLParser. + * + * This library is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +package net.sf.jsqlparser.expression; + +import net.sf.jsqlparser.parser.ASTNodeAccessImpl; +import net.sf.jsqlparser.schema.Column; + +import java.util.Objects; + +/** + * + * @author are + */ +public class ConnectByPriorOperator extends ASTNodeAccessImpl implements Expression { + private final Column column; + + public ConnectByPriorOperator(Column column) { + this.column = Objects.requireNonNull(column, + "The COLUMN of the ConnectByPrior Operator must not be null"); + } + + public Column getColumn() { + return column; + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } + + public StringBuilder appendTo(StringBuilder builder) { + builder.append("PRIOR ").append(column); + return builder; + } + + @Override + public String toString() { + return appendTo(new StringBuilder()).toString(); + } +} \ No newline at end of file diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index e02ff0262..a6a0992b0 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -557,6 +557,12 @@ default void visit(ConnectByRootOperator connectByRootOperator) { this.visit(connectByRootOperator, null); } + T visit(ConnectByPriorOperator connectByPriorOperator, S context); + + default void visit(ConnectByPriorOperator connectByPriorOperator) { + this.visit(connectByPriorOperator, null); + } + T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context); default void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) { diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 5a4b34345..6a54e3851 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -703,6 +703,11 @@ public T visit(ConnectByRootOperator connectByRootOperator, S context) { return connectByRootOperator.getColumn().accept(this, context); } + @Override + public T visit(ConnectByPriorOperator connectByPriorOperator, S context) { + return connectByPriorOperator.getColumn().accept(this, context); + } + @Override public T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { return oracleNamedFunctionParameter.getExpression().accept(this, context); diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index f6ff7e7aa..9e9fa8b05 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -56,6 +56,7 @@ public class ParserKeywordsUtils { {"CHECK", RESTRICTED_SQL2016}, {"CONNECT", RESTRICTED_ALIAS}, {"CONNECT_BY_ROOT", RESTRICTED_JSQLPARSER}, + {"PRIOR", RESTRICTED_JSQLPARSER}, {"CONSTRAINT", RESTRICTED_SQL2016}, {"CREATE", RESTRICTED_ALIAS}, {"CROSS", RESTRICTED_SQL2016}, diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 1e0f93968..ee4601e75 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -20,6 +20,7 @@ import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; import net.sf.jsqlparser.expression.ConnectByRootOperator; +import net.sf.jsqlparser.expression.ConnectByPriorOperator; import net.sf.jsqlparser.expression.DateTimeLiteralExpression; import net.sf.jsqlparser.expression.DateValue; import net.sf.jsqlparser.expression.DoubleValue; @@ -1722,6 +1723,12 @@ public Void visit(ConnectByRootOperator connectByRootOperator, S context) { return null; } + @Override + public Void visit(ConnectByPriorOperator connectByPriorOperator, S context) { + connectByPriorOperator.getColumn().accept(this, context); + return null; + } + @Override public Void visit(IfElseStatement ifElseStatement, S context) { ifElseStatement.getIfStatement().accept(this, context); 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 2575b642f..3b0e7281e 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -20,6 +20,7 @@ import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; import net.sf.jsqlparser.expression.ConnectByRootOperator; +import net.sf.jsqlparser.expression.ConnectByPriorOperator; import net.sf.jsqlparser.expression.DateTimeLiteralExpression; import net.sf.jsqlparser.expression.DateValue; import net.sf.jsqlparser.expression.DoubleValue; @@ -1583,6 +1584,13 @@ public StringBuilder visit(ConnectByRootOperator connectByRootOperator, S co return buffer; } + @Override + public StringBuilder visit(ConnectByPriorOperator connectByPriorOperator, S context) { + buffer.append("PRIOR "); + connectByPriorOperator.getColumn().accept(this, context); + return buffer; + } + @Override public StringBuilder visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { 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 5278c3010..8c3a36066 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 @@ -19,6 +19,7 @@ import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; import net.sf.jsqlparser.expression.ConnectByRootOperator; +import net.sf.jsqlparser.expression.ConnectByPriorOperator; import net.sf.jsqlparser.expression.DateTimeLiteralExpression; import net.sf.jsqlparser.expression.DateValue; import net.sf.jsqlparser.expression.DoubleValue; @@ -1014,6 +1015,12 @@ public Void visit(ConnectByRootOperator connectByRootOperator, S context) { return null; } + @Override + public Void visit(ConnectByPriorOperator connectByPriorOperator, S context) { + connectByPriorOperator.getColumn().accept(this, context); + return null; + } + @Override public Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) { oracleNamedFunctionParameter.getExpression().accept(this, context); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 61b4fc125..5809e4987 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2749,6 +2749,8 @@ SelectItem SelectItem() #SelectItem: ( expression = AllColumns() | + expression = ConnectByPriorOperator() + | LOOKAHEAD(AllTableColumns()) expression = AllTableColumns() | LOOKAHEAD( 3 ) expression = XorExpression() @@ -4899,6 +4901,17 @@ ConnectByRootOperator ConnectByRootOperator() #ConnectByRootOperator: { } } +ConnectByPriorOperator ConnectByPriorOperator() #ConnectByPriorOperator: { + Column column; +} +{ + column = Column() + { + return new ConnectByPriorOperator(column); + } +} + + NextValExpression NextValExpression() : { ObjectNames data = null; Token token; diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by08.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by08.sql new file mode 100644 index 000000000..ca64e160e --- /dev/null +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by08.sql @@ -0,0 +1,15 @@ +--- +-- #%L +-- JSQLParser library +-- %% +-- Copyright (C) 2004 - 2019 JSQLParser +-- %% +-- Dual licensed under GNU LGPL 2.1 or Apache License 2.0 +-- #L% +--- +select t.*, connect_by_root t.id as root_id +from test t +start with t.id = 1 +connect by prior t.id = t.parent_id +order siblings by t.some_text +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on Oct 2, 2024, 8:11:58 PM \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by09.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by09.sql new file mode 100644 index 000000000..e29c601d6 --- /dev/null +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by09.sql @@ -0,0 +1,15 @@ +--- +-- #%L +-- JSQLParser library +-- %% +-- Copyright (C) 2004 - 2019 JSQLParser +-- %% +-- Dual licensed under GNU LGPL 2.1 or Apache License 2.0 +-- #L% +--- +select t.*, prior t.id parent_id +from test t +start with t.id = 1 +connect by prior t.id = t.parent_id +order siblings by t.some_text +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on Oct 2, 2024, 8:14:31 PM \ No newline at end of file diff --git a/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by10.sql b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by10.sql new file mode 100644 index 000000000..f0001cf44 --- /dev/null +++ b/src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/connect_by10.sql @@ -0,0 +1,15 @@ +--- +-- #%L +-- JSQLParser library +-- %% +-- Copyright (C) 2004 - 2019 JSQLParser +-- %% +-- Dual licensed under GNU LGPL 2.1 or Apache License 2.0 +-- #L% +--- +select t.*, prior t.id as parent_id +from test t +start with t.id = 1 +connect by prior t.id = t.parent_id +order siblings by t.some_text +--@SUCCESSFULLY_PARSED_AND_DEPARSED first on Oct 2, 2024, 8:14:33 PM \ No newline at end of file From be8ff930ebc4fa0d3c63122206beefd75a68c365 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 3 Oct 2024 07:30:54 +0700 Subject: [PATCH 47/88] fix: clean up minor issues around #2083 - `PRIOR` is a reserved keyword now Signed-off-by: Andreas Reichel --- build.gradle | 2 +- .../java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java | 1 + src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 4 ++-- src/site/sphinx/keywords.rst | 4 ++++ .../java/net/sf/jsqlparser/statement/select/SelectTest.java | 3 ++- .../net/sf/jsqlparser/statement/select/SpecialOracleTest.java | 3 ++- 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index c5d77bf30..66d4d27f9 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ plugins { id "de.undercouch.download" version "latest.release" id 'org.hidetake.ssh' version "latest.release" - id "se.bjurr.gitchangelog.git-changelog-gradle-plugin" version "latest.release" + id "se.bjurr.gitchangelog.git-changelog-gradle-plugin" version "2.0.0" //later depends on JDK 17 id "me.champeau.jmh" version "latest.release" id "com.nwalsh.gradle.saxon.saxon-gradle" version "0.9.6" } diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 9e9fa8b05..80bc71779 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -116,6 +116,7 @@ public class ParserKeywordsUtils { {"PIVOT", RESTRICTED_JSQLPARSER}, {"PLUS", RESTRICTED_JSQLPARSER}, {"PREFERRING", RESTRICTED_JSQLPARSER}, + {"PRIOR", RESTRICTED_ALIAS}, {"PROCEDURE", RESTRICTED_ALIAS}, {"PUBLIC", RESTRICTED_ALIAS}, {"RETURNING", RESTRICTED_JSQLPARSER}, diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 5809e4987..63d0b55cb 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2018,7 +2018,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PRIOR" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -2749,7 +2749,7 @@ SelectItem SelectItem() #SelectItem: ( expression = AllColumns() | - expression = ConnectByPriorOperator() + LOOKAHEAD( 3 ) expression = ConnectByPriorOperator() | LOOKAHEAD(AllTableColumns()) expression = AllTableColumns() | diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index 133ce39cd..159c2fb85 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -29,6 +29,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | CONNECT_BY_ROOT | Yes | Yes | +----------------------+-------------+-----------+ +| PRIOR | Yes | Yes | ++----------------------+-------------+-----------+ | CONSTRAINT | Yes | Yes | +----------------------+-------------+-----------+ | CREATE | Yes | | @@ -147,6 +149,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | PREFERRING | Yes | Yes | +----------------------+-------------+-----------+ +| PRIOR | Yes | | ++----------------------+-------------+-----------+ | PROCEDURE | Yes | | +----------------------+-------------+-----------+ | PUBLIC | Yes | | 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 fd407ee47..dca870860 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -3055,10 +3055,11 @@ public void testReservedKeyword2() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(stmt); } + // PRIOR is a reserved keyword in Oracle @Test public void testReservedKeyword3() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed( - "SELECT * FROM mytable1 t JOIN mytable2 AS prior ON t.id = prior.id"); + "SELECT * FROM mytable1 t JOIN mytable2 AS \"prior\" ON t.id = \"prior\".id"); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java index f4cb8637d..1c28f6aad 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SpecialOracleTest.java @@ -80,7 +80,8 @@ public class SpecialOracleTest { "condition08.sql", "condition09.sql", "condition10.sql", "condition12.sql", "condition14.sql", "condition15.sql", "condition19.sql", "condition20.sql", "connect_by01.sql", "connect_by02.sql", "connect_by03.sql", "connect_by04.sql", - "connect_by05.sql", "connect_by06.sql", "connect_by07.sql", "datetime01.sql", + "connect_by05.sql", "connect_by06.sql", "connect_by07.sql", "connect_by08.sql", + "connect_by09.sql", "connect_by10.sql", "datetime01.sql", "datetime02.sql", "datetime04.sql", "datetime05.sql", "datetime06.sql", "dblink01.sql", "for_update01.sql", "for_update02.sql", "for_update03.sql", "function04.sql", "function05.sql", "for_update04.sql", "for_update05.sql", "for_update06.sql", From 4814ccdd35b427704717607516a5b4dfc734d39c Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Fri, 18 Oct 2024 09:20:42 +0700 Subject: [PATCH 48/88] feat: `LATERAL VIEW` supports multiple alias columns - fixes #2088 Signed-off-by: Andreas Reichel --- .../java/net/sf/jsqlparser/expression/Alias.java | 16 +++++++++++++--- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 10 ++++++++-- .../net/sf/jsqlparser/expression/AliasTest.java | 8 ++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/Alias.java b/src/main/java/net/sf/jsqlparser/expression/Alias.java index 3011b0985..2bbb7817c 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Alias.java +++ b/src/main/java/net/sf/jsqlparser/expression/Alias.java @@ -65,7 +65,7 @@ public void setAliasColumns(List aliasColumns) { @Override public String toString() { - String alias = (useAs ? " AS " : " ") + name; + String alias = (useAs ? " AS " : " ") + (name != null ? name : ""); if (aliasColumns != null && !aliasColumns.isEmpty()) { StringBuilder ac = new StringBuilder(); @@ -75,10 +75,10 @@ public String toString() { } ac.append(col.name); if (col.colDataType != null) { - ac.append(" ").append(col.colDataType.toString()); + ac.append(" ").append(col.colDataType); } } - alias += "(" + ac + ")"; + alias += name != null ? "(" + ac + ")" : ac; } return alias; @@ -99,6 +99,16 @@ public Alias withAliasColumns(List aliasColumns) { return this; } + + public Alias addAliasColumns(String... columnNames) { + List collection = + Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); + for (String columnName : columnNames) { + collection.add(new AliasColumn(columnName)); + } + return this.withAliasColumns(collection); + } + public Alias addAliasColumns(AliasColumn... aliasColumns) { List collection = Optional.ofNullable(getAliasColumns()).orElseGet(ArrayList::new); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 63d0b55cb..94852dc93 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2314,9 +2314,15 @@ LateralView LateralView() #LateralView: tableAlias = new Alias(tableName, false); } ] - columnName = RelObjectNameWithoutStart() + columnName = RelObjectNameWithoutStart() { columnAlias = new Alias(columnName, true); } + + // Spark SQL supports multiple Alias Columns: https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select-lateral-view.html + // we simulate this by setting the alias name to null and then just adding the columns + [ + LOOKAHEAD(2) "," { columnAlias.setName(null); columnAlias.addAliasColumns( columnName); } + columnName = RelObjectNameWithoutStart() { columnAlias.addAliasColumns( columnName); } + ] { - columnAlias = new Alias(columnName, true); return new LateralView( useOuter , generatorFunction diff --git a/src/test/java/net/sf/jsqlparser/expression/AliasTest.java b/src/test/java/net/sf/jsqlparser/expression/AliasTest.java index 809aed3dd..6c65bc8a3 100644 --- a/src/test/java/net/sf/jsqlparser/expression/AliasTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/AliasTest.java @@ -20,4 +20,12 @@ void testUDTF() throws JSQLParserException { String sqlStr = "select udtf_1(words) as (a1, a2) from tab"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testLateralViewMultipleColumns() throws JSQLParserException { + String sqlStr = "SELECT k, v \n" + + "FROM table \n" + + "LATERAL VIEW EXPLODE(a) exploded_data AS k, v;"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } From 420efa809064e186e035cf1ce0af456f3cef4dcd Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sat, 19 Oct 2024 08:02:44 +0700 Subject: [PATCH 49/88] doc: Explain the different Alias types and use cases Signed-off-by: Andreas Reichel --- src/main/java/net/sf/jsqlparser/expression/Alias.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/net/sf/jsqlparser/expression/Alias.java b/src/main/java/net/sf/jsqlparser/expression/Alias.java index 2bbb7817c..ffc599680 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Alias.java +++ b/src/main/java/net/sf/jsqlparser/expression/Alias.java @@ -20,6 +20,15 @@ import net.sf.jsqlparser.schema.MultiPartName; import net.sf.jsqlparser.statement.create.table.ColDataType; +/** + * The type Alias for Tables, Columns or Views. + * + * We support three different types: + * 1) Simple String: `SELECT 1 AS "ALIAS"` when NAME is set and aliasColumns has no elements + * 2) UDF Aliases: `SELECT udf(1,2,3) AS "Alias(a,b,c)"` " when NAME!=null and aliasColumns has elements + * 3) Column lists for LATERAL VIEW: `SELECT * from a LATERAL VIEW EXPLODE ... AS a, b, c`, when NAME is NULL and aliasColumns has elements + * @see Spark LATERAL VIEW + */ public class Alias implements Serializable { private String name; From 10658530b8d61398e6d49db4d550ed6ce8fb8c72 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Mon, 21 Oct 2024 15:10:42 +0700 Subject: [PATCH 50/88] chore: Update dependabot Signed-off-by: Andreas Reichel --- .github/dependabot.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3e4a382ed..89826d9e5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,9 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - version: 2 updates: - - package-ecosystem: "gradle" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "gradle" # Specify Gradle as the package manager + directory: "/" # Root directory of your project schedule: - interval: "weekly" + interval: "weekly" # Define how often Dependabot should check for updates + ignore: + - dependency-name: "se.bjurr.gitchangelog.git-changelog-gradle-plugin" + versions: ["*"] # This will ignore all versions for this specific plugin From 229099c74b92845c8560e81653c8321a0fd85c47 Mon Sep 17 00:00:00 2001 From: Nathan Jaremko Date: Wed, 23 Oct 2024 21:11:46 -0400 Subject: [PATCH 51/88] Fix parsing `ALTER TABLE ... ADD COLUMNS (...)` (#2087) The current behaviour fails when it encounters `ADD COLUMNS` and merges everything in the `()` into one string with no whitespace. So `ALTER TABLE catalog.table.name ADD COLUMNS (apples int)` becomes `ALTER TABLE catalog.table.name ADD COLUMNS (applesint)`. This commit adds an understanding of how `ADD COLUMNS` to the grammar. --- .../statement/alter/AlterExpression.java | 11 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 68 ++++++++++--------- .../jsqlparser/statement/alter/AlterTest.java | 17 +++++ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index b13e8356a..7b323b145 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -60,6 +60,7 @@ public class AlterExpression implements Serializable { private String commentText; private boolean hasColumn = false; + private boolean hasColumns = false; private boolean useBrackets = false; @@ -80,6 +81,10 @@ public boolean hasColumn() { return hasColumn; } + public boolean hasColumns() { + return hasColumns; + } + public boolean useBrackets() { return useBrackets; } @@ -92,6 +97,10 @@ public void hasColumn(boolean hasColumn) { this.hasColumn = hasColumn; } + public void hasColumns(boolean hasColumns) { + this.hasColumns = hasColumns; + } + public String getFkSourceSchema() { return fkSourceSchema; } @@ -503,6 +512,8 @@ public String toString() { } else { if (hasColumn) { b.append("COLUMN "); + } else if (hasColumns) { + b.append("COLUMNS "); } if (useIfNotExists && operation == AlterOperation.ADD) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 94852dc93..992512c5e 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1187,7 +1187,7 @@ DescribeStatement Describe(): { DescribeStatement stmt = new DescribeStatement(); Token tk = null; } { - (tk= | tk=) + (tk= | tk=) table = Table() { stmt.setDescribeType(tk.image).setTable(table); } { return stmt; @@ -1388,13 +1388,13 @@ Statement RefreshMaterializedView(): { } { - [ LOOKAHEAD(2) { concurrently = true; } ] + [ LOOKAHEAD(2) { concurrently = true; } ] view = Table() [ { refreshMode = RefreshMode.WITH_DATA; } - [ + [ { refreshMode = RefreshMode.WITH_NO_DATA; } - ] + ] ] captureRest = captureRest() @@ -2017,7 +2017,7 @@ The following tokens are allowed as Names for Schema, Table, Column and Aliases String RelObjectNameWithoutValue() : { Token tk = null; } { - ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= + ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -2227,7 +2227,7 @@ TableStatement TableStatement(): List orderByElements = null; Limit limit = null; Offset offset = null; - TableStatement tableStatement = new TableStatement(); + TableStatement tableStatement = new TableStatement(); }{ table = Table() @@ -2566,12 +2566,12 @@ PlainSelect PlainSelect() #PlainSelect: [ LOOKAHEAD(, { limit==null }) limit = LimitWithOffset() { plainSelect.setLimit(limit); } ] [ LOOKAHEAD() fetch = Fetch() { plainSelect.setFetch(fetch); } ] [ LOOKAHEAD( ) withIsolation = WithIsolation() { plainSelect.setIsolation(withIsolation); } ] - [ LOOKAHEAD(2) - + [ LOOKAHEAD(2) + ( - { plainSelect.setForMode(ForMode.UPDATE); } - | { plainSelect.setForMode(ForMode.SHARE); } - | ( { plainSelect.setForMode(ForMode.NO_KEY_UPDATE); }) + { plainSelect.setForMode(ForMode.UPDATE); } + | { plainSelect.setForMode(ForMode.SHARE); } + | ( { plainSelect.setForMode(ForMode.NO_KEY_UPDATE); }) | ( { plainSelect.setForMode(ForMode.KEY_SHARE); }) ) [ LOOKAHEAD(2) updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ] @@ -3486,7 +3486,7 @@ GroupByElement GroupByColumnReferences(): ( LOOKAHEAD(2) ( - + "(" list = GroupingSet() { groupBy.addGroupingSet(list); } ( LOOKAHEAD(2) "," list = GroupingSet() { groupBy.addGroupingSet(list); })* @@ -3496,7 +3496,7 @@ GroupByElement GroupByColumnReferences(): ( list = ExpressionList() { groupBy.setGroupByExpressions(list); } ( - LOOKAHEAD(2) + LOOKAHEAD(2) "(" list = GroupingSet() { groupBy.addGroupingSet(list); } ( LOOKAHEAD(2) "," list = GroupingSet() { groupBy.addGroupingSet(list); })* @@ -6070,10 +6070,10 @@ CreateIndex CreateIndex(): ) | ( - [ using= { + [ using= { index.setUsing(using.image); createIndex.setIndexTypeBeforeOn(true); - } + } ] table=Table() ) @@ -6611,8 +6611,8 @@ List CreateViewTailComment(): if (op != null) { result.add(op); } - result.add(tk2.image); - } + result.add(tk2.image); + } { return result;} } @@ -7077,11 +7077,17 @@ AlterExpression AlterExpression(): ) | LOOKAHEAD(3) ( - ( LOOKAHEAD(2) { alterExp.hasColumn(true); } )? + ( LOOKAHEAD(2) + ( + { alterExp.hasColumn(true); } + | + { alterExp.hasColumns(true); } + ) + )? [ { alterExp.setUseIfNotExists(true); } ] ( LOOKAHEAD(4) ( - "(" + "(" { alterExp.useBrackets(true);} alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); @@ -7095,22 +7101,22 @@ AlterExpression AlterExpression(): ")" ) | - LOOKAHEAD(2) alterExpressionColumnDataType = AlterExpressionColumnDataType() + LOOKAHEAD(2) alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } | - LOOKAHEAD(3) alterExpressionColumnDropNotNull = AlterExpressionColumnDropNotNull() + LOOKAHEAD(3) alterExpressionColumnDropNotNull = AlterExpressionColumnDropNotNull() { alterExp.addColDropNotNull( alterExpressionColumnDropNotNull);} | - alterExpressionColumnDropDefault = AlterExpressionColumnDropDefault() + alterExpressionColumnDropDefault = AlterExpressionColumnDropDefault() { alterExp.addColDropDefault( alterExpressionColumnDropDefault); } ) ) | ( "(" alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } - ("," - alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } - )* + ("," + alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } + )* ")" ) | @@ -7162,7 +7168,7 @@ AlterExpression AlterExpression(): [LOOKAHEAD(2) ( (tk= | tk=) action = Action() { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] - [LOOKAHEAD(2) ( (tk= | tk=) action = Action() + [LOOKAHEAD(2) ( (tk= | tk=) action = Action() { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } )] constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); } @@ -7316,18 +7322,18 @@ AlterExpression AlterExpression(): ) | LOOKAHEAD(2) - ( (( {alterExp.setOperation(AlterOperation.RENAME_INDEX);} - | {alterExp.setOperation(AlterOperation.RENAME_KEY);}) + ( (( {alterExp.setOperation(AlterOperation.RENAME_INDEX);} + | {alterExp.setOperation(AlterOperation.RENAME_KEY);}) | { alterExp.setOperation(AlterOperation.RENAME_CONSTRAINT); } - ) + ) (tk= | tk=){ alterExp.setOldIndex(new Index().withName(tk.image)); - } + } (tk2= | tk2=){ index = new Index().withName(tk2.image); alterExp.setIndex(index); - } + } ) | LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.TRUNCATE_PARTITION); } truncatePartitionName = RelObjectName() { alterExp.setTruncatePartitionName(truncatePartitionName); } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 2deb2abcc..fc02e85a9 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -54,6 +54,23 @@ public void testAlterTableAddColumn() throws JSQLParserException { assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString()); } + @Test + public void testAlterTableAddColumnsWhitespace() throws JSQLParserException { + Statement stmt = + CCJSqlParserUtil.parse( + "ALTER TABLE test_catalog.test20241014.tt ADD COLUMNS (apples string, bees int)"); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + assertEquals("test_catalog.test20241014.tt", alter.getTable().getFullyQualifiedName()); + AlterExpression alterExp = alter.getAlterExpressions().get(0); + assertNotNull(alterExp); + List colDataTypes = alterExp.getColDataTypeList(); + assertEquals("apples", colDataTypes.get(0).getColumnName()); + assertEquals("string", colDataTypes.get(0).getColDataType().toString()); + assertEquals("bees", colDataTypes.get(1).getColumnName()); + assertEquals("int", colDataTypes.get(1).getColDataType().toString()); + } + @Test public void testAlterTableAddColumn_ColumnKeyWordImplicit() throws JSQLParserException { Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable ADD mycolumn varchar (255)"); From 3030c35d28ad3cf8cfce1fa33c7ae41bbb5b1a4b Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 24 Oct 2024 08:56:53 +0700 Subject: [PATCH 52/88] fix: `CREATE TABLE` UNIQUE vs. UNIQUE KEY - fixes #2082 - reformat the `CreateTable` production Signed-off-by: Andreas Reichel --- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 191 +++++++++--------- .../statement/create/CreateTableTest.java | 14 ++ 2 files changed, 108 insertions(+), 97 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 992512c5e..1131a1db2 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6217,78 +6217,85 @@ CreateTable CreateTable(boolean isUsingOrReplace): [ LOOKAHEAD(2) { createTable.setIfNotExists(true); }] table=Table() [ LOOKAHEAD(2) ( - LOOKAHEAD(3) - ("(" tableColumn=RelObjectName() { columns.add(tableColumn); } ("," tableColumn=RelObjectName() { columns.add(tableColumn); } )* ")") + LOOKAHEAD(3) ( + "(" tableColumn=RelObjectName() { columns.add(tableColumn); } ("," tableColumn=RelObjectName() { columns.add(tableColumn); } )* ")" + ) | - ("(" - coldef = ColumnDefinition() - - { columnDefinitions.add(coldef); } - ( - "," + "(" + coldef = ColumnDefinition() { columnDefinitions.add(coldef); } ( - LOOKAHEAD(3) ( - tk= + "," + ( + LOOKAHEAD(3) ( + { + idxSpec.clear(); + } + tk= sk3=RelObjectName() - /* colNames=ColumnsNamesList() */ colNames = ColumnNamesWithParamsList() - { idxSpec.clear(); } ( parameter=CreateParameter() { idxSpec.addAll(parameter); } )* { index = new Index().withType(tk.image).withName(sk3).withColumns(colNames).withIndexSpec(new ArrayList(idxSpec)); indexes.add(index); } - ) - | - LOOKAHEAD(3) ( - { - index = new NamedConstraint(); - } - [ sk3=RelObjectName() {index.setName(sk3);} ] + ) + | + LOOKAHEAD(3) ( + { + index = new NamedConstraint(); + tk2=null; + idxSpec.clear(); + } + [ sk3=RelObjectName() {index.setName(sk3);} ] + + ( + tk= tk2= + | + tk= [ tk2= ] + ) + { + index.setType( tk.image + ( tk2!=null ? " " + tk2.image : "" )); + tk2=null; + } - (tk= tk2= {index.setType(tk.image + " " + tk2.image);} - | tk= [ tk2= ] {index.setType(tk.image + (tk2!=null?" " + tk2.image:""));} - ) - /* colNames=ColumnsNamesList() */ colNames = ColumnNamesWithParamsList() - { idxSpec.clear(); } ( parameter=CreateParameter() { idxSpec.addAll(parameter); } )* { index.withColumns(colNames).withIndexSpec(new ArrayList(idxSpec)); indexes.add(index); } - // reset Token to null forcefullly + ) + | + LOOKAHEAD(3) ( { - tk2=null; - } - ) - | - LOOKAHEAD(3) ( {tk=null;} - [ tk= ] [ tk3= ] tk2= + tk=null; + idxSpec.clear(); + } + [ tk= ] + [ tk3= ] tk2= sk3=RelObjectName() - /* colNames=ColumnsNamesList() */ colNames = ColumnNamesWithParamsList() - { idxSpec.clear(); } ( parameter=CreateParameter() { idxSpec.addAll(parameter); } )* { index = new Index() - .withType((tk!=null?tk.image + " ":"") + (tk3!=null?tk3.image + " ":"") + tk2.image) - .withName(sk3) - .withColumns(colNames) - .withIndexSpec(new ArrayList(idxSpec)); + .withType( ( tk!=null ? tk.image + " " : "") + ( tk3!=null ? tk3.image + " ":"" ) + tk2.image) + .withName(sk3) + .withColumns(colNames) + .withIndexSpec(new ArrayList(idxSpec)); indexes.add(index); } - ) - | - LOOKAHEAD(3)( - { - fkIndex = new ForeignKeyIndex(); - } - [ sk3=RelObjectName() {fkIndex.setName(sk3);} ] - tk= tk2= - /* colNames=ColumnsNamesList() */ + ) + | + LOOKAHEAD(3)( + { + fkIndex = new ForeignKeyIndex(); + sk3=null; + + } + [ sk3=RelObjectName() { fkIndex.setName(sk3); } ] + tk= tk2= colNames = ColumnNamesWithParamsList() { fkIndex.withType(tk.image + " " + tk2.image).withColumns(colNames); @@ -6299,60 +6306,50 @@ CreateTable CreateTable(boolean isUsingOrReplace): fkIndex.setReferencedColumnNames(colNames2); indexes.add(fkIndex); } - [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } - )] - [LOOKAHEAD(2) ( (tk= | tk=) action = Action() - { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } - )] - ) - | - LOOKAHEAD(3)( - [ sk3 = RelObjectName()] - {Expression exp = null;} - ("(" exp = Expression() ")")* { - checkCs = new CheckConstraint().withName(sk3).withExpression(exp); - indexes.add(checkCs); - } - ) - | - LOOKAHEAD(2) tk= {excludeC = new ExcludeConstraint(); Expression exp = null;} - (tk2= - ("(" exp = Expression() ")")* {excludeC.setExpression(exp);}) - { - indexes.add(excludeC); - } - | - ( - - coldef = ColumnDefinition() - - /* - columnName=RelObjectName() - - colDataType = ColDataType() - { - columnSpecs = new ArrayList(); - } - - ( parameter=CreateParameter() { columnSpecs.addAll(parameter); } )* - - { - coldef = new ColumnDefinition(); - coldef.setColumnName(columnName); - coldef.setColDataType(colDataType); - if (columnSpecs.size() > 0) - coldef.setColumnSpecs(columnSpecs); - columnDefinitions.add(coldef); - } */ - { columnDefinitions.add(coldef); } + [ LOOKAHEAD(2) ( + + ( tk= | tk= ) action = Action() + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } + ) + ] + [ LOOKAHEAD(2) ( + + ( tk= | tk=) action = Action() + { fkIndex.setReferentialAction(ReferentialAction.Type.from(tk.image), action); } + ) + ] + ) + | + LOOKAHEAD(3)( + { + sk3 = null; + Expression exp = null; + } + [ sk3 = RelObjectName() ] + ( "(" exp = Expression() ")" )* + { + checkCs = new CheckConstraint().withName(sk3).withExpression(exp); + indexes.add(checkCs); + } + ) + | + LOOKAHEAD(2) tk= {excludeC = new ExcludeConstraint(); Expression exp = null;} + (tk2= + ("(" exp = Expression() ")")* {excludeC.setExpression(exp);}) + { + indexes.add(excludeC); + } + | + ( + coldef = ColumnDefinition() + { columnDefinitions.add(coldef); } + ) ) - ) - )* + )* - ")" + ")" ) - ) + ) ] ( LOOKAHEAD(2, { getToken(1).kind != K_AS }) parameter=CreateParameter() { tableOptions.addAll(parameter); } )* diff --git a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java index d9c477159..6b2e67507 100644 --- a/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java @@ -1059,4 +1059,18 @@ void testIssue1864() throws JSQLParserException { + " CHARACTER SET armscii8 COLLATE armscii8_bin NULL DEFAULT NULL FIRST"; assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testUniqueAfterForeignKeyIssue2082() throws JSQLParserException { + String sqlStr = + "CREATE TABLE employees (\n" + + "employee_number int NOT NULL\n" + + ", employee_name char (50) NOT NULL\n" + + ", department_id int\n" + + ", salary int\n" + + ", PRIMARY KEY (employee_number)\n" + + ", FOREIGN KEY (department_id) REFERENCES departments(id)\n" + + ", UNIQUE (employee_name));"; + assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } } From f3f6b72731d5c92520a88ee039d3c7eb7139f785 Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Thu, 24 Oct 2024 21:20:58 +0900 Subject: [PATCH 53/88] Fix issue 2090: Correctly parse LOCK clause in ALTER TABLE statements (#2095) * Add support for parsing LOCK clause in ALTER TABLE statements * fix code formatting --------- Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 9 +++++ .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 13 +++++-- .../jsqlparser/statement/alter/AlterTest.java | 36 +++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 7b323b145..b8991ade3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -57,6 +57,7 @@ public class AlterExpression implements Serializable { private List constraints; private List parameters; + private String lockOption; private String commentText; private boolean hasColumn = false; @@ -395,6 +396,14 @@ public List getParameters() { return parameters; } + public String getLockOption() { + return lockOption; + } + + public void setLockOption(String lockOption) { + this.lockOption = lockOption; + } + public boolean getUseEqual() { return useEqual; } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index 3d0ead731..23ee44b5f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, TRUNCATE_PARTITION; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, TRUNCATE_PARTITION, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 1131a1db2..1da9a6ec4 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -324,6 +324,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -2017,8 +2018,8 @@ The following tokens are allowed as Names for Schema, Table, Column and Aliases String RelObjectNameWithoutValue() : { Token tk = null; } { - ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -7302,6 +7303,14 @@ AlterExpression AlterExpression(): ["=" { alterExp.setUseEqual(true);} ] sk3 = RelObjectName() {alterExp.addParameters(sk3); } ) + | + ( + { + alterExp.setOperation(AlterOperation.LOCK); + } + ["=" { alterExp.setUseEqual(true);} ] + sk3 = RelObjectName() {alterExp.setLockOption(sk3); } + ) | LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.RENAME); } [ { alterExp.hasColumn(true);} ] ( tk= | tk= ) { alterExp.setColOldName(tk.image); } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index fc02e85a9..c08a96394 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1061,4 +1061,40 @@ public void testIssue2027() throws JSQLParserException { "ALTER TABLE `foo_bar` ADD COLUMN `baz` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL"; assertSqlCanBeParsedAndDeparsed(sqlLongText); } + + @Test + public void testIssue2090LockNone() throws JSQLParserException { + String sql = + "ALTER TABLE sbtest1 MODIFY COLUMN pad_3 VARCHAR(20) DEFAULT NULL, ALGORITHM=INPLACE, LOCK=NONE"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + assertEquals("sbtest1", alter.getTable().getFullyQualifiedName()); + + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(3, alterExpressions.size()); + + AlterExpression lockExp = alterExpressions.get(2); + assertEquals(AlterOperation.LOCK, lockExp.getOperation()); + assertEquals("NONE", lockExp.getLockOption()); + } + + @Test + public void testIssue2090LockExclusive() throws JSQLParserException { + String sql = + "ALTER TABLE sbtest1 MODIFY COLUMN pad_3 VARCHAR(20) DEFAULT NULL, ALGORITHM=INPLACE, LOCK=EXCLUSIVE"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + assertEquals("sbtest1", alter.getTable().getFullyQualifiedName()); + + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(3, alterExpressions.size()); + + AlterExpression lockExp = alterExpressions.get(2); + assertEquals(AlterOperation.LOCK, lockExp.getOperation()); + assertEquals("EXCLUSIVE", lockExp.getLockOption()); + } } From dc123820f869803949405692edfa3ac97cefd3b2 Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Sat, 26 Oct 2024 00:33:05 +0900 Subject: [PATCH 54/88] Add parsing functionality for MySQL CONVERT TO statement (#2097) Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 18 +++++++++ .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 5 +++ .../jsqlparser/statement/alter/AlterTest.java | 37 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index b8991ade3..c0f5ef5aa 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -57,6 +57,8 @@ public class AlterExpression implements Serializable { private List constraints; private List parameters; + private String characterSet; + private String collation; private String lockOption; private String commentText; @@ -396,6 +398,22 @@ public List getParameters() { return parameters; } + public String getCharacterSet() { + return characterSet; + } + + public void setCharacterSet(String characterSet) { + this.characterSet = characterSet; + } + + public String getCollation() { + return collation; + } + + public void setCollation(String collation) { + this.collation = collation; + } + public String getLockOption() { return lockOption; } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index 23ee44b5f..d92ac2485 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, TRUNCATE_PARTITION, LOCK; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, TRUNCATE_PARTITION, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 1da9a6ec4..3f7780133 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -7322,6 +7322,11 @@ AlterExpression AlterExpression(): (tk2= | tk2=) { alterExp.setNewTableName(tk2.image);} ) | + ( { alterExp.setOperation(AlterOperation.CONVERT); } + tk= { alterExp.setCharacterSet(tk.image); } + [ tk2= { alterExp.setCollation(tk2.image); }] + ) + | ( {alterExp.setOperation(AlterOperation.COMMENT);} ["=" {alterExp.setOperation(AlterOperation.COMMENT_WITH_EQUAL_SIGN);} ] tk= { alterExp.setCommentText(tk.image); } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index c08a96394..c240d6c69 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1097,4 +1097,41 @@ public void testIssue2090LockExclusive() throws JSQLParserException { assertEquals(AlterOperation.LOCK, lockExp.getOperation()); assertEquals("EXCLUSIVE", lockExp.getLockOption()); } + + @Test + public void testIssue2089() throws JSQLParserException { + String sql = "ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + assertEquals("test_table", alter.getTable().getFullyQualifiedName()); + + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression convertExp = alterExpressions.get(0); + assertEquals(AlterOperation.CONVERT, convertExp.getOperation()); + assertEquals("utf8mb4", convertExp.getCharacterSet()); + assertNull(convertExp.getCollation()); + } + + @Test + public void testIssue2089WithCollation() throws JSQLParserException { + String sql = + "ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + assertEquals("test_table", alter.getTable().getFullyQualifiedName()); + + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression convertExp = alterExpressions.get(0); + assertEquals(AlterOperation.CONVERT, convertExp.getOperation()); + assertEquals("utf8mb4", convertExp.getCharacterSet()); + assertEquals("utf8mb4_general_ci", convertExp.getCollation()); + } } From 6eb588752f0f7801a911291f517254142576e19a Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Mon, 4 Nov 2024 08:53:10 +0700 Subject: [PATCH 55/88] feat: Snowflake `GET` operator `:` Signed-off-by: Andreas Reichel --- src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 4 ++-- .../net/sf/jsqlparser/expression/JsonExpressionTest.java | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 3f7780133..2cb1295aa 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -4859,7 +4859,7 @@ Expression PrimaryExpression() #PrimaryExpression: [ LOOKAHEAD(2) ( LOOKAHEAD(2) ( - token="->" expression=Expression() + ( token="->" | token=":" /*Snowflake GET_PATH Operator*/ ) expression=Expression() | token="->>" expression=Expression() | @@ -5140,7 +5140,7 @@ JsonExpression JsonExpression(Expression expr, List Date: Tue, 12 Nov 2024 21:05:28 +0900 Subject: [PATCH 56/88] Fix issue 2106: Add parsing functionality for MySQL `ADD PARTITION` and `DROP PARTITION` clauses in `ALTER TABLE` statements (#2107) * feat MySQL Alter add partition * fix PartitionDefinition to Serializable --------- Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 23 ++-- .../statement/alter/AlterOperation.java | 2 +- .../create/table/PartitionDefinition.java | 41 +++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 60 ++++++++++- .../jsqlparser/statement/alter/AlterTest.java | 100 +++++++++++++++--- 5 files changed, 199 insertions(+), 27 deletions(-) create mode 100644 src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index c0f5ef5aa..97cbd209a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -9,24 +9,18 @@ */ package net.sf.jsqlparser.statement.alter; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; - import net.sf.jsqlparser.statement.ReferentialAction; import net.sf.jsqlparser.statement.ReferentialAction.Action; import net.sf.jsqlparser.statement.ReferentialAction.Type; import net.sf.jsqlparser.statement.create.table.ColDataType; import net.sf.jsqlparser.statement.create.table.ColumnDefinition; import net.sf.jsqlparser.statement.create.table.Index; +import net.sf.jsqlparser.statement.create.table.PartitionDefinition; import net.sf.jsqlparser.statement.select.PlainSelect; +import java.io.Serializable; +import java.util.*; + @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class AlterExpression implements Serializable { @@ -55,6 +49,7 @@ public class AlterExpression implements Serializable { private boolean uk; private boolean useEqual; + private List partitionDefinitions; private List constraints; private List parameters; private String characterSet; @@ -789,6 +784,14 @@ public AlterExpression addConstraints(Collection cons return this.withConstraints(collection); } + public List getPartitionDefinitions() { + return partitionDefinitions; + } + + public void setPartitionDefinitions(List partitionDefinition) { + this.partitionDefinitions = partitionDefinition; + } + public static final class ColumnDataType extends ColumnDefinition { private final boolean withType; diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index d92ac2485..d34775398 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, TRUNCATE_PARTITION, LOCK; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, TRUNCATE_PARTITION, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java b/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java new file mode 100644 index 000000000..d7a873c47 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java @@ -0,0 +1,41 @@ +package net.sf.jsqlparser.statement.create.table; + +import java.io.Serializable; +import java.util.List; + +public class PartitionDefinition implements Serializable { + private String partitionName; + private String partitionOperation; + private List values; + + public PartitionDefinition(String partitionName, String partitionOperation, + List values) { + this.partitionName = partitionName; + this.partitionOperation = partitionOperation; + this.values = values; + } + + public String getPartitionName() { + return partitionName; + } + + public void setPartitionName(String partitionName) { + this.partitionName = partitionName; + } + + public String getPartitionOperation() { + return partitionOperation; + } + + public void setPartitionOperation(String partitionOperation) { + this.partitionOperation = partitionOperation; + } + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } +} diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 2cb1295aa..062930cac 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -321,6 +321,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -465,6 +466,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -7013,6 +7015,47 @@ Index IndexWithComment(Index index): } } +List PartitionDefinitions(): +{ + Token tk; + List partitionDefinitions = new ArrayList(); + PartitionDefinition partitionDef = null; + String partitionName = null; + String partitionOperation = null; +} +{ + "(" + ( + + partitionName=RelObjectName() + { + List values = new ArrayList(); + } + + ( + + ( + "(" + ( tk= { values.add(tk.image); } + | tk= { values.add(tk.image); } + [ "," ] )* ")" + | { values.add("MAXVALUE"); } + ) { + partitionOperation = "VALUES LESS THAN"; + } + ) + { + partitionDef = new PartitionDefinition(partitionName, partitionOperation, values); + partitionDefinitions.add(partitionDef); + } + [ "," ] + )* + ")" + { + return partitionDefinitions; + } +} + /** * This production needs refactoring to multiple smaller productions. The target class should * be splitted as well. @@ -7034,6 +7077,7 @@ AlterExpression AlterExpression(): AlterExpression.ColumnDropNotNull alterExpressionColumnDropNotNull = null; AlterExpression.ColumnDropDefault alterExpressionColumnDropDefault = null; ReferentialAction.Action action = null; + List partitionDefinition = null; String truncatePartitionName = null; // for captureRest() @@ -7044,7 +7088,9 @@ AlterExpression AlterExpression(): ( ( ( - { alterExp.setOperation(AlterOperation.ADD); } + { alterExp.setOperation(AlterOperation.ADD); + System.out.println("test"); + } | { alterExp.setOperation(AlterOperation.ALTER); } | @@ -7074,6 +7120,16 @@ AlterExpression AlterExpression(): sk3=RelObjectName() tk= { alterExp.withColumnName(sk3).withCommentText(tk.image); } ) | + ( + { + System.out.println("test _ Partition"); + alterExp.setOperation(AlterOperation.ADD_PARTITION); + } + partitionDefinition=PartitionDefinitions() { + alterExp.setPartitionDefinitions(partitionDefinition); + } + ) + | LOOKAHEAD(3) ( ( LOOKAHEAD(2) ( diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index c240d6c69..d5edbf938 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -9,16 +9,6 @@ */ package net.sf.jsqlparser.statement.alter; -import static net.sf.jsqlparser.test.TestUtils.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; @@ -31,13 +21,17 @@ import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.alter.AlterExpression.ColumnDataType; import net.sf.jsqlparser.statement.create.index.CreateIndex; -import net.sf.jsqlparser.statement.create.table.CheckConstraint; -import net.sf.jsqlparser.statement.create.table.ForeignKeyIndex; -import net.sf.jsqlparser.statement.create.table.Index; +import net.sf.jsqlparser.statement.create.table.*; import net.sf.jsqlparser.statement.create.table.Index.ColumnParams; -import net.sf.jsqlparser.statement.create.table.NamedConstraint; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static net.sf.jsqlparser.test.TestUtils.*; +import static org.junit.jupiter.api.Assertions.*; + public class AlterTest { @Test @@ -1134,4 +1128,82 @@ public void testIssue2089WithCollation() throws JSQLParserException { assertEquals("utf8mb4", convertExp.getCharacterSet()); assertEquals("utf8mb4_general_ci", convertExp.getCollation()); } + + @Test + public void testIssue2106AlterTableAddPartition1() throws JSQLParserException { + String sql = "ALTER TABLE t1 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.ADD_PARTITION, partitionExp.getOperation()); + List partitionDefinitions = partitionExp.getPartitionDefinitions(); + assertNotNull(partitionDefinitions); + assertEquals(1, partitionDefinitions.size()); + + PartitionDefinition partitionDef = partitionDefinitions.get(0); + assertEquals("p3", partitionDef.getPartitionName()); + assertEquals("VALUES LESS THAN", partitionDef.getPartitionOperation()); + assertEquals(Collections.singletonList("2002"), partitionDef.getValues()); + } + + @Test + public void testIssue2106AlterTableAddPartition2() throws JSQLParserException { + String sql = + "ALTER TABLE mtk_seat_state_hist ADD PARTITION (PARTITION SEAT_HIST_202004 VALUES LESS THAN ('2020-05-01'), PARTITION SEAT_HIST_202005 VALUES LESS THAN ('2020-06-01'), PARTITION SEAT_HIST_202006 VALUES LESS THAN ('2020-07-01'));"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.ADD_PARTITION, partitionExp.getOperation()); + List partitions = partitionExp.getPartitionDefinitions(); + assertNotNull(partitions); + assertEquals(3, partitions.size()); + + assertEquals("SEAT_HIST_202004", partitions.get(0).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation()); + assertEquals(Collections.singletonList("'2020-05-01'"), partitions.get(0).getValues()); + + assertEquals("SEAT_HIST_202005", partitions.get(1).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation()); + assertEquals(Collections.singletonList("'2020-06-01'"), partitions.get(1).getValues()); + + assertEquals("SEAT_HIST_202006", partitions.get(2).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(2).getPartitionOperation()); + assertEquals(Collections.singletonList("'2020-07-01'"), partitions.get(2).getValues()); + } + + @Test + public void testIssue2106AlterTableAddPartition3() throws JSQLParserException { + String sql = + "ALTER TABLE employees ADD PARTITION (PARTITION p5 VALUES LESS THAN (2010), PARTITION p6 VALUES LESS THAN MAXVALUE);"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.ADD_PARTITION, partitionExp.getOperation()); + List partitions = partitionExp.getPartitionDefinitions(); + assertNotNull(partitions); + assertEquals(2, partitions.size()); + + assertEquals("p5", partitions.get(0).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation()); + assertEquals(Collections.singletonList("2010"), partitions.get(0).getValues()); + + assertEquals("p6", partitions.get(1).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation()); + assertEquals(Collections.singletonList("MAXVALUE"), partitions.get(1).getValues()); + } } From 12952d64f87bdef0354627e1dc533bbf95b0dcd3 Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Thu, 14 Nov 2024 10:05:19 +0900 Subject: [PATCH 57/88] Fix issue 2106: Add parsing functionality for MySQL ADD PARTITION and DROP PARTITION clauses in ALTER TABLE statements(2) (#2108) * feat MySQL Alter add partition * fix PartitionDefinition to Serializable * add Engine variable to MySQL partition definition * fix: Update parser to correctly handle ENGINE token and pass existing CREATE TABLE tests * feat mysql alter drop partition * refactor truncate partition * fix codacy * fix: add LOOKAHEADs Signed-off-by: Andreas Reichel * doc: mention running `gradle check` Signed-off-by: Andreas Reichel * style: add license header Signed-off-by: Andreas Reichel --------- Signed-off-by: Andreas Reichel Co-authored-by: mj-db Co-authored-by: Andreas Reichel --- .../statement/alter/AlterExpression.java | 28 +++----- .../statement/alter/AlterOperation.java | 2 +- .../create/table/PartitionDefinition.java | 21 +++++- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 46 +++++++++++-- src/site/sphinx/contribution.rst | 17 ++++- src/site/sphinx/unsupported.rst | 12 ---- .../jsqlparser/statement/alter/AlterTest.java | 69 +++++++++++++++++++ 7 files changed, 158 insertions(+), 37 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 97cbd209a..38bed4b7a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -49,6 +49,7 @@ public class AlterExpression implements Serializable { private boolean uk; private boolean useEqual; + private List partitions; private List partitionDefinitions; private List constraints; private List parameters; @@ -63,8 +64,6 @@ public class AlterExpression implements Serializable { private boolean useBrackets = false; - private String truncatePartitionName = null; - private boolean useIfNotExists = false; public Index getOldIndex() { @@ -433,19 +432,6 @@ public void setUk(boolean uk) { this.uk = uk; } - public String getTruncatePartitionName() { - return truncatePartitionName; - } - - public void setTruncatePartitionName(String truncatePartitionName) { - this.truncatePartitionName = truncatePartitionName; - } - - public AlterExpression withTruncatePartitionName(String truncatePartitionName) { - this.truncatePartitionName = truncatePartitionName; - return this; - } - public boolean isUseIfNotExists() { return useIfNotExists; } @@ -499,8 +485,8 @@ public String toString() { // Oracle Multi Column Drop b.append("DROP (").append(PlainSelect.getStringList(pkColumns)).append(')'); } else if (operation == AlterOperation.TRUNCATE_PARTITION - && truncatePartitionName != null) { - b.append("TRUNCATE PARTITION ").append(truncatePartitionName); + && partitions != null) { + b.append("TRUNCATE PARTITION ").append(PlainSelect.getStringList(partitions)); } else { if (operation == AlterOperation.COMMENT_WITH_EQUAL_SIGN) { b.append("COMMENT =").append(" "); @@ -784,6 +770,14 @@ public AlterExpression addConstraints(Collection cons return this.withConstraints(collection); } + public List getPartitions() { + return partitions; + } + + public void setPartitions(List partitions) { + this.partitions = partitions; + } + public List getPartitionDefinitions() { return partitionDefinitions; } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index d34775398..f7cd0a4a3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, TRUNCATE_PARTITION, LOCK; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, TRUNCATE_PARTITION, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java b/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java index d7a873c47..a79f242ed 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/PartitionDefinition.java @@ -1,3 +1,12 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ package net.sf.jsqlparser.statement.create.table; import java.io.Serializable; @@ -7,12 +16,14 @@ public class PartitionDefinition implements Serializable { private String partitionName; private String partitionOperation; private List values; + private String storageEngine; public PartitionDefinition(String partitionName, String partitionOperation, - List values) { + List values, String storageEngine) { this.partitionName = partitionName; this.partitionOperation = partitionOperation; this.values = values; + this.storageEngine = storageEngine; } public String getPartitionName() { @@ -38,4 +49,12 @@ public List getValues() { public void setValues(List values) { this.values = values; } + + public String getStorageEngine() { + return storageEngine; + } + + public void setStorageEngine(String storageEngine) { + this.storageEngine = storageEngine; + } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 062930cac..51b111cfb 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -245,6 +245,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -2021,7 +2022,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -6695,6 +6696,7 @@ List CreateParameter(): | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk = | tk = + | tk= | tk="=" ) { param.add(tk.image); } @@ -7022,6 +7024,7 @@ List PartitionDefinitions(): PartitionDefinition partitionDef = null; String partitionName = null; String partitionOperation = null; + String storageEngine = null; } { "(" @@ -7044,8 +7047,9 @@ List PartitionDefinitions(): partitionOperation = "VALUES LESS THAN"; } ) + [ "ENGINE" "=" tk= { storageEngine = tk.image; } ] { - partitionDef = new PartitionDefinition(partitionName, partitionOperation, values); + partitionDef = new PartitionDefinition(partitionName, partitionOperation, values, storageEngine); partitionDefinitions.add(partitionDef); } [ "," ] @@ -7056,6 +7060,26 @@ List PartitionDefinitions(): } } + +List PartitionNamesList() : +{ + Token tk; + List partitionNames = new ArrayList(); +} +{ + tk = { + partitionNames.add(tk.image); + } + ( + LOOKAHEAD(2) "," tk = { + partitionNames.add(tk.image); + } + )* + { + return partitionNames; + } +} + /** * This production needs refactoring to multiple smaller productions. The target class should * be splitted as well. @@ -7077,6 +7101,7 @@ AlterExpression AlterExpression(): AlterExpression.ColumnDropNotNull alterExpressionColumnDropNotNull = null; AlterExpression.ColumnDropDefault alterExpressionColumnDropDefault = null; ReferentialAction.Action action = null; + List partitions = null; List partitionDefinition = null; String truncatePartitionName = null; @@ -7120,9 +7145,8 @@ AlterExpression AlterExpression(): sk3=RelObjectName() tk= { alterExp.withColumnName(sk3).withCommentText(tk.image); } ) | - ( + LOOKAHEAD(3) ( { - System.out.println("test _ Partition"); alterExp.setOperation(AlterOperation.ADD_PARTITION); } partitionDefinition=PartitionDefinitions() { @@ -7292,6 +7316,15 @@ AlterExpression AlterExpression(): | { alterExp.setOperation(AlterOperation.DROP); } ( + ( + { + alterExp.setOperation(AlterOperation.DROP_PARTITION); + } + partitions=PartitionNamesList() { + alterExp.setPartitions(partitions); + } + ) + | ( ( // we use the PK Columns Field instead of the Column Field @@ -7403,7 +7436,10 @@ AlterExpression AlterExpression(): } ) | - LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.TRUNCATE_PARTITION); } truncatePartitionName = RelObjectName() { alterExp.setTruncatePartitionName(truncatePartitionName); } + LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.TRUNCATE_PARTITION); } + partitions=PartitionNamesList() { + alterExp.setPartitions(partitions); + } | tokens = captureRest() { alterExp.setOperation(AlterOperation.UNSPECIFIC); diff --git a/src/site/sphinx/contribution.rst b/src/site/sphinx/contribution.rst index c001f8eb5..65fd49e4d 100644 --- a/src/site/sphinx/contribution.rst +++ b/src/site/sphinx/contribution.rst @@ -61,7 +61,22 @@ The JSQLParser is generated by ``JavaCC`` based on the provided Grammar. The Gra * The complete test suite must succeed. 5) Add the description of the new feature to the ``README.md`` file, section `Extensions`. - 6) Build the package with ``Maven`` and ensure, all checks do pass (PMD and CheckStyle and Code Formatting). + 6) Build the package with ``Gradle`` and ensure, all checks do pass (PMD and CheckStyle and Code Formatting). + .. tab:: Gradle + + .. code-block:: shell + :caption: Gradle `check` Task + + gradle check + + .. tab:: Maven + + .. code-block:: shell + :caption: Maven `verify` Task + + mvn verify + + 7) Create your `GitHub Pull Request `_ Manage Reserved Keywords ------------------------------ diff --git a/src/site/sphinx/unsupported.rst b/src/site/sphinx/unsupported.rst index b6489a84a..b0ad1bc0c 100644 --- a/src/site/sphinx/unsupported.rst +++ b/src/site/sphinx/unsupported.rst @@ -5,14 +5,6 @@ Unsupported Grammar of various RDBMS *JSQLParser* is a RDBMS agnostic parser with a certain focus on SQL:2016 Standard compliant Queries and the "Big Four" (Oracle, MS SQL Server, Postgres, MySQL/MariaDB). We would like to recommend writing portable, standard compliant SQL in general. -- Postgres Implicit cast is not supported. - - .. code-block:: java - - SELECT date '2022-12-31'; - SELECT double precision 1; - - - Oracle PL/SQL blocks are not support. .. code-block:: sql @@ -40,10 +32,6 @@ We would like to recommend writing portable, standard compliant SQL in general. While *JSQLParser* provides a lot of generic support for DDL statements, it is possible that certain RDBMS specific syntax (especially about indices, encodings, compression) won't be supported. -- `JSON` or `XML` specific syntax and functions - - While *JSQLParser* provides a lot of generic support for `JSON` or `XML` processing, it is possible that certain RDBMS specific syntax or functions won't be supported. - - Interval Operators Anything like `DAY HOUR MINUTE SECOND [TO HOUR MINUTE SECOND]` is not supported.: diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index d5edbf938..79a11def2 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1206,4 +1206,73 @@ public void testIssue2106AlterTableAddPartition3() throws JSQLParserException { assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation()); assertEquals(Collections.singletonList("MAXVALUE"), partitions.get(1).getValues()); } + + @Test + public void testIssue2106AlterTableAddPartitionCodeTransaction() throws JSQLParserException { + String sql = + "ALTER TABLE `code_transaction` ADD PARTITION (PARTITION p202108 VALUES LESS THAN ('20210901') ENGINE = InnoDB);"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.ADD_PARTITION, partitionExp.getOperation()); + List partitions = partitionExp.getPartitionDefinitions(); + assertNotNull(partitions); + assertEquals(1, partitions.size()); + + assertEquals("p202108", partitions.get(0).getPartitionName()); + assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation()); + assertEquals(Collections.singletonList("'20210901'"), partitions.get(0).getValues()); + assertEquals("InnoDB", partitions.get(0).getStorageEngine()); + } + + @Test + public void testIssue2106AlterTableDropPartition() throws JSQLParserException { + String sql = + "ALTER TABLE dkpg_payment_details DROP PARTITION p202007, p202008, p202009, p202010"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.DROP_PARTITION, partitionExp.getOperation()); + List partitionNames = partitionExp.getPartitions(); + assertNotNull(partitionNames); + assertEquals(4, partitionNames.size()); + + assertEquals("p202007", partitionNames.get(0)); + assertEquals("p202008", partitionNames.get(1)); + assertEquals("p202009", partitionNames.get(2)); + assertEquals("p202010", partitionNames.get(3)); + } + + @Test + public void testIssue2106AlterTableTruncatePartition() throws JSQLParserException { + String sql = + "ALTER TABLE dkpg_payments TRUNCATE PARTITION p201701, p201707, p201801, p201807"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression partitionExp = alterExpressions.get(0); + assertEquals(AlterOperation.TRUNCATE_PARTITION, partitionExp.getOperation()); + List partitionNames = partitionExp.getPartitions(); + assertNotNull(partitionNames); + assertEquals(4, partitionNames.size()); + + assertEquals("p201701", partitionNames.get(0)); + assertEquals("p201707", partitionNames.get(1)); + assertEquals("p201801", partitionNames.get(2)); + assertEquals("p201807", partitionNames.get(3)); + } } From bc0c5d2d4d039071210068a4ee5e341cbb19ac4a Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Thu, 14 Nov 2024 08:23:06 +0700 Subject: [PATCH 58/88] doc: fixes Signed-off-by: Andreas Reichel --- CHANGELOG.md | 10578 +++++++++++++++++++++++++++++ src/site/sphinx/contribution.rst | 1 + 2 files changed, 10579 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..70bf11431 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10578 @@ +# JSqlParser changelog + +Changelog of JSqlParser. + +## jsqlparser-5.0 (2024-06-30) + +### Breaking changes + +- Visitors return Objects and accept parameters ([5bd28](https://github.com/JSQLParser/JSqlParser/commit/5bd28c8b309df6c) Andreas Reichel) +- Visitors return Objects ([131a9](https://github.com/JSQLParser/JSqlParser/commit/131a988ccea2d91) Andreas Reichel) +- Visitors return Objects ([c2328](https://github.com/JSQLParser/JSqlParser/commit/c2328120e7a79ff) Andreas Reichel) +- Visitors return Objects ([ec497](https://github.com/JSQLParser/JSqlParser/commit/ec49762708e920a) Andreas Reichel) +- Visitors return Objects ([681ca](https://github.com/JSQLParser/JSqlParser/commit/681cac933d83516) Andreas Reichel) + +### Features + +- provide compatibility methods ([3f995](https://github.com/JSQLParser/JSqlParser/commit/3f99548b99bbfe3) Andreas Reichel) +- apply the new parametrized Visitor patterns to all entities and provide default implementations ([e1692](https://github.com/JSQLParser/JSqlParser/commit/e1692990c543ed1) Andreas Reichel) +- syntax sugar ([2fce4](https://github.com/JSQLParser/JSqlParser/commit/2fce4c009b77d85) Andreas Reichel) +- Visitors return Objects and accept parameters ([5bd28](https://github.com/JSQLParser/JSqlParser/commit/5bd28c8b309df6c) Andreas Reichel) +- Visitors return Objects ([131a9](https://github.com/JSQLParser/JSqlParser/commit/131a988ccea2d91) Andreas Reichel) +- Visitors return Objects ([c2328](https://github.com/JSQLParser/JSqlParser/commit/c2328120e7a79ff) Andreas Reichel) +- Visitors return Objects ([ec497](https://github.com/JSQLParser/JSqlParser/commit/ec49762708e920a) Andreas Reichel) +- Visitors return Objects ([681ca](https://github.com/JSQLParser/JSqlParser/commit/681cac933d83516) Andreas Reichel) +- Allow OUTER keyword as function parameter name (#2021) ([fc90c](https://github.com/JSQLParser/JSqlParser/commit/fc90c0b5e566533) Chris Crabtree) +- BigQuery `SELECT AS STRUCT ...` and `SELECT AS VALUE ...` ([5c360](https://github.com/JSQLParser/JSqlParser/commit/5c360a2fc95c261) Andreas Reichel) +- add syntax sugar ([2ace7](https://github.com/JSQLParser/JSqlParser/commit/2ace74d1047e87d) Andreas Reichel) +- `AllColumns`, DuckDB uses `EXCLUDE` instead of `EXCEPT` ([1ad42](https://github.com/JSQLParser/JSqlParser/commit/1ad4234280f7a70) Andreas Reichel) +- syntax sugar ([ae1ef](https://github.com/JSQLParser/JSqlParser/commit/ae1eff9f7434c08) Andreas Reichel) +- syntax sugar ([81846](https://github.com/JSQLParser/JSqlParser/commit/818464c93ae665a) Andreas Reichel) +- syntax sugar ([2cb3e](https://github.com/JSQLParser/JSqlParser/commit/2cb3e589b60e192) Andreas Reichel) +- syntax sugar ([b2eed](https://github.com/JSQLParser/JSqlParser/commit/b2eed1e910c97de) Andreas Reichel) +- Databricks IGNORE/RESPECT NULLS ([e9c9a](https://github.com/JSQLParser/JSqlParser/commit/e9c9a173a660bbe) Andreas Reichel) +- Databricks IGNORE/RESPECT NULLS ([544b1](https://github.com/JSQLParser/JSqlParser/commit/544b1683789f20b) Andreas Reichel) +- Capture expression name part delimiters (#2001) ([0368b](https://github.com/JSQLParser/JSqlParser/commit/0368b9ebad76742) Chris Crabtree) +- syntax sugar ([ca5c5](https://github.com/JSQLParser/JSqlParser/commit/ca5c553efde37eb) Andreas Reichel) +- translate HEX to Unicode String and ByteArray String ([df519](https://github.com/JSQLParser/JSqlParser/commit/df519333ff34740) Andreas Reichel) +- `StructType` syntax sugar ([6e9bf](https://github.com/JSQLParser/JSqlParser/commit/6e9bf42b0b2d783) Andreas Reichel) +- `Values` implement `FromItem` ([e426c](https://github.com/JSQLParser/JSqlParser/commit/e426c5a67c505b5) Andreas Reichel) +- add `ParenthesedSelect` delegate ([66d05](https://github.com/JSQLParser/JSqlParser/commit/66d05a2bb7c41f3) Andreas Reichel) +- add `ParenthesedSelect` delegate ([f1699](https://github.com/JSQLParser/JSqlParser/commit/f16999393589702) Andreas Reichel) +- Simplify traversing the AST bottom to top ([bddc4](https://github.com/JSQLParser/JSqlParser/commit/bddc41cddf5b5bf) Andreas Reichel) +- AST Node access for `FromItem` ([c1edf](https://github.com/JSQLParser/JSqlParser/commit/c1edf0f8f21bd52) Andreas Reichel) +- RedShift specific Window function IGNORE | RESPECT NULLS ([321c8](https://github.com/JSQLParser/JSqlParser/commit/321c88098a75791) Andreas Reichel) +- RedShift allows `TOP` before `DISTINCT`, see https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_list.html ([13e61](https://github.com/JSQLParser/JSqlParser/commit/13e61a726a87c2f) Andreas Reichel) +- Redshift `APPROXIMATE` Aggregate functions ([e4ece](https://github.com/JSQLParser/JSqlParser/commit/e4ece0c3ecd7ce3) Andreas Reichel) +- add `CCJSqlParserUtil.sanitizeSingleSql(String sqlStr)` to help MyBatikPlus users to clean their statements ([1606e](https://github.com/JSQLParser/JSqlParser/commit/1606e5f0492a485) Andreas Reichel) +- return any `UnsupportedStatement` content ([063d2](https://github.com/JSQLParser/JSqlParser/commit/063d2442d82f920) Andreas Reichel) +- re-enable `UnsupportedStatement` ([82b45](https://github.com/JSQLParser/JSqlParser/commit/82b459bfcd23851) Andreas Reichel) +- better statement error recovery ([b3d3a](https://github.com/JSQLParser/JSqlParser/commit/b3d3a8e492f74a8) Andreas Reichel) +- Syntax Sugar for the parser features ([1d943](https://github.com/JSQLParser/JSqlParser/commit/1d9438e7ef1a86f) Andreas Reichel) +- allow `EXTRACT` to be parsed as regular function also ([b85dc](https://github.com/JSQLParser/JSqlParser/commit/b85dc2fd0004652) Andreas Reichel) +- syntax sugar ([a3858](https://github.com/JSQLParser/JSqlParser/commit/a38581acd538d95) Andreas Reichel) +- syntax sugar ([df7c7](https://github.com/JSQLParser/JSqlParser/commit/df7c792184c61a6) Andreas Reichel) +- Syntax sugar ([67bfa](https://github.com/JSQLParser/JSqlParser/commit/67bfae673421d7c) Andreas Reichel) +- syntax sugar ([b0317](https://github.com/JSQLParser/JSqlParser/commit/b03170e180175b1) Andreas Reichel) +- syntax sugar ([57a29](https://github.com/JSQLParser/JSqlParser/commit/57a296b2c8c5bb0) Andreas Reichel) +- remove Aliases of `ParenthesedSelect`, `LateralSubSelect` and `ParenthesedFromItem` from the Table Names ([46682](https://github.com/JSQLParser/JSqlParser/commit/466826b9b115cb7) Andreas Reichel) +- better access to the `DataType` checks ([edeaf](https://github.com/JSQLParser/JSqlParser/commit/edeafc311c2ab7e) Andreas Reichel) +- Add Data Type information to task for making it easy to understand the expected return type ([31c55](https://github.com/JSQLParser/JSqlParser/commit/31c5533f49776c6) Andreas Reichel) +- Implicit Casts `SELECT DOUBLE PRECISION '1'` ([411a3](https://github.com/JSQLParser/JSqlParser/commit/411a3da9facf206) Andreas Reichel) +- Function Column Aliases without an Alias Name `func(x) (a, b, c)` ([b4ef7](https://github.com/JSQLParser/JSqlParser/commit/b4ef763614bf3a4) Andreas Reichel) +- Support BigQuery specific Aggregate clauses ([0179c](https://github.com/JSQLParser/JSqlParser/commit/0179cc0cac9ceeb) Andreas Reichel) +- syntax sugar for Binary Expressions like Conact, Addition, Multiplication ([ffdde](https://github.com/JSQLParser/JSqlParser/commit/ffddeef7199a056) Andreas Reichel) +- Hex to Long conversion ([620db](https://github.com/JSQLParser/JSqlParser/commit/620db709e48c22e) Andreas Reichel) +- syntax sugar for Expressions ([a5693](https://github.com/JSQLParser/JSqlParser/commit/a56934da1d3a7ae) Andreas Reichel) +- Salesforce SOQL `INCLUDES` and `EXCLUDES` operators (#1985) ([f3f0e](https://github.com/JSQLParser/JSqlParser/commit/f3f0e051358a493) lucarota) +- Google BigQuery `CAST` with `FORMAT` clause ([0d813](https://github.com/JSQLParser/JSqlParser/commit/0d813f03faa2b3b) Andreas Reichel) +- DuckDB Lambda Functions ([23679](https://github.com/JSQLParser/JSqlParser/commit/236793aaeabc30f) Andreas Reichel) +- DuckDB `STRUCT` with curly brackets and explicit Column Type Cast ([1cd57](https://github.com/JSQLParser/JSqlParser/commit/1cd576b32c774e8) Andreas Reichel) +- `RECURSIVE` does not need to be a reserved ([5cb4c](https://github.com/JSQLParser/JSqlParser/commit/5cb4c55067f4fe2) Andreas Reichel) +- DuckDB `STRUCT` with curly brackets ([339d6](https://github.com/JSQLParser/JSqlParser/commit/339d6baece2c199) Andreas Reichel) +- BigQuery `STRUCT` data types and literal ([4c187](https://github.com/JSQLParser/JSqlParser/commit/4c187d51055a3d8) Andreas Reichel) +- TablesNamesFinder can return also references to WITH items ([9d645](https://github.com/JSQLParser/JSqlParser/commit/9d64511239a4514) Andreas Reichel) +- allow double-quoted `DateTimeLiteral` like `DATETIME "2005-01-03 12:34:56"` ([f6790](https://github.com/JSQLParser/JSqlParser/commit/f6790913b754850) Andreas Reichel) +- support `DATETIME` literal used for Google BigQuery ([a386d](https://github.com/JSQLParser/JSqlParser/commit/a386d297c418921) Andreas Reichel) +- link `TOP` to AST node ([79c42](https://github.com/JSQLParser/JSqlParser/commit/79c42ed31eb6986) Andreas Reichel) + +### Bug Fixes + +- `AllTableColumns`, DuckDB specific `EXCLUDE` ([c9ecf](https://github.com/JSQLParser/JSqlParser/commit/c9ecfc6ddbdd139) Andreas Reichel) +- `AllColumns` Replacement shall be about Columns only ([f4b40](https://github.com/JSQLParser/JSqlParser/commit/f4b40e43a4f8d3d) Andreas Reichel) +- `FromItem` with Alias without `AS` keyword ([5f580](https://github.com/JSQLParser/JSqlParser/commit/5f580af190c6fbb) Andreas Reichel) +- set `stringValue` in `DoubleValue.setValue` (#2009) ([e07f8](https://github.com/JSQLParser/JSqlParser/commit/e07f8d019ddf38d) Damian) +- try working around `UnsupportedStatement` issue ([fbe97](https://github.com/JSQLParser/JSqlParser/commit/fbe97a8deb84ae9) Andreas Reichel) +- allow `BASE64` keyword ([7daf7](https://github.com/JSQLParser/JSqlParser/commit/7daf7af36d825f7) Andreas Reichel) +- `StructType` expressions must use Visitor instead of `toString()` ([b95d8](https://github.com/JSQLParser/JSqlParser/commit/b95d8e3e4ee01b0) Andreas Reichel) +- `AnyComparisionItem` with extra brackets ([4e1a1](https://github.com/JSQLParser/JSqlParser/commit/4e1a1535f4ef706) Andreas Reichel) +- `FOR UPDATE` clause should come after the select body ([cf7fe](https://github.com/JSQLParser/JSqlParser/commit/cf7fe157de372f3) Andreas Reichel) +- initialise the `SelectDeparser` with an `ExpressionDeparser` (but not with an empty Adaptor only) ([f417c](https://github.com/JSQLParser/JSqlParser/commit/f417c8f248c7bb1) Andreas Reichel) +- `ALTER ...` shall `captureRest()` only to the next statement terminator ([15d14](https://github.com/JSQLParser/JSqlParser/commit/15d14ab0b9dcadf) Andreas Reichel) +- correct the wrong Assertion ([8461e](https://github.com/JSQLParser/JSqlParser/commit/8461e8ad1a3f5e3) Andreas Reichel) +- don't insert space after certain punctuation ([159c2](https://github.com/JSQLParser/JSqlParser/commit/159c28ee8f68cab) Andreas Reichel) +- treat Array Brackets `[..]` as syntax characters and surround by space when normalizing for comparison ([c9d1e](https://github.com/JSQLParser/JSqlParser/commit/c9d1eaefca91c6e) Andreas Reichel) +- `REGEXP` does not need to be reserved ([f6524](https://github.com/JSQLParser/JSqlParser/commit/f65240f381f9855) Andreas Reichel) +- `REGEXP` does not need to be reserved ([a9e67](https://github.com/JSQLParser/JSqlParser/commit/a9e67667b9c1590) Andreas Reichel) +- Array Arguments without `ARRAY` keyword ([0f9a8](https://github.com/JSQLParser/JSqlParser/commit/0f9a8ec02786f5d) Andreas Reichel) +- Function with Array Arguments ([f782e](https://github.com/JSQLParser/JSqlParser/commit/f782eda7afa17d3) Andreas Reichel) +- parsing `SelectItem` shall support `Xor` ([c8839](https://github.com/JSQLParser/JSqlParser/commit/c883920a1175ffc) Andreas Reichel) + +### Other changes + +**switched to version 5.0-SNAPSHOT** + + +[275e0](https://github.com/JSQLParser/JSqlParser/commit/275e0c0627bb8a2) Tobias Warneke *2024-06-30 20:26:08* + +**corrected license header** + + +[5fb9f](https://github.com/JSQLParser/JSqlParser/commit/5fb9f568684ace1) Tobias Warneke *2024-06-30 20:21:47* + +**corrected license header** + + +[456d5](https://github.com/JSQLParser/JSqlParser/commit/456d53b09c48f77) Tobias Warneke *2024-06-30 20:02:41* + +**support custom DeParser (#2013)** + + +[74793](https://github.com/JSQLParser/JSqlParser/commit/7479342dd95125a) Redkale *2024-05-29 06:02:40* + +**Add missing java.sql require (#1999)** + +* Add missing java.sql +* Update maven checkstyle +* Fix gradle checkstyle +* Bump surefire plugin +* Skip modules in tests + +[df48c](https://github.com/JSQLParser/JSqlParser/commit/df48c4ba5b2b44f) Ethan McCue *2024-04-30 05:13:54* + +**Add module info (#1998)** + +* Add module info +* Trailing newline + +[761b4](https://github.com/JSQLParser/JSqlParser/commit/761b45b2f6c4b81) Ethan McCue *2024-04-30 04:36:41* + +**** + + +[89ac0](https://github.com/JSQLParser/JSqlParser/commit/89ac0fc3c0af712) Tobias Warneke *2024-03-09 22:12:33* + + +## jsqlparser-4.9 (2024-03-09) + +### Features + +- add DB2 special register `CURRENT TIMEZONE` ([c412d](https://github.com/JSQLParser/JSqlParser/commit/c412d6a52f9b2ea) Andreas Reichel) +- add additional CREATE VIEW modifiers (#1964) ([67e22](https://github.com/JSQLParser/JSqlParser/commit/67e220425f24148) David Goss) +- with no log (#1953) ([d9c44](https://github.com/JSQLParser/JSqlParser/commit/d9c44499d096b1f) mjh) +- support keyword "only" for postgresql (#1952) ([f1676](https://github.com/JSQLParser/JSqlParser/commit/f1676dd992911d9) 猫屎咖啡) +- support any number/order of merge operations (#1938) ([f1c52](https://github.com/JSQLParser/JSqlParser/commit/f1c525a1eaf3087) David Goss) + +### Bug Fixes + +- chained function calls of `SimpleFunction` ([98055](https://github.com/JSQLParser/JSqlParser/commit/9805581accf89d2) Andreas Reichel) +- issue #1948 `Between` with expression ([b9453](https://github.com/JSQLParser/JSqlParser/commit/b9453f228adf9ad) Andreas Reichel) +- return NULL when parsing empty Strings ([94fb8](https://github.com/JSQLParser/JSqlParser/commit/94fb87237f36cce) Andreas Reichel) +- allow Parameters like `$1`,`$2` ([17f5f](https://github.com/JSQLParser/JSqlParser/commit/17f5f2ad680dfdb) Andreas Reichel) +- allow `DATA` as `ColumnType()` keyword ([72a51](https://github.com/JSQLParser/JSqlParser/commit/72a51e58413a291) Andreas Reichel) +- make analytic expression visitor null-safe (#1944) ([768c6](https://github.com/JSQLParser/JSqlParser/commit/768c63f4660509b) David Goss) +- Fixes parsing failing for ALTER MODIFY queries not containing datatype (#1961) ([029fd](https://github.com/JSQLParser/JSqlParser/commit/029fd42e84e65ee) Tanish Grover) +- tables not find in parentheses join sql. (#1956) ([182f4](https://github.com/JSQLParser/JSqlParser/commit/182f484dc43945b) hancher) +- issue1875 (#1957) ([98aa9](https://github.com/JSQLParser/JSqlParser/commit/98aa90cb988580a) mjh) +- ExpressionVisitor.visit(AllTableColumns) method isn't being called. (#1942) ([bc166](https://github.com/JSQLParser/JSqlParser/commit/bc16618eaa8fd93) Brian S. O'Neill) + +### Other changes + +**** + + +[2319d](https://github.com/JSQLParser/JSqlParser/commit/2319da81bb27f4e) Tobias Warneke *2024-03-09 20:49:14* + +**Handle select in ExpressionVisitorAdapter (#1972)** + + +[424a8](https://github.com/JSQLParser/JSqlParser/commit/424a852ac8071d7) Kaartic Sivaraam *2024-02-23 23:32:07* + +**Update README.md** + +* Fixes #1968 + +[8dcfb](https://github.com/JSQLParser/JSqlParser/commit/8dcfb4a3bf5682d) manticore-projects *2024-02-17 12:03:43* + +**Guard Values against null/empty values (#1965)** + +* Guard Values against null/empty values +* The classes modified by this commit are `DoubleValue`, `LongValue`, and +* `TimeValue`. Both `null` and empty strings provided to their +* constructors fail, but they provide very different error messages +* (NullPointerException and StringIndexOutOfBoundsException), which is +* neither sensible nor helpful in debugging. +* This commit adds a guard to throw `IllegalArgumentException` for both +* cases in order to improve coherency and usefulness of the error +* messages. +* fix checkstyle issues + +[b0032](https://github.com/JSQLParser/JSqlParser/commit/b00322efa0c77d2) Heewon Lee *2024-02-14 07:34:40* + +**support oracle alter table truncate partition (#1954)** + +* feat: oracle alter table truncate partition +* feat: oracle alter table truncate partition +* feat: code format +* feat: code format +* --------- +* Co-authored-by: mjh <majh118@chinaunicom.cn> + +[cc7aa](https://github.com/JSQLParser/JSqlParser/commit/cc7aa01913a7201) mjh *2024-02-04 07:19:19* + +**Build with Automatic-Module-Name for compatibility with the Java module system. (#1941)** + + +[92e02](https://github.com/JSQLParser/JSqlParser/commit/92e02c6da69d917) Brian S. O'Neill *2024-01-06 14:04:45* + +**Create maven_deploy.yml** + + +[b4070](https://github.com/JSQLParser/JSqlParser/commit/b40705785751b49) Tobias *2023-12-28 22:31:54* + +**corrected hopefully maven snapshot deployment** + + +[a70f0](https://github.com/JSQLParser/JSqlParser/commit/a70f0d1f3f3d91e) Tobias Warneke *2023-12-28 22:20:08* + +**corrected hopefully maven snapshot deployment** + + +[f0d3a](https://github.com/JSQLParser/JSqlParser/commit/f0d3ab6b42193ae) Tobias Warneke *2023-12-28 22:17:43* + +**finally done** + + +[6c1ca](https://github.com/JSQLParser/JSqlParser/commit/6c1caff118f84bd) Tobias Warneke *2023-12-28 00:29:26* + + +## jsqlparser-4.8 (2023-12-28) + +### Features + +- support mysql with rollup (#1923) ([77f6f](https://github.com/JSQLParser/JSqlParser/commit/77f6fb8c92b3378) jxnu-liguobin) +- Support `FOR SHARE` (#1922) ([815f8](https://github.com/JSQLParser/JSqlParser/commit/815f8753d552d89) jxnu-liguobin) +- [MySQL] Support `TABLE STATEMENT` (#1921) ([313a4](https://github.com/JSQLParser/JSqlParser/commit/313a4b42444b2d2) jxnu-liguobin) +- Support `RENAME INDEX` for MySQL, `RENAME CONSTRAINT` for PostgreSQL (#1920) ([989a8](https://github.com/JSQLParser/JSqlParser/commit/989a84bb215283b) jxnu-liguobin) +- Add support comment in `create view` for MySQL and MariaDb (#1913) ([4d47e](https://github.com/JSQLParser/JSqlParser/commit/4d47e0ab7bc2872) jxnu-liguobin) +- Add support for `REFRESH MATERIALIZED VIEW` (#1911) ([425c7](https://github.com/JSQLParser/JSqlParser/commit/425c72eb7d7f931) jxnu-liguobin) +- `SimpleFunction` for faster parsing of simple, but deep nested functions ([085d7](https://github.com/JSQLParser/JSqlParser/commit/085d7504235e58c) Andreas Reichel) +- add support for snowflake merge statements (#1887) ([36b80](https://github.com/JSQLParser/JSqlParser/commit/36b806dede06260) David Goss) +- `ColDataType` supports `PUBLIC` schema and all non-restricted keywords for type ([1088d](https://github.com/JSQLParser/JSqlParser/commit/1088db7aea0b2f9) Andreas Reichel) +- T-SQL Join Hints ([5f09e](https://github.com/JSQLParser/JSqlParser/commit/5f09ec4914fbdd1) Andreas Reichel) +- old TSQL Joins `*=` and `=*` ([0b50d](https://github.com/JSQLParser/JSqlParser/commit/0b50da4cca555b6) Andreas Reichel) +- MS SQL Server `Merge` `Output` clause ([7bd42](https://github.com/JSQLParser/JSqlParser/commit/7bd42edaa0d9aed) Andreas Reichel) +- MS SQL Server `UPDATE ...` Index Hint ([f919e](https://github.com/JSQLParser/JSqlParser/commit/f919e00c30ff5df) Andreas Reichel) +- Postgres `Contains` and `ContainedBy` Operators ([28a4c](https://github.com/JSQLParser/JSqlParser/commit/28a4c080b718aba) Andreas Reichel) +- Postgres `Contains` and `ContainedBy` Operators ([09d6d](https://github.com/JSQLParser/JSqlParser/commit/09d6dfe7bc7acb8) Andreas Reichel) +- Clickhouse `GLOBAL IN ...` ([ced0d](https://github.com/JSQLParser/JSqlParser/commit/ced0d0090c5c9a9) Andreas Reichel) +- `CREATE INDEX IF NOT EXISTS...` ([da13d](https://github.com/JSQLParser/JSqlParser/commit/da13d7dc1dd1608) Andreas Reichel) +- support clickhouse global keyword in IN Expression ([a9ed7](https://github.com/JSQLParser/JSqlParser/commit/a9ed79825110df7) hezw) + +### Bug Fixes + +- refactor `JsonExpression`, avoiding expensive semantic lookahead and improving performance ([56515](https://github.com/JSQLParser/JSqlParser/commit/56515aba6ca893f) Andreas Reichel) +- `GO` shall terminate statement only, when appearing alone on an empty line ([14637](https://github.com/JSQLParser/JSqlParser/commit/14637ce64763b42) Andreas Reichel) +- De-Parse Oracle Hints in UPDATE, INSERT, DELETE and MERGE ([aaca0](https://github.com/JSQLParser/JSqlParser/commit/aaca05855f9a11b) Andreas Reichel) +- `UpdateSet` shall not have brackets with single element only ([15b9a](https://github.com/JSQLParser/JSqlParser/commit/15b9aef7ca05416) Andreas Reichel) +- make `GLOBAL` a restricted keyword, not usable as an Alias ([dd6cf](https://github.com/JSQLParser/JSqlParser/commit/dd6cf23150f4804) Andreas Reichel) +- Postgres `NextVal()` function ([e3afa](https://github.com/JSQLParser/JSqlParser/commit/e3afa5fbdebc715) Andreas Reichel) +- optional `Expression` in `FETCH` clause ([daee3](https://github.com/JSQLParser/JSqlParser/commit/daee30f7ae88bea) Andreas Reichel) +- allow `RAW` as `CreateParameter` ([ecd40](https://github.com/JSQLParser/JSqlParser/commit/ecd40386585a519) Andreas Reichel) + +### Other changes + +**problem with old sonatype repo?** + + +[66dd0](https://github.com/JSQLParser/JSqlParser/commit/66dd0cffad8255d) Tobias Warneke *2023-12-28 00:10:08* + +**problem with old sonatype repo?** + + +[19bde](https://github.com/JSQLParser/JSqlParser/commit/19bdef65c0e04c3) Tobias Warneke *2023-12-27 22:50:54* + +**problem with old sonatype repo?** + + +[d6b4c](https://github.com/JSQLParser/JSqlParser/commit/d6b4cc374db4197) Tobias Warneke *2023-12-27 22:43:59* + +**problem with old sonatype repo?** + + +[5ff53](https://github.com/JSQLParser/JSqlParser/commit/5ff53e835e675ea) Tobias Warneke *2023-12-27 00:54:26* + +**** + + +[6a327](https://github.com/JSQLParser/JSqlParser/commit/6a327b186528d1a) Tobias Warneke *2023-12-26 23:15:57* + +**npe in memory leak verifier** + + +[63955](https://github.com/JSQLParser/JSqlParser/commit/639555315180cbf) Tobias Warneke *2023-12-26 23:01:20* + +**allow reinitializing of javacc semanticize** + + +[44274](https://github.com/JSQLParser/JSqlParser/commit/44274b252c21cd1) Tobias Warneke *2023-12-26 22:53:28* + +**Allowed to build JSqlParser on slower computers by increasing a fixed timeout. This should take machine power into account.** + + +[806d3](https://github.com/JSQLParser/JSqlParser/commit/806d3a39e8f093e) Tobias Warneke *2023-12-26 20:31:48* + +**upgraded some plugins** + + +[cff03](https://github.com/JSQLParser/JSqlParser/commit/cff03ca200c674c) Tobias Warneke *2023-12-26 12:59:38* + +**upgraded some plugins** + + +[256a1](https://github.com/JSQLParser/JSqlParser/commit/256a1eff904834b) Tobias Warneke *2023-12-25 23:53:18* + +**upgraded some plugins** + + +[b2bd0](https://github.com/JSQLParser/JSqlParser/commit/b2bd025b424e472) Tobias Warneke *2023-12-25 23:51:46* + +**corrected license header of some files** + + +[23ba3](https://github.com/JSQLParser/JSqlParser/commit/23ba326db05e863) Tobias Warneke *2023-12-25 23:39:37* + +**Update sphinx.yml** + + +[2974f](https://github.com/JSQLParser/JSqlParser/commit/2974f4d20e2d785) manticore-projects *2023-12-16 07:13:01* + +**Update sphinx.yml** + + +[a35fb](https://github.com/JSQLParser/JSqlParser/commit/a35fbe77b33a07b) manticore-projects *2023-12-16 04:42:01* + +**Update build.gradle** + + +[546b3](https://github.com/JSQLParser/JSqlParser/commit/546b3ee00e4c3f8) manticore-projects *2023-12-15 09:14:49* + +**Update build.gradle** + + +[48b3a](https://github.com/JSQLParser/JSqlParser/commit/48b3acbeef56b2d) manticore-projects *2023-12-15 09:11:51* + +**Closed #1814, mysql and mariadb can use `index type` before `ON` (#1918)** + + +[b0aff](https://github.com/JSQLParser/JSqlParser/commit/b0aff31314a8df4) jxnu-liguobin *2023-12-15 04:56:55* + +**Fix conflict (#1915)** + + +[2ae1d](https://github.com/JSQLParser/JSqlParser/commit/2ae1d53e56e45b2) jxnu-liguobin *2023-12-14 07:22:57* + +**Fix typo in migration.rst (#1888)** + +* Found a typo in the 4.7 migration document. Trivial PR. Please merge. + +[902e4](https://github.com/JSQLParser/JSqlParser/commit/902e4c46f783985) Ed Sabol *2023-11-10 03:05:39* + +**Unit tests support multi-os and higher versions of jdk (#1886)** + +* fix: tokenBlockPattern support \r\n or \r +* test: remove nashorn ignore annotation to support jdk11+ + +[97e92](https://github.com/JSQLParser/JSqlParser/commit/97e9229d15df7d6) human-user *2023-11-08 03:07:04* + +**Support for Nested With Clauses Added** + + +[59104](https://github.com/JSQLParser/JSqlParser/commit/59104fd96f29a2e) MathewJoseph31 *2023-09-12 12:01:59* + +**Support for Array Contains (&>) and ContainedBy (<&) operator added** + + +[727c7](https://github.com/JSQLParser/JSqlParser/commit/727c732fd217843) MathewJoseph31 *2023-09-12 12:01:20* + +**Support for postgres overlap operator && added, natural left/right/full outer joins added** + + +[6955c](https://github.com/JSQLParser/JSqlParser/commit/6955c4391e65a33) MathewJoseph31 *2023-09-12 12:01:15* + +**add support for index hints in Update statement for MySQL** + + +[9a67d](https://github.com/JSQLParser/JSqlParser/commit/9a67d1277a0bf80) joeqiao *2022-11-08 01:27:25* + +**added support for T-SQL left and right joins (*= and =*)** + + +[786c8](https://github.com/JSQLParser/JSqlParser/commit/786c8fc65858ff6) Nico *2019-01-29 11:11:07* + + +## jsqlparser-4.7 (2023-09-02) + +### Breaking changes + +- add support for INTERPRET function parsing (#1816) ([180ec](https://github.com/JSQLParser/JSqlParser/commit/180ec68cc9fa7eb) Matteo Sist) +- Remove `ItemsList`, `MultiExpressionList`, `Replace` ([14170](https://github.com/JSQLParser/JSqlParser/commit/141708eabc4f2ea) Andreas Reichel) +- Consolidate the `ExpressionList`, removing many redundant List alike Classes and Productions ([288b1](https://github.com/JSQLParser/JSqlParser/commit/288b177fe9c8a4c) Andreas Reichel) +- remove `SelectExpressionItem` in favor of `SelectItem` ([b9057](https://github.com/JSQLParser/JSqlParser/commit/b9057d2b75cd1d7) Andreas Reichel) +- ClickHouse `Select...` ``FINAL` modifier ([4b7f2](https://github.com/JSQLParser/JSqlParser/commit/4b7f21c54c24d04) Andreas Reichel) + +### Features + +- H2 BYTEA Values `X'01' '02'` ([54828](https://github.com/JSQLParser/JSqlParser/commit/54828a456a7f192) Andreas Reichel) +- BigQuery Except(..) Replace(..) syntax ([4b4ae](https://github.com/JSQLParser/JSqlParser/commit/4b4ae04f44ff18b) Andreas Reichel) +- implement a few missing expressions ([04128](https://github.com/JSQLParser/JSqlParser/commit/0412897f9ea809f) Andreas Reichel) +- SQL:2016 TABLESAMPLE clause ([4d8a5](https://github.com/JSQLParser/JSqlParser/commit/4d8a512191a4a1b) Andreas Reichel) +- add a method checking balanced brackets ([52df3](https://github.com/JSQLParser/JSqlParser/commit/52df32dd8ec2c10) Andreas Reichel) +- add support for INTERPRET function parsing (#1816) ([180ec](https://github.com/JSQLParser/JSqlParser/commit/180ec68cc9fa7eb) Matteo Sist) +- MySQL `NOT RLIKE`, `NOT REGEXP` expressions ([f1325](https://github.com/JSQLParser/JSqlParser/commit/f132547f56a1edd) Andreas Reichel) +- Postgres `NOTNULL` support ([386dc](https://github.com/JSQLParser/JSqlParser/commit/386dc7a0df98f1c) manticore-projects) +- `QUALIFY` clause ([75e4d](https://github.com/JSQLParser/JSqlParser/commit/75e4d30747a7e6e) Andreas Reichel) +- T-SQL `FOR ...` clause ([8027d](https://github.com/JSQLParser/JSqlParser/commit/8027dbf2cbf9163) Andreas Reichel) +- Quoted Identifiers can contain double-quotes (PostgreSQL) ([73c55](https://github.com/JSQLParser/JSqlParser/commit/73c55fda1ac6a42) Andreas Reichel) +- functions blocks, parenthesed JSON Expressions ([5263b](https://github.com/JSQLParser/JSqlParser/commit/5263b91f3e555b7) Andreas Reichel) +- functions blocks, parenthesed JSON Expressions ([e19dc](https://github.com/JSQLParser/JSqlParser/commit/e19dc0e081f741d) Andreas Reichel) +- parse CREATE TRIGGER as UnsupportedStatement ([64b03](https://github.com/JSQLParser/JSqlParser/commit/64b0331f772278b) Andreas Reichel) +- chaining JSON Expressions ([6ef5e](https://github.com/JSQLParser/JSqlParser/commit/6ef5e0b6ee06211) Andreas Reichel) +- Write API documentation to the WebSite via XMLDoclet ([c5366](https://github.com/JSQLParser/JSqlParser/commit/c53667f8eff30e3) Andreas Reichel) +- `MEMBER OF` condition as shown at https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of ([6e7a7](https://github.com/JSQLParser/JSqlParser/commit/6e7a78dfc563749) Andreas Reichel) +- access Elements of Array Columns ([09a70](https://github.com/JSQLParser/JSqlParser/commit/09a70a499121792) Andreas Reichel) +- JdbcNamedParameter allows "&" (instead of ":") ([c07a4](https://github.com/JSQLParser/JSqlParser/commit/c07a43b3c128a5d) Andreas Reichel) +- Consolidate the `ExpressionList`, removing many redundant List alike Classes and Productions ([288b1](https://github.com/JSQLParser/JSqlParser/commit/288b177fe9c8a4c) Andreas Reichel) +- ClickHouse `LIMIT ... BY ...` clause ([4d5e2](https://github.com/JSQLParser/JSqlParser/commit/4d5e26d3febe686) Andreas Reichel) +- implement SQL:2016 Convert() and Trim() ([3a27a](https://github.com/JSQLParser/JSqlParser/commit/3a27a9dd4add700) Andreas Reichel) +- Switch off contradicting `JOIN` qualifiers, when setting a qualifier ([b6ea8](https://github.com/JSQLParser/JSqlParser/commit/b6ea8b162450545) Andreas Reichel) +- Test if a JOIN is an INNER JOIN according to the SQL:2016 ([6281b](https://github.com/JSQLParser/JSqlParser/commit/6281b07a543b088) Andreas Reichel) +- ClickHouse `Select...` ``FINAL` modifier ([4b7f2](https://github.com/JSQLParser/JSqlParser/commit/4b7f21c54c24d04) Andreas Reichel) +- Multi-Part Names for Variables and Parameters ([9da7a](https://github.com/JSQLParser/JSqlParser/commit/9da7a06ebe9b036) Andreas Reichel) +- Oracle `HAVING` before `GROUP BY` ([4efb9](https://github.com/JSQLParser/JSqlParser/commit/4efb99f1510ad16) Andreas Reichel) +- Lateral View ([8a1bd](https://github.com/JSQLParser/JSqlParser/commit/8a1bdeccbadb04f) Andreas Reichel) +- FETCH uses EXPRESSION ([0979b](https://github.com/JSQLParser/JSqlParser/commit/0979b2e5ea76b8c) Andreas Reichel) +- Support more Statement Separators ([b0814](https://github.com/JSQLParser/JSqlParser/commit/b08148414bd8f30) Andreas Reichel) +- CREATE VIEW ... REFRESH AUTO... ([1c8d8](https://github.com/JSQLParser/JSqlParser/commit/1c8d8daf48ebac1) Andreas Reichel) +- Oracle Alternative Quoting ([c57c4](https://github.com/JSQLParser/JSqlParser/commit/c57c427032c91d0) Andreas Reichel) +- make important Classes Serializable ([b94b2](https://github.com/JSQLParser/JSqlParser/commit/b94b2cc6a8f8c7d) Andreas Reichel) + +### Bug Fixes + +- ExpressionList of Expressions in `Values` ([994e6](https://github.com/JSQLParser/JSqlParser/commit/994e6c63d065a48) Andreas Reichel) +- check for NULL before iterating ([beb68](https://github.com/JSQLParser/JSqlParser/commit/beb68d55239da97) Andreas Reichel) +- Backslash escaped single quote `'\''` ([a2975](https://github.com/JSQLParser/JSqlParser/commit/a29754341adeffc) Andreas Reichel) +- `INSERT` must use simple Column Names only ([420d7](https://github.com/JSQLParser/JSqlParser/commit/420d7d834760f14) Andreas Reichel) +- SPHINX modules and themes ([6f277](https://github.com/JSQLParser/JSqlParser/commit/6f277654b9344ec) Andreas Reichel) +- expose IntervalExpression attributes and use DeParser ([b6fab](https://github.com/JSQLParser/JSqlParser/commit/b6fab2a484e0b47) Andreas Reichel) +- throw the specific exception ([cb960](https://github.com/JSQLParser/JSqlParser/commit/cb960a35647a19a) Andreas Reichel) +- Complex Parsing Approach ([4f048](https://github.com/JSQLParser/JSqlParser/commit/4f0488ccb4611f0) Andreas Reichel) +- issue #1789 ([32ec5](https://github.com/JSQLParser/JSqlParser/commit/32ec56114c1fbc4) Andreas Reichel) +- issue #1789 ([d20c8](https://github.com/JSQLParser/JSqlParser/commit/d20c8e94de64e2a) Andreas Reichel) +- issue #1791 ([88d1b](https://github.com/JSQLParser/JSqlParser/commit/88d1b62f0038a9a) Andreas Reichel) +- Java Version 8 ([7cecd](https://github.com/JSQLParser/JSqlParser/commit/7cecd293cf4e0ea) Andreas Reichel) +- find the correct position when field belongs to an internal class ([21389](https://github.com/JSQLParser/JSqlParser/commit/21389b712995674) Andreas Reichel) +- Remove tests for `()`, since `ParenthesedExpressionList` will catch those too ([905ef](https://github.com/JSQLParser/JSqlParser/commit/905ef6512d592d6) Andreas Reichel) +- assign Enum case insensitive ([fc577](https://github.com/JSQLParser/JSqlParser/commit/fc577caa4146878) Andreas Reichel) + +### Other changes + +**** + + +[d45f2](https://github.com/JSQLParser/JSqlParser/commit/d45f29ef42a6859) Tobias Warneke *2023-09-01 22:07:49* + +**Fixing a problem with an OP_CONCAT in WhenExpression (#1837)** + +* fix: Concatenation in inner ELSE statement (Second level of Case Expression) +* fix: broken tests +* fix: Delete lookahead(3) + +[f05cb](https://github.com/JSQLParser/JSqlParser/commit/f05cb7ff4aa46c5) amigalev *2023-08-20 04:43:30* + +**Update Gradle JavaCC parser to latest version (3.0.0) (#1843)** + + +[c59a0](https://github.com/JSQLParser/JSqlParser/commit/c59a088dfaee75a) Zbynek Konecny *2023-08-05 22:14:21* + +**Update sql-parser-error.md** + + +[41d70](https://github.com/JSQLParser/JSqlParser/commit/41d705bb1036b34) manticore-projects *2023-07-26 00:37:51* + +**Update sql-parser-error.md** + + +[812c6](https://github.com/JSQLParser/JSqlParser/commit/812c6cae3a8438b) manticore-projects *2023-07-26 00:37:14* + +**Update sql-parser-error.md** + + +[b34d3](https://github.com/JSQLParser/JSqlParser/commit/b34d3c88a881c0f) manticore-projects *2023-07-25 00:09:05* + +**Update sphinx.yml** + +* fix the FURO theme + +[51cc4](https://github.com/JSQLParser/JSqlParser/commit/51cc444ff98ad1d) manticore-projects *2023-06-01 02:49:23* + +**Create gradle.yml** + + +[be7fc](https://github.com/JSQLParser/JSqlParser/commit/be7fc53cff240be) manticore-projects *2023-05-18 10:16:14* + +**Update sphinx.yml** + + +[11323](https://github.com/JSQLParser/JSqlParser/commit/11323388ab4abfd) manticore-projects *2023-05-14 13:10:16* + +**** + + +[0aa8a](https://github.com/JSQLParser/JSqlParser/commit/0aa8a629b9cecc2) Tobias Warneke *2023-04-27 21:18:29* + +**Fix #1758: Use long for Feature.timeOut (#1759)** + +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[3314e](https://github.com/JSQLParser/JSqlParser/commit/3314edf0ea17772) Tomasz Zarna *2023-04-27 20:30:31* + +**Ignoring unnecessarily generated jacoco report (#1762)** + +* Ignoring unnecessarily generated jacoco report +* Ignoring unnecessarily generated by pmd plugin +* --------- +* Co-authored-by: other <other@ECE-A55006.austin.utexas.edu> +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[1bbb1](https://github.com/JSQLParser/JSqlParser/commit/1bbb1443d84684c) optimizing-ci-builds *2023-04-27 19:50:42* + +**Ignoring unnecessarily generated by pmd plugin (#1763)** + +* Co-authored-by: other <other@ECE-A55006.austin.utexas.edu> + +[52648](https://github.com/JSQLParser/JSqlParser/commit/52648277e69fa07) optimizing-ci-builds *2023-04-27 19:49:15* + +**Refactor Parenthesed SelectBody and FromItem (#1754)** + +* Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH +* Support parsing create view statements in Redshift with AUTO REFRESH +* option. +* Reduce cyclomatic complexity in CreateView.toString +* Extract adding the force option into a dedicated method resulting in the +* cyclomatic complexity reduction of the CreateView.toString method. +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Sphinx Documentation +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser +* doc: request for `Conventional Commit` messages +* feat: make important Classes Serializable +* Implement Serializable for persisting via ObjectOutputStream +* chore: Make Serializable +* doc: Better integration of the RR diagrams +* - apply neutral Sphinx theme +* - insert the RR diagrams into the sphinx sources +* - better documentation on Gradle dependencies +* - link GitHub repository +* Merge +* feat: Oracle Alternative Quoting +* - add support for Oracle Alternative Quoting e.g. `q'(...)'` +* - fixes #1718 +* - add a Logo and FavIcon to the Website +* - document recent changes on Quoting/Escaping +* - add an example on building SQL from Java +* - rework the README.md, promote the Website +* - add Spotless Formatter, using Google Java Style (with Tab=4 Spaces) +* style: Appease PMD/Codacy +* doc: fix the issue template +* - fix the issue template +* - fix the -SNAPSHOT version number +* Update issue templates +* Update issue templates +* feat: Support more Statement Separators +* - `GO` +* - Slash `/` +* - Two empty lines +* feat: FETCH uses EXPRESSION +* - `FETCH` uses `EXPRESSION` instead of SimpleJDBCParameter only +* - Visit/Accept `FETCH` `EXPRESSION` instead of `append` to String +* - Visit/Accept `OFFSET` `EXPRESSION` instead of `append` to String +* - Gradle: remove obsolete/incompatible `jvmArgs` from Test() +* style: apply Spotless +* test: commit missing test +* fix: JSon Operator can use Simple Function +* Supports `Function() ->> Literal` (although `Function()` would not allow Nested Expression Parameters) +* fixes #1571 +* style: Reformat changed files and headers +* style: Remove unused variable +* feat: Add support for Hangul "\uAC00"-"\uD7A3" +* fixes #1747 +* style: expose `SetStatement` key-value list +* fixes #1746 +* style: Appease PMD/Codacy +* feat: `ConflictTarget` allows multiple `IndexColumnNames` +* fixes #1749 +* fixes #1633 +* fixes #955 +* doc: fix reference in the Java Doc +* build: better Upload Groovy Task +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - First properly working version +* - Work in progress, 13 tests failing +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - delete unneeded ParenthesedJoin +* - rename ParenthesisFromItem into ParenthesedFromItem +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - fix `NULLS FIRST` and `NULLS LAST` +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - fix Oracle Hints +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - parse `SetOperation` only after a (first plain) SelectBody has found, this fixes the performance issue +* - one more special Oracle Test succeeds +* - 5 remaining test failures +* feat: ParenthesedSelectBody and ParenthesedFromItem +* - extract `OrderByElements` into `SelectBody` +* - one more special Oracle Test succeeds +* - all tests succeed +* style: Appease PMD/Codacy +* style: Appease PMD/Codacy +* feat: Refactor SelectBody implementations +* - `SelectBody` implements `FromItem` +* - get rid of `SubSelect` and `SpecialSubSelect` +* - `Merge` can use `FromItem` instead of `SubSelect` or `Table` +* - `LateralSubSelect` extends `ParenthesedSelectBody` directly +* - Simplify the `Select` statement, although it is still redundant since `SelectBody` also could implement `Statement` directly +* - `WithItem` can use `SelectBody` directly, which allows for nested `WithItems` +* BREAKING-CHANGE: Lots of redundant methods and intermediate removed +* feat: Refactor SelectBody implementations +* - `SelectBody` implements `Statement` and so makes `Select` redundant +* - get rid of `ValuesList` +* - refactor `ValuesStatement` into `Values` which just implements `SelectBody` (and becomes a `Statement` and a `FromItem`), move to `select` package +* BREAKING-CHANGE: Lots of redundant methods and intermediate removed +* style: Code cleanup +* - remove 3 unused/obsolete productions +* - appease PMD/Codacy +* feat: Merge `SelectBody` into `Select` Statement +* - former `SelectBody` implements `Statement` and so becomes `Select` +* - this reduces the AST by 1 hierarchy level +* style: Remove unused import +* test: @Disabled invalid Test +* style: Appease PMD/Codacy +* test: Add a SubSelect Parsing Test +* --------- +* Co-authored-by: zaza <tzarna@gmail.com> + +[a312d](https://github.com/JSQLParser/JSqlParser/commit/a312dcdc2d618f1) manticore-projects *2023-04-27 19:38:24* + +**** + + +[c1c92](https://github.com/JSQLParser/JSqlParser/commit/c1c92ade94ebe60) Tobias Warneke *2023-04-01 19:54:09* + +**Assorted Fixes #7 (#1745)** + +* Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH +* Support parsing create view statements in Redshift with AUTO REFRESH +* option. +* Reduce cyclomatic complexity in CreateView.toString +* Extract adding the force option into a dedicated method resulting in the +* cyclomatic complexity reduction of the CreateView.toString method. +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Sphinx Documentation +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser +* doc: request for `Conventional Commit` messages +* feat: make important Classes Serializable +* Implement Serializable for persisting via ObjectOutputStream +* chore: Make Serializable +* doc: Better integration of the RR diagrams +* - apply neutral Sphinx theme +* - insert the RR diagrams into the sphinx sources +* - better documentation on Gradle dependencies +* - link GitHub repository +* Merge +* feat: Oracle Alternative Quoting +* - add support for Oracle Alternative Quoting e.g. `q'(...)'` +* - fixes #1718 +* - add a Logo and FavIcon to the Website +* - document recent changes on Quoting/Escaping +* - add an example on building SQL from Java +* - rework the README.md, promote the Website +* - add Spotless Formatter, using Google Java Style (with Tab=4 Spaces) +* style: Appease PMD/Codacy +* doc: fix the issue template +* - fix the issue template +* - fix the -SNAPSHOT version number +* Update issue templates +* Update issue templates +* feat: Support more Statement Separators +* - `GO` +* - Slash `/` +* - Two empty lines +* feat: FETCH uses EXPRESSION +* - `FETCH` uses `EXPRESSION` instead of SimpleJDBCParameter only +* - Visit/Accept `FETCH` `EXPRESSION` instead of `append` to String +* - Visit/Accept `OFFSET` `EXPRESSION` instead of `append` to String +* - Gradle: remove obsolete/incompatible `jvmArgs` from Test() +* style: apply Spotless +* test: commit missing test +* fix: JSon Operator can use Simple Function +* Supports `Function() ->> Literal` (although `Function()` would not allow Nested Expression Parameters) +* fixes #1571 +* style: Reformat changed files and headers +* style: Remove unused variable +* feat: Add support for Hangul "\uAC00"-"\uD7A3" +* fixes #1747 +* style: expose `SetStatement` key-value list +* fixes #1746 +* style: Appease PMD/Codacy +* feat: `ConflictTarget` allows multiple `IndexColumnNames` +* fixes #1749 +* fixes #1633 +* fixes #955 +* doc: fix reference in the Java Doc +* build: better Upload Groovy Task +* --------- +* Co-authored-by: zaza <tzarna@gmail.com> + +[31ef1](https://github.com/JSQLParser/JSqlParser/commit/31ef1aaf23e2917) manticore-projects *2023-03-21 22:04:58* + +**disable xml report (#1748)** + +* Co-authored-by: other <other@ECE-A55006.austin.utexas.edu> + +[476d9](https://github.com/JSQLParser/JSqlParser/commit/476d96965492131) optimizing-ci-builds *2023-03-21 21:58:25* + +**Assorted Fixes #6 (#1740)** + +* Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH +* Support parsing create view statements in Redshift with AUTO REFRESH +* option. +* Reduce cyclomatic complexity in CreateView.toString +* Extract adding the force option into a dedicated method resulting in the +* cyclomatic complexity reduction of the CreateView.toString method. +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Sphinx Documentation +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser +* doc: request for `Conventional Commit` messages +* feat: make important Classes Serializable +* Implement Serializable for persisting via ObjectOutputStream +* chore: Make Serializable +* doc: Better integration of the RR diagrams +* - apply neutral Sphinx theme +* - insert the RR diagrams into the sphinx sources +* - better documentation on Gradle dependencies +* - link GitHub repository +* Merge +* feat: Oracle Alternative Quoting +* - add support for Oracle Alternative Quoting e.g. `q'(...)'` +* - fixes #1718 +* - add a Logo and FavIcon to the Website +* - document recent changes on Quoting/Escaping +* - add an example on building SQL from Java +* - rework the README.md, promote the Website +* - add Spotless Formatter, using Google Java Style (with Tab=4 Spaces) +* style: Appease PMD/Codacy +* doc: fix the issue template +* - fix the issue template +* - fix the -SNAPSHOT version number +* Update issue templates +* Update issue templates +* feat: Support more Statement Separators +* - `GO` +* - Slash `/` +* - Two empty lines +* feat: FETCH uses EXPRESSION +* - `FETCH` uses `EXPRESSION` instead of SimpleJDBCParameter only +* - Visit/Accept `FETCH` `EXPRESSION` instead of `append` to String +* - Visit/Accept `OFFSET` `EXPRESSION` instead of `append` to String +* - Gradle: remove obsolete/incompatible `jvmArgs` from Test() +* style: apply Spotless +* test: commit missing test +* feat: Unicode CJK Unified Ideographs (Unicode block) +* fixes #1741 +* feat: Unicode CJK Unified Ideographs (Unicode block) +* fixes #1741 +* feat: Functions with nested Attributes +* Supports `SELECT schemaName.f1(arguments).f2(arguments).f3.f4` and similar constructs +* fixes #1742 +* fixes #1050 +* --------- +* Co-authored-by: zaza <tzarna@gmail.com> + +[adeed](https://github.com/JSQLParser/JSqlParser/commit/adeed5359c65b8f) manticore-projects *2023-03-09 21:22:40* + +**version 4.7-SNAPSHOT** + + +[74570](https://github.com/JSQLParser/JSqlParser/commit/745701bfb90a233) Tobias Warneke *2023-02-23 21:41:03* + +**Update issue templates** + + +[4aeaf](https://github.com/JSQLParser/JSqlParser/commit/4aeafbc68f0525c) manticore-projects *2023-02-01 01:37:53* + +**Update issue templates** + + +[46314](https://github.com/JSQLParser/JSqlParser/commit/46314c41eb06957) manticore-projects *2023-02-01 01:24:35* + +**Sphinx Documentation** + +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser + +[2ef66](https://github.com/JSQLParser/JSqlParser/commit/2ef6637afffa943) Andreas Reichel *2023-01-21 04:06:00* + +**Define Reserved Keywords explicitly** + +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests + +[f49e8](https://github.com/JSQLParser/JSqlParser/commit/f49e828fc9c5f2f) Andreas Reichel *2023-01-21 04:05:51* + +**Adjust Gradle to JUnit 5** + +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 + +[e960a](https://github.com/JSQLParser/JSqlParser/commit/e960a35e591ce07) Andreas Reichel *2023-01-21 04:05:51* + +**Enhanced Keywords** + +* Add Keywords and document, which keywords are allowed for what purpose + +[b5321](https://github.com/JSQLParser/JSqlParser/commit/b5321d6e8bac588) Andreas Reichel *2023-01-21 04:05:51* + +**Remove unused imports** + + +[a016b](https://github.com/JSQLParser/JSqlParser/commit/a016be0c7f8a46f) Andreas Reichel *2023-01-21 04:05:51* + +**Fix test resources** + + +[86f33](https://github.com/JSQLParser/JSqlParser/commit/86f337dbafd10ab) Andreas Reichel *2023-01-21 04:05:51* + +**Do not mark SpeedTest for concurrent execution** + + +[67f79](https://github.com/JSQLParser/JSqlParser/commit/67f7951a048a05d) Andreas Reichel *2023-01-21 04:05:51* + +**Fix incorrect tests** + + +[5fae2](https://github.com/JSQLParser/JSqlParser/commit/5fae2f5984c3b39) Andreas Reichel *2023-01-21 04:05:51* + +**Remove unused imports** + + +[3ba54](https://github.com/JSQLParser/JSqlParser/commit/3ba5410bf052091) Andreas Reichel *2023-01-21 04:05:51* + +**Adjust Gradle to JUnit 5** + +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 + +[2d51a](https://github.com/JSQLParser/JSqlParser/commit/2d51a82d3e9e51c) Andreas Reichel *2023-01-21 04:05:51* + +**Do not mark SpeedTest for concurrent execution** + + +[232af](https://github.com/JSQLParser/JSqlParser/commit/232aff6873f24f9) Andreas Reichel *2023-01-21 04:05:51* + +**Reduce cyclomatic complexity in CreateView.toString** + +* Extract adding the force option into a dedicated method resulting in the +* cyclomatic complexity reduction of the CreateView.toString method. + +[ea447](https://github.com/JSQLParser/JSqlParser/commit/ea4477bb775ebdb) zaza *2023-01-08 20:43:40* + +**Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH** + +* Support parsing create view statements in Redshift with AUTO REFRESH +* option. + +[74715](https://github.com/JSQLParser/JSqlParser/commit/747152a9fc1bfd1) zaza *2022-12-11 20:03:52* + + +## jsqlparser-4.6 (2023-02-23) + +### Bug Fixes + +- add missing public Getter (#1632) ([d2212](https://github.com/JSQLParser/JSqlParser/commit/d2212776ac5eb83) manticore-projects) + +### Other changes + +**actualized release plugin** + + +[9911a](https://github.com/JSQLParser/JSqlParser/commit/9911ad7a990356f) Tobias Warneke *2023-02-23 21:17:52* + +**actualized release plugin** + + +[0b2c3](https://github.com/JSQLParser/JSqlParser/commit/0b2c33b29928ec4) Tobias Warneke *2023-02-23 21:16:43* + +**** + + +[b07f7](https://github.com/JSQLParser/JSqlParser/commit/b07f791b27c3ee4) Tobias Warneke *2023-02-23 19:50:39* + +**Update build.gradle** + + +[35233](https://github.com/JSQLParser/JSqlParser/commit/35233882aaffb0e) Tobias *2023-02-17 20:20:25* + +**Update README.md** + + +[0b092](https://github.com/JSQLParser/JSqlParser/commit/0b09229a3d92547) Tobias *2023-02-17 16:27:41* + +**Oracle Alternative Quoting (#1722)** + +* Fixes #1684: Support CREATE MATERIALIZED VIEW with AUTO REFRESH +* Support parsing create view statements in Redshift with AUTO REFRESH +* option. +* Reduce cyclomatic complexity in CreateView.toString +* Extract adding the force option into a dedicated method resulting in the +* cyclomatic complexity reduction of the CreateView.toString method. +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Sphinx Documentation +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser +* doc: request for `Conventional Commit` messages +* feat: make important Classes Serializable +* Implement Serializable for persisting via ObjectOutputStream +* chore: Make Serializable +* doc: Better integration of the RR diagrams +* - apply neutral Sphinx theme +* - insert the RR diagrams into the sphinx sources +* - better documentation on Gradle dependencies +* - link GitHub repository +* Merge +* feat: Oracle Alternative Quoting +* - add support for Oracle Alternative Quoting e.g. `q'(...)'` +* - fixes #1718 +* - add a Logo and FavIcon to the Website +* - document recent changes on Quoting/Escaping +* - add an example on building SQL from Java +* - rework the README.md, promote the Website +* - add Spotless Formatter, using Google Java Style (with Tab=4 Spaces) +* style: Appease PMD/Codacy +* doc: fix the issue template +* - fix the issue template +* - fix the -SNAPSHOT version number +* Update issue templates +* Update issue templates +* feat: Support more Statement Separators +* - `GO` +* - Slash `/` +* - Two empty lines +* --------- +* Co-authored-by: zaza <tzarna@gmail.com> + +[e71e5](https://github.com/JSQLParser/JSqlParser/commit/e71e57dfe4b377c) manticore-projects *2023-02-07 20:18:52* + +**Issue1673 case within brackets (#1675)** + +* fix: add missing public Getter +* Add public Getter for `updateSets` +* Fixes #1630 +* fix: Case within brackets +* fixes #1673 + +[2ced7](https://github.com/JSQLParser/JSqlParser/commit/2ced7ded930f8b0) manticore-projects *2023-01-31 20:56:01* + +**Added support for SHOW INDEX from table (#1704)** + +* Added support for SHOW INDEX from table +* Added * import +* fix for javadoc +* added <doclint>none</doclint> + +[a2618](https://github.com/JSQLParser/JSqlParser/commit/a2618321135d517) Jayant Kumar Yadav *2023-01-31 20:54:05* + +**** + + +[d33f6](https://github.com/JSQLParser/JSqlParser/commit/d33f6f5a658751d) Tobias Warneke *2023-01-22 15:43:07* + +**Sphinx Website (#1624)** + +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Keyword test adopt JUnit5 +* Update keywords +* CheckStyle sanitation of method names +* Merge Master +* Add Jupiter Parameters dependency again +* Automate the `updateKeywords` Step +* Update PMD and rules +* Rewrite test expected to fail +* Appease Codacy +* Remove broken rule warning about perfectly fine switch-case statements +* Force Changes +* Fix Merge Issues +* Read Tokens directly from the Grammar File without invoking JTREE +* - read Tokens per REGEX Matcher +* - move Reserved Keywords from Grammar into ParserKeywordsUtils +* - adjust the Tests +* Appease PMD/Codacy +* Extract the Keywords from the Grammar by using JTRee (instead of Regex) +* Add some tests to ensure, that all Keywords or found +* Appease Codacy/PMD +* Separate UpdateKeywords Task again +* Including it into compileJavacc won't work since it depends on compiling the ParserKeywordUtils.java +* Single file compilation did not work +* Clean-up the imports +* Add JavaCC dependency to Maven for building ParserKeywordsUtils +* Add JavaCC dependency to Maven for building ParserKeywordsUtils +* Merge Upstream +* Merge Master +* Fixes broken PR #1524 and Commit fb6e950ce0e62ebcd7a44ba9eea679da2b04b2ed +* Add AST Visualization +* Show the Statement's Java Objects in a tree hierarchy +* Sphinx Documentation +* Update the MANTICORE Sphinx Theme, but ignore it in GIT +* Add the content to the Sphinx sites +* Add a Gradle function to derive Stable and Snapshot version from GIT Tags +* Add a Gradle GIT change task +* Add a Gradle sphinx task +* Add a special Test case for illustrating the use of JSQLParser +* test: Document an additional Special Oracle test success +* doc: ignore the autogenerated changelog.rst in GIT +* build: temporarily reduce the Code Coverage requirements +* Temporarily reduce the Coverage checks regarding Minimum Coverage and Maximum Missed Lines in order to get the Keywords PR accepted. We should do a major Code cleanup afterwards. +* build: Clean-up the Gradle Build +* Prefix the Sphinx Prolog Variables with JSQLPARSER in order to allow for build the Main Website for various projects +* Remove some redundant version requests for PMD, CheckStyle and friends +* Remove JUnit-4 dependency and add HarmCrest +* Complete the PUBLISHING task +* doc: Explain the ``updateKeywords`` Gradle Task +* build: Un-escape the Unicode on the changelog file +* build: Un-escape the Unicode on the changelog file +* doc: Cleanup +* Unescape unicode characters from Git Changelog +* Remove obsolete code from Sphinx' conf.py +* doc: Properly un-escape the Git Commit message +* doc: request for `Conventional Commit` messages +* doc: correctly refer to `RelObjectNameWithoutValue()` +* build: upload the built files via Excec/SFTP +* doc: Add an example on Token White-listing +* doc: write the correct Git Repository +* doc: pronounce the OVERLAPS example more +* feat: make important Classes Serializable +* Implement Serializable for persisting via ObjectOutputStream +* doc: Add the "How to Use" java code +* chore: Make Serializable +* fix: Non-serializable field in serializable class +* build: various fixes to the Maven build file +* add the Keywords Documentation file to the task +* exclude the Sphinx files from the license header plugin +* fix the JavaDoc plugin options +* build: add the Keywords Documentation file to the task +* doc: add a page about actually Reserved Keywords +* build: avoid PMD/Codacy for Sphinx Documentation +* update Changelog +* build: Add Sphinx GitHub Action +* Add a GitHub Action, which will +* - Install Sphinx and Extensions +* - Install Gradle Wrapper +* - Run Gradle Wrapper Task `sphinx` +* - Deploy the generated static HTML site to GH Pages +* fix: fix a merge error, brackets +* fix: remove JavaCC dependency +* Parse Tokens via Regex +* Move JavaCC Token Parser into the KeywordsTest +* Make JavaCC a Test Dependency only +* doc: Fix Maven Artifact Version +* style: Avoid throwing raw exception types. +* style: Avoid throwing raw exception types. +* doc: Better integration of the RR diagrams +* - apply neutral Sphinx theme +* - insert the RR diagrams into the sphinx sources +* - better documentation on Gradle dependencies +* - link GitHub repository +* build: gradle, execute all Checks after Test +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[be8e7](https://github.com/JSQLParser/JSqlParser/commit/be8e7a8a1d77184) manticore-projects *2023-01-20 21:45:35* + +**Assorted Fixes #5 (#1715)** + +* refactor: Merge REPLACE into UPSERT +* fixes #1706 +* feat: `DROP TEMPORARY TABLE ...` +* fixes #1712 +* build: PMD compliance +* ci: Merge master +* feat: Configurable backslash `\` escaping +* - Enables `\` as escape character in String Literals (beside SQL:2016 compliant `'`) +* - Default is OFF (since its not SQL:2016 compliant) +* - Activate per Parser Feature +* - Fixes #1638 +* - Fixes #1209 +* - Fixes #1173 +* - Fixes #1172 +* - Fixes #832 +* - Fixes #827 +* - Fixes #578 +* BREAKING-CHANGE: Backslash Escaping needs to be activated explicitly or else Backslash won't work as Escape Character. +* style: Checkstyle +* style: remove dead code +* style: PMD compliance +* style: Checkstyle, unused import +* feat: allow `S_CHAR_LITERAL` to break lines +* - fixes #875 + +[a00d7](https://github.com/JSQLParser/JSqlParser/commit/a00d77a100bfab7) manticore-projects *2023-01-20 21:32:20* + +**Support DROP MATERIALIZED VIEW statements (#1711)** + + +[1af68](https://github.com/JSQLParser/JSqlParser/commit/1af682d436055ad) Tomasz Zarna *2023-01-12 21:37:42* + +**corrected readme** + + +[4dfd2](https://github.com/JSQLParser/JSqlParser/commit/4dfd2e43fcdd3ab) Tobias Warneke *2023-01-04 21:07:17* + +**Update README.md** + +* lgtm removed + +[954b8](https://github.com/JSQLParser/JSqlParser/commit/954b8dd2e760a01) Tobias *2022-12-27 10:34:18* + +**Fix #1686: add support for creating views with "IF NOT EXISTS" clause (#1690)** + + +[0f34f](https://github.com/JSQLParser/JSqlParser/commit/0f34f5bc647365d) Tomasz Zarna *2022-12-22 21:52:35* + +**Assorted Fixes #4 (#1676)** + +* support clickhouse global keyword in join +* fix: add missing public Getter +* Add public Getter for `updateSets` +* Fixes #1630 +* feat: Clickhouse GLOBAL JOIN +* All credits to @julianzlzhang +* fixes #1615 +* fixes #1535 +* feat: IF/ELSE statements supports Block +* Make `If... Else...` statements work with Blocks +* Make `Statement()` production work with `Block()` +* Rewrite the `Block()` related Unit Tests +* fixes #1682 +* fix: Revert unintended changes to the Special Oracle Tests +* fix: `SET` statement supports `UserVariable` +* Make `SetStatement` parse Objects instead of Names only +* Add Grammar to accept `UserVariable` (e.g. "set @Flag = 1") +* Add Test Case for `UserVariable` +* fixes #1682 +* feat: Google Spanner Support +* Replaces PR #1415, all credit goes to @s13o +* Re-arranged some recently added Tokens in alphabetical order +* Update Keywords +* fix: fix JSonExpression, accept Expressions +* Make JSonExpression accept Expressions +* Add Testcase +* Expose Idents() and Operators() +* Fixes #1696 +* test: add Test for Issue #1237 +* Co-authored-by: Zhang Zhongliang <zhangzhongliang@xiaomi.com> + +[8d9db](https://github.com/JSQLParser/JSqlParser/commit/8d9db7052c3aeb5) manticore-projects *2022-12-22 21:17:55* + +**Fixed download war script in the renderRR task (#1659)** + +* Co-authored-by: Hai Chang <haichang@microsoft.com> + +[08a92](https://github.com/JSQLParser/JSqlParser/commit/08a92fcd7b4f7f2) haha1903 *2022-12-10 09:23:53* + +**Assorted fixes (#1666)** + +* fix: add missing public Getter +* Add public Getter for `updateSets` +* Fixes #1630 +* feat: LISTAGG() with OVER() clause +* fixes issue #1652 +* fixes 3 more Special Oracle Tests +* fix: White-list CURRENT_DATE and CURRENT_TIMESTAMP tokens +* allows CURRENT_DATE(3) and CURRENT_TIMESTAMP(3) as regular functions +* fixes #1507 +* fixes #1607 +* feat: Deparser for Expression Lists +* Visit each Expression of a List instead ExpressionList.toString() +* fixes #1608 +* fix: Lookahead needed + +[bff26](https://github.com/JSQLParser/JSqlParser/commit/bff268a7c699947) manticore-projects *2022-11-20 10:06:01* + +**Fix parsing statements with multidimensional array PR2 (#1665)** + +* Fix parsing statements with multidimensional array +* fix: Whitelist LOCKED keyword +* Co-authored-by: Andrei Lisouski <alisousk@akamai.com> + +[e1865](https://github.com/JSQLParser/JSqlParser/commit/e186588f044753f) manticore-projects *2022-11-20 09:59:26* + +**removed disabled from Keyword tests and imports** + + +[af6c2](https://github.com/JSQLParser/JSqlParser/commit/af6c2702c8a505c) Tobias Warneke *2022-11-02 23:02:38* + +**removed disabled from Keyword tests** + + +[89a9a](https://github.com/JSQLParser/JSqlParser/commit/89a9a575fac1ba8) Tobias Warneke *2022-11-02 22:58:19* + +**** + + +[8a018](https://github.com/JSQLParser/JSqlParser/commit/8a0183311b01d2d) Tobias Warneke *2022-10-28 22:30:25* + +**** + + +[67de4](https://github.com/JSQLParser/JSqlParser/commit/67de469e585060f) Tobias Warneke *2022-10-25 23:26:28* + +**Enhanced Keywords (#1382)** + +* Enhanced Keywords +* Add Keywords and document, which keywords are allowed for what purpose +* Fix incorrect tests +* Define Reserved Keywords explicitly +* Derive All Keywords from Grammar directly +* Generate production for Object Names (semi-) automatically +* Add parametrized Keyword Tests +* Fix test resources +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Keyword test adopt JUnit5 +* Update keywords +* CheckStyle sanitation of method names +* Merge Master +* Add Jupiter Parameters dependency again +* Automate the `updateKeywords` Step +* Update PMD and rules +* Rewrite test expected to fail +* Appease Codacy +* Remove broken rule warning about perfectly fine switch-case statements +* Force Changes +* Fix Merge Issues +* Read Tokens directly from the Grammar File without invoking JTREE +* - read Tokens per REGEX Matcher +* - move Reserved Keywords from Grammar into ParserKeywordsUtils +* - adjust the Tests +* Appease PMD/Codacy +* Extract the Keywords from the Grammar by using JTRee (instead of Regex) +* Add some tests to ensure, that all Keywords or found +* Appease Codacy/PMD +* Separate UpdateKeywords Task again +* Including it into compileJavacc won't work since it depends on compiling the ParserKeywordUtils.java +* Single file compilation did not work +* Clean-up the imports +* Add JavaCC dependency to Maven for building ParserKeywordsUtils +* Add JavaCC dependency to Maven for building ParserKeywordsUtils +* Merge Upstream +* Merge Master +* Fixes broken PR #1524 and Commit fb6e950ce0e62ebcd7a44ba9eea679da2b04b2ed +* Add AST Visualization +* Show the Statement's Java Objects in a tree hierarchy +* build: temporarily reduce the Code Coverage requirements +* Temporarily reduce the Coverage checks regarding Minimum Coverage and Maximum Missed Lines in order to get the Keywords PR accepted. We should do a major Code cleanup afterwards. +* build: JSQLParser is a build dependency +* chore: Update keywords +* feat: add line count to output + +[4863e](https://github.com/JSQLParser/JSqlParser/commit/4863eb5a8e30a5d) manticore-projects *2022-10-25 23:15:32* + +**#1610 Support for SKIP LOCKED tokens on SELECT statements (#1649)** + +* Co-authored-by: Lucas Dillmann <lucas.dillmann@totvs.com.br> + +[e6d50](https://github.com/JSQLParser/JSqlParser/commit/e6d50f756e99846) Lucas Dillmann *2022-10-25 22:59:09* + +**Assorted fixes (#1646)** + +* fix: add missing public Getter +* Add public Getter for `updateSets` +* Fixes #1630 +* fix: Assorted Fixes +* SelectExpressionItem with Function and Complex Parameters +* Tables with Oracle DB Links +* Make Table Name Parts accessible +* Fixes #1644 +* Fixes #1643 +* fix: Revert correct test case + +[15ff8](https://github.com/JSQLParser/JSqlParser/commit/15ff84348228278) manticore-projects *2022-10-16 20:15:36* + +**actualized multiple dependencies** + + +[34502](https://github.com/JSQLParser/JSqlParser/commit/34502d0e66ad214) Tobias Warneke *2022-09-28 20:17:35* + +**Bump h2 from 1.4.200 to 2.1.210 (#1639)** + +* Bumps [h2](https://github.com/h2database/h2database) from 1.4.200 to 2.1.210. +* - [Release notes](https://github.com/h2database/h2database/releases) +* - [Commits](https://github.com/h2database/h2database/compare/version-1.4.200...version-2.1.210) +* --- +* updated-dependencies: +* - dependency-name: com.h2database:h2 +* dependency-type: direct:development +* ... +* Signed-off-by: dependabot[bot] <support@github.com> +* Signed-off-by: dependabot[bot] <support@github.com> +* Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +[fc3c4](https://github.com/JSQLParser/JSqlParser/commit/fc3c4cfd6b1eda9) dependabot[bot] *2022-09-28 19:52:31* + +**Support BigQuery SAFE_CAST (#1622) (#1634)** + +* Co-authored-by: Zhang, Dequn <deqzhang@paypal.com> + +[d9985](https://github.com/JSQLParser/JSqlParser/commit/d9985ae4f559cda) dequn *2022-09-20 18:22:25* + +**Support timestamptz dateliteral (#1621)** + +* support timestamptz as datetime literal +* rename test + +[81a64](https://github.com/JSQLParser/JSqlParser/commit/81a648eba8db92d) Todd Pollak *2022-08-31 20:31:44* + +**fixes #1617** + + +[b0aae](https://github.com/JSQLParser/JSqlParser/commit/b0aae378864c6e1) Tobias Warneke *2022-08-31 20:22:25* + +**fixes #419** + + +[427e9](https://github.com/JSQLParser/JSqlParser/commit/427e90f6b861e23) Tobias Warneke *2022-08-31 19:01:57* + +**Closes #1604, added simple OVERLAPS support (#1611)** + + +[236a5](https://github.com/JSQLParser/JSqlParser/commit/236a50b800a4794) Rob Audenaerde *2022-08-16 08:21:03* + +**Fixes PR #1524 support hive alter sql (#1609)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Fixes broken PR #1524 and Commit fb6e950ce0e62ebcd7a44ba9eea679da2b04b2ed + +[2619c](https://github.com/JSQLParser/JSqlParser/commit/2619ce0a6fd8bd5) manticore-projects *2022-08-14 16:29:18* + +**#1524 support hive alter sql : ALTER TABLE name ADD COLUMNS (col_spec[, col_spec ...]) (#1605)** + +* Co-authored-by: zhum@aotain.com <zm7705264> + +[fb6e9](https://github.com/JSQLParser/JSqlParser/commit/fb6e950ce0e62eb) Zhumin-lv-wn *2022-08-03 20:56:44* + +**fixes #1581** + + +[732e8](https://github.com/JSQLParser/JSqlParser/commit/732e840e99740ff) Tobias Warneke *2022-07-25 06:43:39* + +**Using own Feature - constant for "delete with returning" #1597 (#1598)** + + +[d3218](https://github.com/JSQLParser/JSqlParser/commit/d3218483f7f33ec) gitmotte *2022-07-25 04:55:20* + +**** + + +[2f491](https://github.com/JSQLParser/JSqlParser/commit/2f4916d3e512e14) Tobias Warneke *2022-07-22 23:19:59* + + +## jsqlparser-4.5 (2022-07-22) + +### Other changes + +**introduced changelog generator** + + +[e0f0e](https://github.com/JSQLParser/JSqlParser/commit/e0f0eabdfd1e820) Tobias Warneke *2022-07-22 22:47:00* + +**fixes #1596** + + +[60d64](https://github.com/JSQLParser/JSqlParser/commit/60d648397b01c2d) Tobias Warneke *2022-07-22 22:31:12* + +**integrated test for #1595** + + +[b3927](https://github.com/JSQLParser/JSqlParser/commit/b392733f25468f1) Tobias Warneke *2022-07-19 22:04:18* + +**** + + +[09830](https://github.com/JSQLParser/JSqlParser/commit/09830c9fb999bc6) Tobias Warneke *2022-07-19 21:44:43* + +**reduced time to parse exception to minimize impact on building time** + + +[191b9](https://github.com/JSQLParser/JSqlParser/commit/191b9fd2c796aa1) Tobias Warneke *2022-07-19 21:40:35* + +**add support for drop column if exists (#1594)** + + +[fcfdf](https://github.com/JSQLParser/JSqlParser/commit/fcfdfb7458fd28f) rrrship *2022-07-19 21:38:40* + +**PostgreSQL INSERT ... ON CONFLICT Issue #1551 (#1552)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Support Postgres INSERT ... ON CONFLICT +* Fixes #1551 +* Refactor UpdateSet.toString(), which is used by Insert and Update +* Allow KEEP keyword +* Enables special Oracle Test keywordasidentifier04.sql, now 191 tests succeed +* Sanitize before push +* Tweak Grammar in order to survive the Maven Build +* Ammend the README +* Move Plugin configuration files to the CONFIG folder (hoping, that Codacy will find it there) +* Update PMD in the Maven configuration +* Update PMD in the Maven and Gradle configuration +* Appease Codacy +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[5ae09](https://github.com/JSQLParser/JSqlParser/commit/5ae09ad097c7294) manticore-projects *2022-07-19 21:18:02* + +**Configurable Parser Timeout via Feature (#1592)** + +* Configurable Parser Timeout via Feature +* Fixes #1582 +* Implement Parser Timeout Feature, e. g. `CCJSqlParserUtil.parse(sqlStr, parser -> parser.withTimeOut(60000));` +* Add a special test failing after a long time only, to test TimeOut vs. Parser Exception +* Appease Codacy +* Appease Codacy +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[74000](https://github.com/JSQLParser/JSqlParser/commit/74000130e850788) manticore-projects *2022-07-19 20:48:49* + +**fixes #1590** + + +[cfba6](https://github.com/JSQLParser/JSqlParser/commit/cfba6e54df4ed58) Tobias Warneke *2022-07-19 20:26:19* + +**fixes #1590** + + +[1abaf](https://github.com/JSQLParser/JSqlParser/commit/1abaf4cdbed1938) Tobias Warneke *2022-07-19 20:17:50* + +**extended support Postgres' `Extract( field FROM source)` where `field` is a String instead of a Keyword (#1591)** + +* Fixes #1582 +* Amend the ExtractExpression +* Add Test case for issue #1582 +* Amend the README + +[2b3ce](https://github.com/JSQLParser/JSqlParser/commit/2b3ce25a23b264a) manticore-projects *2022-07-19 19:25:23* + +**** + + +[87a37](https://github.com/JSQLParser/JSqlParser/commit/87a37d73f29ff55) Tobias Warneke *2022-07-14 19:30:27* + +**** + + +[26545](https://github.com/JSQLParser/JSqlParser/commit/26545484caa9372) Tobias Warneke *2022-07-14 19:23:39* + +**Closes #1579. Added ANALYZE
support. (#1587)** + + +[e5c8a](https://github.com/JSQLParser/JSqlParser/commit/e5c8a89ded6d5ca) Rob Audenaerde *2022-07-14 19:22:47* + +**** + + +[b4a5c](https://github.com/JSQLParser/JSqlParser/commit/b4a5ce1374ab4f1) Tobias Warneke *2022-07-14 19:01:29* + +**** + + +[b08f2](https://github.com/JSQLParser/JSqlParser/commit/b08f205ea573553) Tobias Warneke *2022-07-14 18:56:19* + +**Closes #1583:: Implement Postgresql optional TABLE in TRUNCATE (#1585)** + +* Closes #1583 +* Closes #1583, removed unnecessary local variable. +* Closes #1583, proper support for deparsing. + +[26248](https://github.com/JSQLParser/JSqlParser/commit/262482610b80d18) Rob Audenaerde *2022-07-14 18:55:44* + +**** + + +[6b242](https://github.com/JSQLParser/JSqlParser/commit/6b2422e9cca5d56) Tobias Warneke *2022-07-14 18:53:41* + +**Support table option character set and index options (#1586)** + +* Support table option character set and index options +* Signed-off-by: luofei <luoffei@outlook.com> +* move test +* Signed-off-by: luofei <luoffei@outlook.com> + +[27cdf](https://github.com/JSQLParser/JSqlParser/commit/27cdfa9ca1237f6) luofei *2022-07-14 18:46:14* + +**corrected a last minute bug** + + +[afbaf](https://github.com/JSQLParser/JSqlParser/commit/afbaf53f4d5e727) Tobias Warneke *2022-07-09 15:28:17* + +**corrected a last minute bug** + + +[f3d2b](https://github.com/JSQLParser/JSqlParser/commit/f3d2b19dda25d09) Tobias Warneke *2022-07-09 15:25:36* + +**corrected a last minute bug** + + +[8378e](https://github.com/JSQLParser/JSqlParser/commit/8378ea4343e1a97) Tobias Warneke *2022-07-09 15:23:50* + +**fixes #1576** + + +[48ea0](https://github.com/JSQLParser/JSqlParser/commit/48ea0e2238e8186) Tobias Warneke *2022-07-09 14:26:07* + +**added simple test for #1580** + + +[5fdab](https://github.com/JSQLParser/JSqlParser/commit/5fdabf13251b193) Tobias Warneke *2022-07-07 20:13:12* + +**disabled test for large cnf expansion and stack overflow problem** + + +[d3000](https://github.com/JSQLParser/JSqlParser/commit/d30005b4486618b) Tobias Warneke *2022-07-07 19:30:37* + +**Add test for LikeExpression.setEscape and LikeExpression.getStringExpression (#1568)** + +* Add test for LikeExpression.setEscape and LikeExpression.getStringExpression +* like + set escape test for $ as escape character + +[bcf6f](https://github.com/JSQLParser/JSqlParser/commit/bcf6ff4157277f9) Caro *2022-07-07 19:27:43* + +**** + + +[a8a05](https://github.com/JSQLParser/JSqlParser/commit/a8a05535ca6e7c9) Tobias Warneke *2022-07-06 20:22:51* + +**add support for postgres drop function statement (#1557)** + + +[964fa](https://github.com/JSQLParser/JSqlParser/commit/964fa49ff25cd46) rrrship *2022-07-06 20:06:09* + +**** + + +[afbb5](https://github.com/JSQLParser/JSqlParser/commit/afbb595c749d2c2) Tobias Warneke *2022-07-06 19:53:35* + +**Add support for Hive dialect GROUPING SETS. (#1539)** + +* Add support for Hive GROUPING SETS dialect `GROUP BY a, b, c GROUPING SETS ((a, b), (a, c))` +* Simplify HiveTest::testGroupByGroupingSets. + +[03c58](https://github.com/JSQLParser/JSqlParser/commit/03c58de9d341a13) chenwl *2022-07-06 19:40:41* + +**fixes #1566** + + +[886f0](https://github.com/JSQLParser/JSqlParser/commit/886f06dac867b55) Tobias Warneke *2022-06-28 20:55:12* + +**Postgres NATURAL LEFT/RIGHT joins (#1560)** + +* Postgres NATURAL LEFT/RIGHT joins +* Fixes #1559 +* Make NATURAL an optional Join Keyword, which can be combined with LEFT, RIGHT, INNER +* Add tests +* Postgres NATURAL LEFT/RIGHT joins +* Amend readme +* Revert successful Oracle test + +[74a0f](https://github.com/JSQLParser/JSqlParser/commit/74a0f2fb22e24fe) manticore-projects *2022-06-28 20:15:34* + +**compound statement tests (#1545)** + + +[c1c38](https://github.com/JSQLParser/JSqlParser/commit/c1c38fe26b1fe90) Matthew Rathbone *2022-06-08 19:11:08* + +**Allow isolation keywords as column name and aliases (#1534)** + + +[fc5a9](https://github.com/JSQLParser/JSqlParser/commit/fc5a9a3dbb91e8e) Tomer Shay (Shimshi) *2022-05-19 21:01:44* + +**added github action badge** + + +[e4ec0](https://github.com/JSQLParser/JSqlParser/commit/e4ec041bdcf5683) Tobias *2022-05-16 09:31:36* + +**Create maven.yml** + +* started maven build using github actions + +[b7e5c](https://github.com/JSQLParser/JSqlParser/commit/b7e5c151df37f5e) Tobias *2022-05-16 09:24:24* + +**introduced deparser and toString correction for insert output clause** + + +[51105](https://github.com/JSQLParser/JSqlParser/commit/5110598f0a2a774) Tobias Warneke *2022-05-15 22:07:19* + +**revived compilable status after merge** + + +[75489](https://github.com/JSQLParser/JSqlParser/commit/75489bfc3a0355c) Tobias Warneke *2022-05-15 21:29:21* + +**INSERT with SetOperations (#1531)** + +* INSERT with SetOperations +* Simplify the INSERT production +* Use SetOperations for Select and Values +* Better Bracket handling for WITH ... SELECT ... +* Fixes #1491 +* INSERT with SetOperations +* Appease Codazy/PMD +* INSERT with SetOperations +* Appease Codazy/PMD +* Update Readme +* List the changes +* Minor rephrases +* Correct the Maven Artifact Example +* Fix the two test cases (missing white space) +* Remove unused import + +[b5672](https://github.com/JSQLParser/JSqlParser/commit/b5672c54386cdf8) manticore-projects *2022-05-15 20:29:06* + +**#1516 rename without column keyword (#1533)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* `RENAME ... TO ...` without `COLUMN` keyword +* Fixes #1516 + +[e8f07](https://github.com/JSQLParser/JSqlParser/commit/e8f0750d75e74c7) manticore-projects *2022-05-11 20:44:34* + +**Add support for `... ALTER COLUMN ... DROP DEFAULT` (#1532)** + + +[de0e8](https://github.com/JSQLParser/JSqlParser/commit/de0e8715ad7cab5) manticore-projects *2022-05-11 20:37:08* + +**** + + +[81caf](https://github.com/JSQLParser/JSqlParser/commit/81caf3af5eb2762) Tobias Warneke *2022-05-11 20:15:28* + +**#1527 DELETE ... RETURNING ... (#1528)** + +* #1527 DELETE ... RETURNING ... +* Fixes #1527 +* Add DELETE... RETURNING ... expression +* Simplify INSERT ... RETURNING ... expression +* Simply UPDATE ... RETURNING ... expression +* TSQL Output Clause +* According to https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver15 +* Implement Output Clause for INSERT, UPDATE and DELETE +* Add Tests according the Microsoft Documentation +* Appease Codacy/PMD + +[4d815](https://github.com/JSQLParser/JSqlParser/commit/4d8152159454069) manticore-projects *2022-05-11 20:04:23* + +**fixs #1520 (#1521)** + + +[f7f9d](https://github.com/JSQLParser/JSqlParser/commit/f7f9d270b13377d) chiangcho *2022-05-11 19:51:47* + +**** + + +[22fef](https://github.com/JSQLParser/JSqlParser/commit/22fef8c95eddbce) Tobias Warneke *2022-05-11 19:45:25* + +**Unsupported statement (#1519)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Implement UnsupportedStatement +* - Add Feature allowUnsupportedStatement, default=false +* - Fully implement UnsupportedStatement for the Statement() production +* - Partially implement UnsupportedStatement for the Statements() production, works only when UnsupportedStatement comes first +* Revert unintended changes of the test resources +* Reformat BLOCK production +* Disable STATEMENTS() test, which will never fail and add comments to this regard + +[59bb9](https://github.com/JSQLParser/JSqlParser/commit/59bb9a4e40753cf) manticore-projects *2022-05-11 19:23:35* + +**fixes #1518** + + +[bc113](https://github.com/JSQLParser/JSqlParser/commit/bc11309777df6b4) Tobias Warneke *2022-04-26 21:06:44* + +**Update bug_report.md (#1512)** + +* Focus more on the particular SQL Statement and the JSQLParser Version. +* Link to the Online Formatter for testing. + +[13441](https://github.com/JSQLParser/JSqlParser/commit/13441f47fbd8023) manticore-projects *2022-04-22 22:29:07* + +**changed to allow #1481** + + +[0cc2a](https://github.com/JSQLParser/JSqlParser/commit/0cc2a29c4d7b3ad) Tobias Warneke *2022-04-22 21:56:27* + +**Performance Improvements (#1439)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Performance Improvements +* Simplify the Primary Expression Production +* Try to simple parse without Complex Expressions first, before parsing complex and slow (if supported by max nesting depth) +* Add Test cases for issues #1397 and #1438 +* Update Libraries to its latest version +* Remove JUnit 4 from Gradle +* Appease PMD +* Update Gradle Plugins to its latest versions +* Let Parser timeout after 6 seconds and fail gently +* Add a special test verifying the clean up after timeout +* Revert unintended changes to the Test Resources +* Appease PMD/Codacy +* Correct the Gradle "+" dependencies +* Bump version to 4.4.-SNAPSHOT +* update build file +* revert unwarranted changes in test files +* strip the Exception Class Name from the Message +* maxDepth = 10 collides with the Parser Timeout = 6 seconds +* License Headers +* Unused imports +* Bump version to 4.5-SNAPSHOT +* Reduce test loops to fit intothe timeout + +[181a2](https://github.com/JSQLParser/JSqlParser/commit/181a21ab90870e1) manticore-projects *2022-04-14 21:18:18* + + +## jsqlparser-4.4 (2022-04-10) + +### Other changes + +**** + + +[00b24](https://github.com/JSQLParser/JSqlParser/commit/00b2440852b847a) Tobias Warneke *2022-04-09 22:43:11* + +**Json function Improvements (#1506)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Improve JSON Functions +* Space around the `:` delimiter of JSON Functions +* Improve JSON Functions +* Enforce `KEY` as `S_CHAR_LITERAL` +* Allow `Column` as `VALUE` +* Temporarily disable Postgres Syntax +* Improve JSON Functions +* Bring back Postgres Syntax +* Enable MySQL Syntax JSON_OBJECT(key, value [, key, value, ...]) +* Fix some more tests, where key was not a String +* Appease Codacy +* Let JSON_OBJECT accept Expressions as value +* set Version = 4.4-SNAPSHOT + +[e3f53](https://github.com/JSQLParser/JSqlParser/commit/e3f531caf7ad9ba) manticore-projects *2022-04-09 22:37:36* + +**fixes #1505** + + +[41c77](https://github.com/JSQLParser/JSqlParser/commit/41c77ca5dd75ae1) Tobias Warneke *2022-04-09 21:16:45* + +**** + + +[f3fac](https://github.com/JSQLParser/JSqlParser/commit/f3facb762de3ef7) Tobias Warneke *2022-04-09 20:20:23* + +**fixes #1502** + + +[fea85](https://github.com/JSQLParser/JSqlParser/commit/fea8575fbed4cbb) Tobias Warneke *2022-04-09 20:10:41* + +**Issue1500 - Circular References in `AllColumns` and `AllTableColumns` (#1501)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports +* Remove circular reference revealed by issue #1500 +* Add test for Issue 1500 Circular reference for All Columns Expression +* Fix Test case +* Add Test for AllTableColumn due to similar circular reference +* Remove similar circular reference from AllTableColumn +* Update dependencies +* Adjust Jacoco Missed Lines count + +[0949d](https://github.com/JSQLParser/JSqlParser/commit/0949df9d789123c) manticore-projects *2022-04-03 18:51:35* + +**** + + +[62677](https://github.com/JSQLParser/JSqlParser/commit/62677a68fcc5c34) Tobias Warneke *2022-04-02 23:59:19* + +**Optimize assertCanBeParsedAndDeparsed (#1389)** + +* Optimize assertCanBeParsedAndDeparsed +* - Avoid redundant calls of buildSqlString() +* - Replace String.replaceAll() with Matcher.replaceAll() based on precompiled Regex Patterns +* Reset the testcase results + +[ea316](https://github.com/JSQLParser/JSqlParser/commit/ea3164a1e418f3b) manticore-projects *2022-04-02 22:40:09* + +**Add geometry distance operator (#1493)** + +* Add support for geometry distance operators in PostGIS. +* Fix missing imports. +* Co-authored-by: Thomas Powell <tpowell@palantir.com> + +[98c47](https://github.com/JSQLParser/JSqlParser/commit/98c476a6c9fa1a1) Thomas Powell *2022-04-02 22:31:08* + +**Support WITH TIES option in TOP #1435 (#1479)** + +* Support WITH TIES option in TOP +* - Add the support of WITH TIES option in SELECT TOP statement. +* add specific test + +[1756a](https://github.com/JSQLParser/JSqlParser/commit/1756adcade48fb4) Olivier Cavadenti *2022-04-02 21:26:54* + +**fixes #1482** + + +[7ddb7](https://github.com/JSQLParser/JSqlParser/commit/7ddb7c8e056be6d) Tobias Warneke *2022-03-15 21:51:56* + +**fixes #1482** + + +[251cc](https://github.com/JSQLParser/JSqlParser/commit/251cc3c09c477d1) Tobias Warneke *2022-03-15 21:48:13* + +**Extending CaseExpression, covering #1458 (#1459)** + +* Add unit tests for Case expressions. +* More tests for CaseExpression. +* Switch expression becomes an Expression instead of a Condition. +* It allows complex expressions in the switch, similarly to what is allowed in when clauses. + +[4df13](https://github.com/JSQLParser/JSqlParser/commit/4df1391a28a7402) Mathieu Goeminne *2022-03-15 20:07:43* + +**fixes #1471** + + +[3695e](https://github.com/JSQLParser/JSqlParser/commit/3695e0479448ab9) Tobias Warneke *2022-02-18 23:03:24* + +**fixes #1471** + + +[e789c](https://github.com/JSQLParser/JSqlParser/commit/e789c9c7869dc27) Tobias Warneke *2022-02-18 22:32:04* + +**fixes #1470** + + +[c7075](https://github.com/JSQLParser/JSqlParser/commit/c70758266b5af51) Tobias Warneke *2022-02-06 22:21:12* + +**Add support for IS DISTINCT FROM clause (#1457)** + +* Co-authored-by: Tomer Shay <tomer@Tomers-MBP.lan> + +[31ed3](https://github.com/JSQLParser/JSqlParser/commit/31ed383ff0f3903) Tomer Shay (Shimshi) *2022-01-18 07:01:14* + +**fix fetch present in the end of union query (#1456)** + + +[6e632](https://github.com/JSQLParser/JSqlParser/commit/6e6321481a15965) chiangcho *2022-01-18 07:00:14* + +**added SQL_CACHE implementation and changed** + + +[cf012](https://github.com/JSQLParser/JSqlParser/commit/cf0128ac884c2b8) Tobias Warneke *2022-01-09 12:16:39* + +**support for db2 with ru (#1446)** + + +[3e976](https://github.com/JSQLParser/JSqlParser/commit/3e976528094e646) chiangcho *2021-12-20 22:50:56* + +**** + + +[13878](https://github.com/JSQLParser/JSqlParser/commit/1387891cc837f64) Tobias Warneke *2021-12-12 15:37:58* + + +## jsqlparser-4.3 (2021-12-12) + +### Other changes + +**updated readme.md to show all changes for version 4.3** + + +[f0396](https://github.com/JSQLParser/JSqlParser/commit/f039659d1fb5b35) Tobias Warneke *2021-12-12 15:20:32* + +**Adjust Gradle to JUnit 5 (#1428)** + +* Adjust Gradle to JUnit 5 +* Parallel Test execution +* Gradle Caching +* Explicitly request for latest JavaCC 7.0.10 +* Do not mark SpeedTest for concurrent execution +* Remove unused imports + +[af7bc](https://github.com/JSQLParser/JSqlParser/commit/af7bc1cc06700c3) manticore-projects *2021-11-28 21:43:10* + +**corrected some maven plugin versions** + + +[0acb2](https://github.com/JSQLParser/JSqlParser/commit/0acb28fe33bc7df) Tobias Warneke *2021-11-28 21:40:56* + +**fixes #1429** + + +[bc891](https://github.com/JSQLParser/JSqlParser/commit/bc891e7dcf1d86d) Tobias Warneke *2021-11-23 06:29:25* + +**closes #1427** + + +[46424](https://github.com/JSQLParser/JSqlParser/commit/46424d93784f205) Tobias Warneke *2021-11-21 19:42:11* + +**CreateTableTest** + + +[50ef7](https://github.com/JSQLParser/JSqlParser/commit/50ef7edc3ed6bd6) Tobias Warneke *2021-11-21 12:21:21* + +**Support EMIT CHANGES for KSQL (#1426)** + +* - Add the EMIT CHANGES syntax used in KSQL. + +[f6c17](https://github.com/JSQLParser/JSqlParser/commit/f6c17412accdd18) Olivier Cavadenti *2021-11-21 12:20:56* + +**SelectTest.testMultiPartColumnNameWithDatabaseNameAndSchemaName** + + +[d8735](https://github.com/JSQLParser/JSqlParser/commit/d873526fe9f9a38) Tobias Warneke *2021-11-21 12:17:29* + +**reformatted test source code** + + +[fb455](https://github.com/JSQLParser/JSqlParser/commit/fb455a7efe1ed04) Tobias Warneke *2021-11-21 12:11:43* + +**organize imports** + + +[31921](https://github.com/JSQLParser/JSqlParser/commit/31921285376bb41) Tobias Warneke *2021-11-21 12:09:26* + +**replaced all junit 3 and 4 with junit 5 stuff** + + +[2c672](https://github.com/JSQLParser/JSqlParser/commit/2c6724769e76429) Tobias Warneke *2021-11-21 12:03:37* + +**** + + +[fce5b](https://github.com/JSQLParser/JSqlParser/commit/fce5b9953a5a9c1) Tobias Warneke *2021-11-20 00:08:05* + +**Support RESTART without value (#1425)** + +* Since Postgre 8.4, RESTART in ALTER SEQUENCE can be set without value. + +[98b66](https://github.com/JSQLParser/JSqlParser/commit/98b66be4b2919df) Olivier Cavadenti *2021-11-20 00:00:32* + +**Add support for oracle UnPivot when use multi columns at once. (#1419)** + +* Co-authored-by: LeiJun <02280245@yto.net.cn> + +[8e8bb](https://github.com/JSQLParser/JSqlParser/commit/8e8bb708636e6c6) LeiJun *2021-11-19 23:22:29* + +**** + + +[1fe92](https://github.com/JSQLParser/JSqlParser/commit/1fe92bc61914135) Tobias Warneke *2021-11-19 22:36:41* + +**Fix issue in parsing TRY_CAST() function (#1391)** + +* Fix issue in parsing TRY_CAST() function +* Fix issue in parsing TRY_CAST() function +* Add parser, deparser, validator and vistior implementation for try_cast function +* Update toString() method of TryCastExpression class + +[bfcf0](https://github.com/JSQLParser/JSqlParser/commit/bfcf00f9dfcc0a3) Prashant Sutar *2021-11-19 22:24:49* + +**fixes #1414** + + +[93b8c](https://github.com/JSQLParser/JSqlParser/commit/93b8c8b96d5558d) Tobias Warneke *2021-11-19 22:21:21* + +**Add support for expressions (such as columns) in AT TIME ZONE expressions (#1413)** + +* Co-authored-by: EverSQL <tomer@eversql.com> + +[ebe17](https://github.com/JSQLParser/JSqlParser/commit/ebe171b3b502089) Tomer Shay (Shimshi) *2021-11-19 22:04:40* + +**Add supported for quoted cast expressions for PostgreSQL (#1411)** + +* Co-authored-by: EverSQL <tomer@eversql.com> + +[dbbce](https://github.com/JSQLParser/JSqlParser/commit/dbbcebbf0490e1c) Tomer Shay (Shimshi) *2021-11-19 21:54:37* + +**added USE SCHEMA and CREATE OR REPLACE
support; things that are allowed in Snowflake SQL (#1409)** + +* Co-authored-by: Richard Kooijman <richard.kooijman@inergy.nl> + +[f35d2](https://github.com/JSQLParser/JSqlParser/commit/f35d24cfbb88342) Richard Kooijman *2021-11-19 21:40:45* + +**Issue #420 Like Expression with Escape Expression (#1406)** + +* Issue #420 Like Expression with Escape Expression +* Fixes issue #420 +* CheckStyle compliance + +[8eaa4](https://github.com/JSQLParser/JSqlParser/commit/8eaa4d2fc243f0a) manticore-projects *2021-11-19 21:38:54* + +**fixes #1405 and some junit.jupiter stuff** + + +[9adab](https://github.com/JSQLParser/JSqlParser/commit/9adab8d059685ff) Tobias Warneke *2021-11-19 21:32:23* + +**#1401 add junit-jupiter-api (#1403)** + + +[80ff5](https://github.com/JSQLParser/JSqlParser/commit/80ff50e0296c107) gitmotte *2021-11-19 21:10:18* + +**Support Postgres Dollar Quotes #1372 (#1395)** + + +[0bd4c](https://github.com/JSQLParser/JSqlParser/commit/0bd4c198e483616) Olivier Cavadenti *2021-11-19 20:32:26* + +**Add Delete / Update modifiers for MySQL #1254 (#1396)** + +* Add Delete / Update modifiers for MySQL #1254 +* fix codacy issues + pr return +* simplify low_priority + +[7be5d](https://github.com/JSQLParser/JSqlParser/commit/7be5d8e65e23f6e) Olivier Cavadenti *2021-11-19 20:31:00* + +**Fixes #1381 (#1383)** + +* Allow Complex Expressions as SelectItem + +[cdf0f](https://github.com/JSQLParser/JSqlParser/commit/cdf0f095294b04a) manticore-projects *2021-11-19 20:27:44* + +**Allows CASE ... ELSE ComplexExpression (#1388)** + +* Fixes #1375 +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[60a7d](https://github.com/JSQLParser/JSqlParser/commit/60a7d103853cb5e) manticore-projects *2021-11-02 20:48:39* + +**IN() with complex expressions (#1384)** + +* IN() with Complex Expressions +* Fixes #905 +* Allow Complex Expressions and multiple SubSelects for the IN() Expression +* Tune the Test Coverage +* Remove unused import +* Reset TEST status + +[c4232](https://github.com/JSQLParser/JSqlParser/commit/c42322440d5fb36) manticore-projects *2021-11-01 21:23:48* + +**Fixes #1385 and PR#1380 (#1386)** + +* Add another Alias() Keyword related LOOKAHEAD +* Fix a Keyword Spelling Error in the Deparser +* Remove UNPIVOT from the PARENTHESIS Deparser, as it was an ugly workaround made obsolete by PR #1380 + +[8c1eb](https://github.com/JSQLParser/JSqlParser/commit/8c1eba24be61cf0) manticore-projects *2021-10-22 20:19:15* + +**Fixes #1369 (#1370)** + +* Issue1369 +* Add test + +[2335e](https://github.com/JSQLParser/JSqlParser/commit/2335ed136e92163) Ben Grabham *2021-10-20 21:44:06* + +**Fixes #1371 (#1377)** + +* Fixes #1371 +* Postgres specific JSON_OBJECT syntax supporting: +* SELECT json_object('{a, 1, b, 2}'); +* SELECT json_object('{{a, 1}, {b, 2}}'); +* SELECT json_object('{a, b}', '{1,2 }'); +* Improve Test Coverage + +[cbffe](https://github.com/JSQLParser/JSqlParser/commit/cbffe6b58cd0074) manticore-projects *2021-10-20 21:13:54* + +**LIMIT OFFSET with Expressions (#1378)** + +* Fixes #933 + +[a52db](https://github.com/JSQLParser/JSqlParser/commit/a52db54ff61be34) manticore-projects *2021-10-20 21:05:27* + +**Oracle Multi Column Drop (#1379)** + +* Fixes #1363 + +[9ad18](https://github.com/JSQLParser/JSqlParser/commit/9ad18d29efb66a2) manticore-projects *2021-10-20 21:01:04* + +**Support alias for UnPivot statement (see discussion #1374) (#1380)** + +* - Changed JSqlParserCC.jjt file to add the alias to the UnPivot lexical entity. +* - Added Alias to the UnPivot object. +* - Improved SelectDeParser to correctly deparse SubSelect's UnPivot component. + +[0c0c3](https://github.com/JSQLParser/JSqlParser/commit/0c0c32e9cda0f1a) fabriziodelfranco *2021-10-20 20:18:13* + +**Issue1352 (#1353)** + +* Fixes #1352 +* Allow SYSTEM as table- or column- name +* Fixes #1352 +* Allow SYSTEM as tablename +* Fixes #1352 +* Allow SYSTEM as tablename and columnname +* Fixes #1352 +* Allow QUERY as tablename and columnname +* Fixes #1352 +* Allow FULLTEXT as tablename and columnname +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[a8afd](https://github.com/JSQLParser/JSqlParser/commit/a8afd9a4e6a8bc0) manticore-projects *2021-10-09 21:31:45* + +**Enhance ALTER TABLE ... DROP CONSTRAINTS ... (#1351)** + +* Enhance ALTER TABLE ... DROP CONSTRAINTS ... +* Add support for DROP PRIMARY KEY, DROP UNIQUE(...) +* Add support for DROP FOREIGN KEY(...) +* Fixes #1342 +* Remove one useless PMD rule +* Add more tests +* Adjust Test Coverage + +[388b7](https://github.com/JSQLParser/JSqlParser/commit/388b7c3afff4f50) manticore-projects *2021-10-08 23:02:46* + +**Function to use AllColumns or AllTableColumns Expression (#1350)** + +* Fix a trivial MERGE error from Commit 4797a8d676625fcc6cf8c9e3b403ca120b6a8141 +* Function use AllColumns or AllTableColumns +* Fixes #1346 +* Remove one useless PMD rule + +[b0ada](https://github.com/JSQLParser/JSqlParser/commit/b0adaa8de1421ea) manticore-projects *2021-10-08 21:58:04* + +**Postgres compliant ALTER TABLE ... RENAME TO ... (#1334)** + +* Fix a trivial MERGE error from Commit 4797a8d676625fcc6cf8c9e3b403ca120b6a8141 +* Fixes #1333 +* Postgres compliant ALTER TABLE ... RENAME TO ... +* Postgres compliant ALTER TABLE IF EXISTS ... RENAME TO ... +* Postgres compliant ALTER TABLE IF EXISTS ... RENAME TO ... + +[f353e](https://github.com/JSQLParser/JSqlParser/commit/f353ec830deb719) manticore-projects *2021-09-18 11:35:17* + +**Postgres compliant ALTER TABLE ... RENAME TO ... (#1334)** + +* Fix a trivial MERGE error from Commit 4797a8d676625fcc6cf8c9e3b403ca120b6a8141 +* Fixes #1333 +* Postgres compliant ALTER TABLE ... RENAME TO ... +* Postgres compliant ALTER TABLE IF EXISTS ... RENAME TO ... +* Postgres compliant ALTER TABLE IF EXISTS ... RENAME TO ... + +[5e904](https://github.com/JSQLParser/JSqlParser/commit/5e9045f431d9cc4) manticore-projects *2021-09-18 11:34:50* + +**corrected readme to the new snapshot version** + + +[b8867](https://github.com/JSQLParser/JSqlParser/commit/b8867d71c0f29d3) Tobias Warneke *2021-09-08 09:57:36* + + +## jsqlparser-4.2 (2021-09-08) + +### Other changes + +**introducing test for issue #1328** + + +[56a39](https://github.com/JSQLParser/JSqlParser/commit/56a39a4693a991f) Tobias Warneke *2021-09-07 09:57:20* + +**included some distinct check** + + +[1264a](https://github.com/JSQLParser/JSqlParser/commit/1264a2033c0062a) Tobias Warneke *2021-09-07 09:49:48* + +**corrected a merge bug** + + +[d53f8](https://github.com/JSQLParser/JSqlParser/commit/d53f8a7fb6b898c) Tobias Warneke *2021-09-07 09:28:35* + +**Prepare4.2 (#1329)** + +* Implement caching of the Gradle and Maven files +* Provided by @YunLemon via PR #1307 +* Fix CREATE TABLE AS SELECT ... UNION SELECT ... +* Provided by @fanchuo via PR #1309 +* Fix #1316 +* Add more specific tests verifying the nature of the UpdateSets +* Allow "SELECT *" (without FROM) to parse, its a valid SELECT statement +* Add the enhancements since Release 4.1 +* Adjust the Coverage +* Improve Test Coverage +* Revert the Special Oracle Tests (accidentally set to FAILURE) +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[4797a](https://github.com/JSQLParser/JSqlParser/commit/4797a8d676625fc) manticore-projects *2021-09-07 08:56:12* + +**CREATE TABLE AS (...) UNION (...) fails (#1309)** + + +[a7b5c](https://github.com/JSQLParser/JSqlParser/commit/a7b5c2b078e3ebe) François Sécherre *2021-09-07 08:51:01* + +**Fixes #1325 (#1327)** + +* Removes redundant production Identifier() and uses RelObjectnameWithoutValue() instead for MS SQL Server Hints + +[cf0d7](https://github.com/JSQLParser/JSqlParser/commit/cf0d74f6572d6aa) manticore-projects *2021-09-06 12:09:01* + +**Implement Joins with multiple trailing ON Expressions (#1303)** + +* Implement Joins with multiple trailing ON Expressions +* Fixes #1302 +* Fixes SpecialOracleTest JOIN17, now 190/273 tests pass +* Fixes #1229 +* Merge MASTER +* Refactor the appendTo() method in favour of the traditional toString() +* Remove unused imports + +[d18c5](https://github.com/JSQLParser/JSqlParser/commit/d18c59bf845c57d) manticore-projects *2021-09-06 11:34:05* + +**Fix Gradle PMD and Checkstyle (#1318)** + +* Fixes #1306 +* Nested Cases with Complex Expressions +* Reduce coverage for Java 8 +* GROUP BY with Complex Expressions +* Fixes #1308 +* Update Sets with Complex Expressions +* Fixes #1316 +* Update Sets with Complex Expressions +* Fix existing tests +* Add tests for the new functionality +* Implement PMD/Codacy recommendations +* Add Checkstyle Configuration to Gradle +* Add Checkstyle Config files +* Fix additional exceptions in Test Sources + +[2e876](https://github.com/JSQLParser/JSqlParser/commit/2e876130b46d087) manticore-projects *2021-09-01 22:01:40* + +**** + + +[3f2e7](https://github.com/JSQLParser/JSqlParser/commit/3f2e76cf07ba699) Tobias Warneke *2021-08-28 20:59:29* + +**Fixes #1306 (#1311)** + +* Fixes #1306 +* Nested Cases with Complex Expressions +* Reduce coverage for Java 8 +* GROUP BY with Complex Expressions +* Fixes #1308 + +[8f632](https://github.com/JSQLParser/JSqlParser/commit/8f632b92e511b28) manticore-projects *2021-08-28 20:28:55* + +**Update sets (#1317)** + +* Fixes #1306 +* Nested Cases with Complex Expressions +* Reduce coverage for Java 8 +* GROUP BY with Complex Expressions +* Fixes #1308 +* Update Sets with Complex Expressions +* Fixes #1316 +* Update Sets with Complex Expressions +* Fix existing tests +* Add tests for the new functionality +* Implement PMD/Codacy recommendations + +[21e5e](https://github.com/JSQLParser/JSqlParser/commit/21e5ebac02822e2) manticore-projects *2021-08-27 21:37:05* + +**** + + +[50313](https://github.com/JSQLParser/JSqlParser/commit/50313376d5e6554) Tobias Warneke *2021-08-25 21:12:12* + +**Special oracle tests (#1279)** + +* Allow keywords: LINK, GROUPING() +* Deparse ParenthesisFromItem's Pivot and UnPivot correctly +* Write Test results to the SQL File +* Reduce the noise during the test +* Update/correct the list of expected passing files +* Get the benchmark from the list of expected passing files +* There are no Pivots or UnPivots yet, so we will return NULL. +* Record the expected Test Results on each SQL Source +* Fail the test when any expected success suddenly fails +* Improve Test Coverage +* Appease Codacy + +[346ee](https://github.com/JSQLParser/JSqlParser/commit/346eea5fbcf2461) manticore-projects *2021-08-09 21:55:00* + +**Implements Hierarchical CONNECT_BY_ROOT Operator (#1282)** + +* Implements Hierarchical CONNECT_BY_ROOT Operator +* Fixes Issue #1269 +* Resolves some Special Oracle Tests +* Improve Test Coverage +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[b6014](https://github.com/JSQLParser/JSqlParser/commit/b60140740aab93e) manticore-projects *2021-08-09 21:53:08* + +**Implement Transact-SQL IF ELSE Statement Control Flows. (#1275)** + +* Implement Transact-SQL IF ELSE Statement Control Flows. +* Fixes #1273 except for Blocks. +* Improce Test Coverage +* Adjust the required Test Coverage for JDK 8 + +[750c3](https://github.com/JSQLParser/JSqlParser/commit/750c30aafe83957) manticore-projects *2021-08-09 21:43:50* + +**Add some flexibility to the Alter Statement (#1293)** + +* in order to allow: +* ALTER TABLE ... MOVE TABLESPACE ... +* ALTER TABLE ... COMPRESS NOLOGGING +* ALTER TABLE ... ROWFORMAT=DYNAMIC +* Fixes #1033 + +[a88e9](https://github.com/JSQLParser/JSqlParser/commit/a88e921970c57b8) manticore-projects *2021-08-02 20:51:19* + +**Implement Oracle's Alter System (#1288)** + + +[4ac5a](https://github.com/JSQLParser/JSqlParser/commit/4ac5ab468b1dd1d) manticore-projects *2021-08-02 20:37:40* + +**Implement Oracle Named Function Parameters Func( param1 => arg1, ...) (#1283)** + +* Fixes #1270 + +[c8a5d](https://github.com/JSQLParser/JSqlParser/commit/c8a5d7c3dfc97f4) manticore-projects *2021-08-02 20:32:41* + +**Implement Gradle Buildsystem (#1271)** + +* Gradle build +* implement SpotBugs, PMD and JaCoCo +* implement RR diagrams +* Move Special Oracle Test resources into the correct package +* Implement a basic Gradle/Maven compatibility workaround for the Special Oracle Test +* Fix the Gradle Wrapper and add the folder to git + +[6933d](https://github.com/JSQLParser/JSqlParser/commit/6933d86e0fa2d48) manticore-projects *2021-08-02 20:18:48* + +**fixes #1272** + + +[48a11](https://github.com/JSQLParser/JSqlParser/commit/48a1133ced7dd19) Tobias Warneke *2021-07-26 21:14:20* + +**Allowes JdbcParameter or JdbcNamedParameter for MySQL FullTextSearch (#1278)** + +* Fixes issue #1223 + +[e6c91](https://github.com/JSQLParser/JSqlParser/commit/e6c91b6a813a1e0) manticore-projects *2021-07-26 21:06:38* + +**Fixes #1267 Cast into RowConstructor (#1274)** + +* Fixes #1267 Cast into RowConstructor +* Improve Test Coverage +* Improve Test Coverage +* Improve Test Coverage +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[c89cf](https://github.com/JSQLParser/JSqlParser/commit/c89cf21641d672b) manticore-projects *2021-07-26 21:02:19* + +**** + + +[fecc9](https://github.com/JSQLParser/JSqlParser/commit/fecc95d0ee93100) Tobias Warneke *2021-07-26 20:47:58* + +**Separate MySQL Special String Functions accepting Named Argument Separation as this could collide with ComplexExpressionList when InExpression is involved (#1285)** + +* Fixes #1284 +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[c074a](https://github.com/JSQLParser/JSqlParser/commit/c074a21ad70dd0e) manticore-projects *2021-07-26 20:34:06* + +**Implements Oracle RENAME oldTable TO newTable Statement (#1286)** + +* Implements Oracle RENAME oldTable TO newTable Statement +* Fixes #1253 +* Implement MariaDB specific syntax +* Remove redundant License Headers +* Use LinkedHashMap to preserve the order of the Entries +* Increase Test Coverage +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[f7f7b](https://github.com/JSQLParser/JSqlParser/commit/f7f7bcd65be8f4c) manticore-projects *2021-07-26 20:26:47* + +**Implement Oracle Purge Statement (#1287)** + + +[f86bc](https://github.com/JSQLParser/JSqlParser/commit/f86bc2e432305fb) manticore-projects *2021-07-26 20:18:39* + +**included jacoco to allow code coverage for netbeans** + + +[f85b4](https://github.com/JSQLParser/JSqlParser/commit/f85b4b630008d9e) Tobias Warneke *2021-07-18 21:15:14* + +**corrected a Lookahead problem** + + +[db90e](https://github.com/JSQLParser/JSqlParser/commit/db90e74f1d5d6e8) Tobias Warneke *2021-07-16 21:31:17* + +**Json functions (#1263)** + +* Implement Json Aggregate Functions JSON_OBJECTAGG() and JSON_ARRAYAGG() +* fix the returned type +* Implement JSON_OBJECT and JSON_ARRAY +* Solves #1260 and dbeaver/dbeaver/#13141 +* Better workaround for NULL, NULL NULL ON NULL +* Remove the workaround for NULL ON NULL (without expression) +* Implement "PMD.MissingBreakInSwitch" in order to appease Codacy +* Improve Test Coverage +* Improve Test Coverage +* KEYs can be SQL Value Expressions +* Add another testcase + +[59bf0](https://github.com/JSQLParser/JSqlParser/commit/59bf07f5425ecb4) manticore-projects *2021-07-16 21:24:44* + +**fixes #1255** + + +[2c732](https://github.com/JSQLParser/JSqlParser/commit/2c732ad9bfbe34e) Tobias Warneke *2021-07-16 21:12:45* + +**Active JJDoc and let it create the Grammar BNF documentation (#1256)** + +* Clean-up the Site generation + +[1ecff](https://github.com/JSQLParser/JSqlParser/commit/1ecffd2c1a6e8d8) manticore-projects *2021-07-16 20:38:05* + +**Bump commons-io from 2.6 to 2.7 (#1265)** + +* Bumps commons-io from 2.6 to 2.7. +* --- +* updated-dependencies: +* - dependency-name: commons-io:commons-io +* dependency-type: direct:development +* ... +* Signed-off-by: dependabot[bot] <support@github.com> +* Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +[09898](https://github.com/JSQLParser/JSqlParser/commit/09898107fe6d001) dependabot[bot] *2021-07-14 05:27:57* + +**Update README.md** + + +[e6303](https://github.com/JSQLParser/JSqlParser/commit/e630354df1cd0f4) Tobias *2021-07-13 05:34:12* + +**Implement DB2 Special Register Date Time CURRENT DATE and CURRENT TIME (#1252)** + +* Implement DB2 Special Register Date Time CURRENT DATE and CURRENT TIME +* Fixes issue #1249 +* (Although there are more Special Registers which are not supported yet.) +* Make the spaces mandatory +* Add 2 more tests + +[05157](https://github.com/JSQLParser/JSqlParser/commit/05157a841897033) manticore-projects *2021-07-13 05:32:38* + +**Rename the PMD ruleset configuration file hoping for automatic synchronization with Codacy (#1251)** + +* Solves Issue #1220 + +[930b7](https://github.com/JSQLParser/JSqlParser/commit/930b7a561876b7e) manticore-projects *2021-07-13 05:28:43* + +**corrected .travis.yml** + + +[11124](https://github.com/JSQLParser/JSqlParser/commit/111244ab565a160) Tobias Warneke *2021-07-05 20:57:22* + +**corrected .travis.yml** + + +[5cf7e](https://github.com/JSQLParser/JSqlParser/commit/5cf7eeaa6f7074d) Tobias Warneke *2021-07-05 20:52:40* + +**** + + +[3e0e7](https://github.com/JSQLParser/JSqlParser/commit/3e0e7f38a11fe21) Tobias Warneke *2021-07-05 20:39:11* + +**Update README.md** + + +[ec16d](https://github.com/JSQLParser/JSqlParser/commit/ec16d1f68c83063) Tobias *2021-07-05 20:27:41* + +**fixes #1250** + + +[9e434](https://github.com/JSQLParser/JSqlParser/commit/9e4341a26be1f7f) Tobias Warneke *2021-07-01 12:24:36* + +**** + + +[05d68](https://github.com/JSQLParser/JSqlParser/commit/05d684416f338b6) Tobias Warneke *2021-06-30 22:12:00* + + +## jsqlparser-4.1 (2021-06-30) + +### Other changes + +**fixes #1140** + + +[1a917](https://github.com/JSQLParser/JSqlParser/commit/1a9173f7d65a026) Tobias Warneke *2021-06-30 21:50:28* + +**introduced #1248 halfway** + + +[1deea](https://github.com/JSQLParser/JSqlParser/commit/1deeab8b349343f) Tobias Warneke *2021-06-30 21:15:56* + +**Savepoint rollback (#1236)** + +* Implement SAVEPOINT and ROLLBACK statements, fixes issue #1235 +* Activate a test which is supported now. + +[2cae6](https://github.com/JSQLParser/JSqlParser/commit/2cae62dbf74a744) manticore-projects *2021-06-30 19:57:56* + +**Fixes Function Parameter List Brackets issue #1239 (#1240)** + + +[750f3](https://github.com/JSQLParser/JSqlParser/commit/750f3d1e28fa0d9) manticore-projects *2021-06-30 19:45:32* + +**** + + +[0ba44](https://github.com/JSQLParser/JSqlParser/commit/0ba44c59fcea1cc) Tobias Warneke *2021-06-30 19:41:44* + +**corrected javadoc problem** + + +[f7ea4](https://github.com/JSQLParser/JSqlParser/commit/f7ea4a5040ac7c7) Tobias Warneke *2021-06-27 00:20:35* + +**corrected some lookahead problem** + + +[59c2a](https://github.com/JSQLParser/JSqlParser/commit/59c2a9432ee23d7) Tobias Warneke *2021-06-26 23:57:06* + +**RESET statement, SET PostgreSQL compatibility (#1104)** + +* Support +* RESET statement (https://www.postgresql.org/docs/current/sql-reset.html) +* SET [LOCAL|SESSION] (https://www.postgresql.org/docs/current/sql-set.html) +* SET search_path=my_schema, public ( https://www.postgresql.org/docs/current/sql-set.html +* value New value of parameter. Values can be specified as string constants, identifiers, numbers, or comma-separated lists of these) +* Update ResetStatementTest.java +* remove Tim Zone token +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[13503](https://github.com/JSQLParser/JSqlParser/commit/13503edff30f06d) Роман Зотов *2021-06-26 22:44:33* + +**corrected some lookahead problem** + + +[6711f](https://github.com/JSQLParser/JSqlParser/commit/6711f6043c168f7) Tobias Warneke *2021-06-26 22:42:24* + +**Implement Oracle Alter Session Statements (#1234)** + +* Implement Oracle Alter Session Statements according to https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_2012.htm +* Implement PMD Rule "SwitchStmtsShouldHaveDefault" +* Reorganize Test Case imports + +[3a46a](https://github.com/JSQLParser/JSqlParser/commit/3a46a29d6936611) manticore-projects *2021-06-26 22:38:19* + +**fixes #1230** + + +[3082d](https://github.com/JSQLParser/JSqlParser/commit/3082de3a689c88e) Tobias Warneke *2021-06-26 22:31:43* + +**Support DELETE FROM T1 USING T2 WHERE ... (#1228)** + +* Co-authored-by: Francois Secherre <secherre.nospam@gmail.com> + +[96cd4](https://github.com/JSQLParser/JSqlParser/commit/96cd483ab85783d) francois-secherre *2021-06-16 05:27:14* + +**Row access support (#1181)** + +* Row acess support +* Remove IN Left Expression List, replaced by RowConstructor Expression +* Remove IN Left Expression List, replaced by RowConstructor Expression +* Formatting + +[27e6a](https://github.com/JSQLParser/JSqlParser/commit/27e6a9f0e07320e) Роман Зотов *2021-06-16 05:15:47* + +**corrected lookahead problem of PR #1225** + + +[aec76](https://github.com/JSQLParser/JSqlParser/commit/aec76eae23f1edd) Tobias Warneke *2021-06-14 05:27:40* + +**Delete queries without from, with a schema identifier fails (#1224)** + +* Delete queries without from, with a schema identifier fails +* Better tests +* Fix style issue +* Deparse should match for DELETE WITHOUT FROM queries +* Co-authored-by: François Sécherre <francois.secherre@ouicar.fr> + +[d70e1](https://github.com/JSQLParser/JSqlParser/commit/d70e151c0f22f22) François Sécherre *2021-06-14 05:15:15* + +**Create temporary table t(c1, c2) as select ... (#1225)** + +* Co-authored-by: Francois Secherre <secherre.nospam@gmail.com> + +[b62f1](https://github.com/JSQLParser/JSqlParser/commit/b62f19feb3b497c) francois-secherre *2021-06-14 05:13:13* + +**Nested with items (#1221)** + +* Nested WithItems, fixes issue #1186 +* Remove redundant Test +* Avoid altering the nb-configuration +* Mention Nested WITH CTEs in the readme +* Eliminate dead/unused MultiExpression Code + +[8eb3d](https://github.com/JSQLParser/JSqlParser/commit/8eb3d9a586a182e) manticore-projects *2021-06-10 05:50:08* + +**Implement GROUP BY () without columns (#1218)** + +* Implement GROUP BY () without columns +* Migrate GroupByElement to ExpressionList +* Also solves issue #1210 automatically +* Solves issue #1168, add a test for it. + +[999db](https://github.com/JSQLParser/JSqlParser/commit/999db01658c30f9) manticore-projects *2021-06-03 05:55:35* + +**TSQL Compliant NEXT VALUE FOR sequence_id (but keeping the spurious NEXTVAL FOR expression) (#1216)** + +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[7c212](https://github.com/JSQLParser/JSqlParser/commit/7c21242e893abcd) manticore-projects *2021-06-02 12:35:03* + +**Pmd clean up (#1215)** + +* Add PMD Annotations in order to avoid useless exceptions for the Deparsers +* Add Eclipse Formatter configuration +* Fix typo +* Replace Comments on empty methods with Class wide PMD Annotation +* Do not enforce checkstyle formatting + +[53764](https://github.com/JSQLParser/JSqlParser/commit/537649bf28f641b) manticore-projects *2021-06-02 12:19:32* + +**Add support for boolean 'XOR' operator (#1193)** + +* Add support for boolean 'XOR' operator +* XorExpression added to the ReflectionModelTest +* XorExpression case added to the SelectTest +* XorExpression cases added for Validation +* Additional tests added for code coverage. +* Code style fixed. +* Separate test case for XOR added. +* Imports explicitly added to avoid namespace pollution. +* Additional tests cases for precedence and associativity. +* Co-authored-by: Szabó Miklós <miklos.szabo@arh.hu> + +[c7832](https://github.com/JSQLParser/JSqlParser/commit/c7832402dded4c0) Adaptive Recognition *2021-06-02 12:10:56* + +**Update README.md** + + +[1feea](https://github.com/JSQLParser/JSqlParser/commit/1feea013d865f58) Tobias *2021-05-31 08:46:48* + +**Implement WITH for DELETE, UPDATE and MERGE statements (#1217)** + + +[63ed1](https://github.com/JSQLParser/JSqlParser/commit/63ed1a2f42d14e9) manticore-projects *2021-05-31 08:44:08* + +**** + + +[9184c](https://github.com/JSQLParser/JSqlParser/commit/9184cda558e60a5) Tobias Warneke *2021-05-26 23:12:05* + +**** + + +[f83ed](https://github.com/JSQLParser/JSqlParser/commit/f83ed0a3a30f6d4) Tobias Warneke *2021-05-26 23:09:08* + +**** + + +[76bff](https://github.com/JSQLParser/JSqlParser/commit/76bff01b6b4450f) Tobias Warneke *2021-05-26 23:04:41* + +**increases complex scanning range** + + +[13b88](https://github.com/JSQLParser/JSqlParser/commit/13b88f7f511107e) Tobias Warneke *2021-05-26 21:38:44* + +**Allow Complex Parsing of Functions (#1200)** + +* Allow Complex Parsing of Functions +* Fixes issues #1190 #1103 +* Apply Complex Parsing to PrimaryExpression() +* Fixes issue #1194 +* Increase Test Timeout to 2 seconds for slow CI Servers. +* Appease Codazy + +[3a5da](https://github.com/JSQLParser/JSqlParser/commit/3a5da445ea9cb85) manticore-projects *2021-05-26 20:35:10* + +**Add support for AT TIME ZONE expressions (#1196)** + +* Add support for AT TIME ZONE expressions +* adding tests +* Fixing imports + +[a5204](https://github.com/JSQLParser/JSqlParser/commit/a5204f63ccb1ea8) Tomer Shay (Shimshi) *2021-05-25 23:03:31* + +**fixes #1211** + + +[ed089](https://github.com/JSQLParser/JSqlParser/commit/ed089f1f800ece1) Tobias Warneke *2021-05-25 21:52:01* + +**fixes #1212** + + +[b8ee7](https://github.com/JSQLParser/JSqlParser/commit/b8ee7526375c9d9) Tobias Warneke *2021-05-25 21:45:01* + +**** + + +[1c2ac](https://github.com/JSQLParser/JSqlParser/commit/1c2ac7a4e998e76) Tobias Warneke *2021-05-25 21:32:45* + +**** + + +[68695](https://github.com/JSQLParser/JSqlParser/commit/686958cf0bd758b) Tobias Warneke *2021-05-25 19:42:23* + +**Fix Nested CASE WHEN performance, fixes issue #1162 (#1208)** + +* Fix Nested CASE WHEN performance, fixes issue #1162 +* Apease Codazy +* Apease Codazy + +[42610](https://github.com/JSQLParser/JSqlParser/commit/426102e4cf272ca) manticore-projects *2021-05-25 19:26:30* + +**Add support for casts in json expressions (#1189)** + + +[86b61](https://github.com/JSQLParser/JSqlParser/commit/86b613c72428e0c) Tomer Shay (Shimshi) *2021-05-10 20:00:59* + +**fixes #1185** + + +[2320b](https://github.com/JSQLParser/JSqlParser/commit/2320b1baa6e1dea) Tobias Warneke *2021-05-04 21:11:12* + +**** + + +[53745](https://github.com/JSQLParser/JSqlParser/commit/537452dda91bcc3) Tobias Warneke *2021-05-01 20:57:01* + +**** + + +[002f5](https://github.com/JSQLParser/JSqlParser/commit/002f5966c577366) Tobias Warneke *2021-05-01 19:57:10* + +**supporting/fixing unique inside sql function such as count eg - SELECT count(UNIQUE col2) FROM mytable (#1184)** + +* Co-authored-by: Adhikesavan <radhikesavan@paypal.com> + +[f18e9](https://github.com/JSQLParser/JSqlParser/commit/f18e92eaf4b3bc6) RajaSudharsan Adhikesavan *2021-05-01 19:28:05* + +**Oracle compliant ALTER TABLE ADD/MODIFY deparser (#1163)** + +* javadoc-fixes +* fix check-style error : assignment to parameter not allowed +* import for javadoc reference +* javadoc - add description to parameter "fqn" (fix warning) +* remove doclint=none, but exclude package with exclude package with +* generated sources (javacc/jjtree) from javadoc +* Implement Oracle Hints for INSERT, UPDATE, MERGE, DELETE +* Correct CreateIndex TailOptions +* Add a Test Case for CreateIndex TailOptions +* Add WHERE expression to MergeInsert +* Add test case for MergeInsert WHERE expression +* Fix Issue #1156: ALTER TABLE ADD FOREIGN KEY with schema reference +* Add a specific test case +* Fix Issue #1157: Oracle does not accept COLUMN keyword in ALTER TABLE ADD/MODIFY +* Correct the test cases accepting a non existing COLUMN keyword +* Add a specific test cases +* Fix Issue #1164 UNIQUE after PRIMARY KEY +* Add test case for UNIQUE after PRIMARY KEY +* Switch of warnings for un-fixble method namings +* Switch of warnings for un-fixble method namings +* Activate PMD and define our own ruleset +* Execute PMD before building/testing in order to fail early +* Fix 63 PMD warnings +* Activate rule "PMD.CyclomaticComplexity" in order to simulate the Codazy checks +* Apply @SuppressWarnings({"PMD.CyclomaticComplexity"}) where this rule throws an unavoidable warning (especially for toString() and deparse()) +* Activate rule , "PMD.ExcessiveMethodLength" in order to simulate the Codazy checks +* Apply @SuppressWarnings({"PMD.ExcessiveMethodLength"}) where this rule throws an unavoidable warning (especially for toString() and deparse()) +* Refactor an ENUM name +* Refactor an ENUM name and reflect this also in the JavaCC Parser definition file +* Co-authored-by: gitmotte <www@synbee.at> + +[83837](https://github.com/JSQLParser/JSqlParser/commit/838379f21be0d32) manticore-projects *2021-04-21 07:55:17* + +**Pmd (#1165)** + +* Implement Oracle Hints for INSERT, UPDATE, MERGE, DELETE +* Correct CreateIndex TailOptions +* Add a Test Case for CreateIndex TailOptions +* Add WHERE expression to MergeInsert +* Add test case for MergeInsert WHERE expression +* Fix Issue #1156: ALTER TABLE ADD FOREIGN KEY with schema reference +* Add a specific test case +* Fix Issue #1157: Oracle does not accept COLUMN keyword in ALTER TABLE ADD/MODIFY +* Correct the test cases accepting a non existing COLUMN keyword +* Add a specific test cases +* Fix Issue #1164 UNIQUE after PRIMARY KEY +* Add test case for UNIQUE after PRIMARY KEY +* Switch of warnings for un-fixble method namings +* Switch of warnings for un-fixble method namings +* Activate PMD and define our own ruleset +* Execute PMD before building/testing in order to fail early +* Fix 63 PMD warnings +* Activate rule "PMD.CyclomaticComplexity" in order to simulate the Codazy checks +* Apply @SuppressWarnings({"PMD.CyclomaticComplexity"}) where this rule throws an unavoidable warning (especially for toString() and deparse()) +* Activate rule , "PMD.ExcessiveMethodLength" in order to simulate the Codazy checks +* Apply @SuppressWarnings({"PMD.ExcessiveMethodLength"}) where this rule throws an unavoidable warning (especially for toString() and deparse()) +* Refactor an ENUM name +* Refactor an ENUM name and reflect this also in the JavaCC Parser definition file + +[08cfd](https://github.com/JSQLParser/JSqlParser/commit/08cfd29459044c6) manticore-projects *2021-04-20 08:01:48* + +**function order by support (#1108)** + + +[d6ef7](https://github.com/JSQLParser/JSqlParser/commit/d6ef7b995134594) Роман Зотов *2021-04-20 04:16:03* + +**fixes #1159** + + +[79e2f](https://github.com/JSQLParser/JSqlParser/commit/79e2f587ee11297) Tobias Warneke *2021-04-16 23:51:24* + +**added improvements of pr to readme** + + +[0ef4a](https://github.com/JSQLParser/JSqlParser/commit/0ef4a5c8a105a44) Tobias Warneke *2021-04-16 23:02:51* + +**Assorted fixes to the Java CC Parser definition (#1153)** + +* Implement Oracle Hints for INSERT, UPDATE, MERGE, DELETE +* Correct CreateIndex TailOptions +* Add a Test Case for CreateIndex TailOptions +* Add WHERE expression to MergeInsert +* Add test case for MergeInsert WHERE expression +* Fix Issue #1156: ALTER TABLE ADD FOREIGN KEY with schema reference +* Add a specific test case + +[5ee6e](https://github.com/JSQLParser/JSqlParser/commit/5ee6ec9dd7a66bf) manticore-projects *2021-04-16 22:51:27* + +**** + + +[b880e](https://github.com/JSQLParser/JSqlParser/commit/b880e1663ca607f) Tobias Warneke *2021-04-16 22:49:29* + +**fixes #1138** + + +[e95f6](https://github.com/JSQLParser/JSqlParser/commit/e95f6ce1c5ecca8) Tobias Warneke *2021-04-10 21:36:07* + +**fixes #1138** + + +[cb7a0](https://github.com/JSQLParser/JSqlParser/commit/cb7a018a8c0cd9e) Tobias Warneke *2021-04-10 21:35:53* + +**fixes #1137** + + +[9d676](https://github.com/JSQLParser/JSqlParser/commit/9d676b90c6c1e30) Tobias Warneke *2021-04-10 21:23:00* + +**fixes #1136** + + +[ba9b8](https://github.com/JSQLParser/JSqlParser/commit/ba9b8d7a6f24274) Tobias Warneke *2021-04-10 21:09:19* + +**** + + +[f0bec](https://github.com/JSQLParser/JSqlParser/commit/f0bec22644f99e7) Tobias Warneke *2021-03-22 21:21:13* + +**issue #1134 adressed** + + +[5d9f4](https://github.com/JSQLParser/JSqlParser/commit/5d9f4fdff2e6ce6) Tobias Warneke *2021-03-20 21:35:05* + +**Add support for union_with_brackets_and_orderby (#1131)** + + +[c3a1a](https://github.com/JSQLParser/JSqlParser/commit/c3a1aa688442c1d) Tomer Shay (Shimshi) *2021-03-14 20:10:33* + +**Add support for union without brackets and with limit (#1132)** + +* add support for union without brackets and with limit +* Fixing the last commit. + +[56c2d](https://github.com/JSQLParser/JSqlParser/commit/56c2dfe332b5ee8) Tomer Shay (Shimshi) *2021-03-14 20:09:12* + +**** + + +[d2f61](https://github.com/JSQLParser/JSqlParser/commit/d2f61d138c2c0e3) Tobias Warneke *2021-03-14 20:04:28* + +**Add support for functions in an interval expression (#1099)** + + +[7f8b5](https://github.com/JSQLParser/JSqlParser/commit/7f8b58c1e32a919) Tomer Shay (Shimshi) *2021-03-14 19:55:40* + +**** + + +[bcc68](https://github.com/JSQLParser/JSqlParser/commit/bcc683ab8791b71) Tobias Warneke *2021-02-06 20:37:50* + +**** + + +[7deb6](https://github.com/JSQLParser/JSqlParser/commit/7deb6d9bde678d6) Tobias Warneke *2021-02-05 21:59:11* + +**subArray support arr[1:3] (#1109)** + + +[cde50](https://github.com/JSQLParser/JSqlParser/commit/cde50692c131fff) Роман Зотов *2021-02-05 21:55:29* + +**bug fix (#769)** + +* Co-authored-by: Kunal Jha <kjha@zalando-11116.corp.ad.zalando.net> + +[7234d](https://github.com/JSQLParser/JSqlParser/commit/7234de1d65ccf1b) Kunal jha *2021-02-05 17:46:15* + +**** + + +[089fc](https://github.com/JSQLParser/JSqlParser/commit/089fc44eba26cb1) Tobias Warneke *2021-02-04 19:47:39* + +**Array contructor support (#1105)** + +* Array contructor support array[[1, 2], [id1, id2]] +* ARRAYLITERAL->ARRAY_LITERAL +* Fix empty array +* Support ARRAY as DEFAULT value in CREATE TABLE +* https://github.com/JSQLParser/JSqlParser/issues/970#issue-594819872 +* fix empty Array + +[43c28](https://github.com/JSQLParser/JSqlParser/commit/43c282deaa05555) Роман Зотов *2021-02-04 19:28:49* + +**** + + +[85193](https://github.com/JSQLParser/JSqlParser/commit/8519356a4939816) Tobias Warneke *2021-01-31 22:59:20* + +**Partial support construct tuple as simple expression (#1107)** + +* SELECT (1,2) + +[2065f](https://github.com/JSQLParser/JSqlParser/commit/2065fedb5b4c318) Роман Зотов *2021-01-31 22:58:08* + +**support create table parameters without columns, parameter values any names (#1106)** + +* CREATE TEMPORARY TABLE t1 WITH (APPENDONLY=true,ORIENTATION=column,COMPRESSTYPE=zlib,OIDS=FALSE) ON COMMIT DROP AS SELECT column FROM t2 + +[f2e74](https://github.com/JSQLParser/JSqlParser/commit/f2e74f15cd63d87) Роман Зотов *2021-01-31 22:53:09* + +**fixes #995** + + +[d7b46](https://github.com/JSQLParser/JSqlParser/commit/d7b468a651ab966) Tobias Warneke *2021-01-13 19:21:40* + +**fixes #1100** + + +[ea31a](https://github.com/JSQLParser/JSqlParser/commit/ea31a0480cea00e) Tobias Warneke *2021-01-13 18:58:16* + +**next correction of parenthesis around unions** + + +[5706f](https://github.com/JSQLParser/JSqlParser/commit/5706fb4e1133884) Tobias Warneke *2021-01-11 23:15:21* + +**** + + +[e2ff2](https://github.com/JSQLParser/JSqlParser/commit/e2ff225132bfedd) Tobias Warneke *2021-01-10 00:13:16* + +**fixes #992** + + +[9fd11](https://github.com/JSQLParser/JSqlParser/commit/9fd11563fc86281) Tobias Warneke *2021-01-07 22:34:40* + +**corrected patch for case as table name** + + +[f2638](https://github.com/JSQLParser/JSqlParser/commit/f2638ead2f189c2) Tobias Warneke *2021-01-07 21:57:52* + +**Added support for the Case keyword in table names (#1093)** + + +[b85a2](https://github.com/JSQLParser/JSqlParser/commit/b85a2003bbd9a1a) Tomer Shay (Shimshi) *2021-01-07 21:43:11* + +**** + + +[9785b](https://github.com/JSQLParser/JSqlParser/commit/9785b09cd774e14) Tobias Warneke *2021-01-04 06:45:18* + +**corrected some javadoc parameter** + + +[449b7](https://github.com/JSQLParser/JSqlParser/commit/449b74a67c50700) Tobias Warneke *2021-01-03 22:16:44* + +**added missing pivot test files** + + +[e599b](https://github.com/JSQLParser/JSqlParser/commit/e599bd957b2a70f) Tobias Warneke *2021-01-03 21:07:06* + +**fixes #282 - first refactoring to allow with clause as a start in insert and update** + + +[d4402](https://github.com/JSQLParser/JSqlParser/commit/d4402df3ef4978d) Tobias Warneke *2021-01-02 23:57:26* + +**fixes #282 - first refactoring to allow with clause as a start in insert and update** + + +[e6d65](https://github.com/JSQLParser/JSqlParser/commit/e6d65ab3808b9cc) Tobias Warneke *2021-01-02 23:56:12* + +**Update README.md** + + +[54708](https://github.com/JSQLParser/JSqlParser/commit/5470880139cdc94) Tobias *2021-01-02 08:58:01* + +**fixes #887** + + +[74aab](https://github.com/JSQLParser/JSqlParser/commit/74aab7cc81f5665) Tobias Warneke *2021-01-02 00:04:43* + +**fixes #1091 - added H2 casewhen function with conditional parameters** + + +[085e1](https://github.com/JSQLParser/JSqlParser/commit/085e120d4221f1a) Tobias Warneke *2021-01-01 23:49:30* + +**fixes #1091 - added H2 casewhen function with conditional parameters** + + +[e5e7d](https://github.com/JSQLParser/JSqlParser/commit/e5e7d376fc641a9) Tobias Warneke *2021-01-01 23:46:03* + +**** + + +[1eaa1](https://github.com/JSQLParser/JSqlParser/commit/1eaa1ba88028f79) Tobias Warneke *2021-01-01 23:18:55* + + +## jsqlparser-4.0 (2021-01-01) + +### Other changes + +**fixes #961 - allow unsigned as type** + + +[7783e](https://github.com/JSQLParser/JSqlParser/commit/7783e05d024b006) Tobias Warneke *2020-12-31 01:49:42* + +**fixes #961 - allow unsigned as type** + + +[67a33](https://github.com/JSQLParser/JSqlParser/commit/67a331e0052527a) Tobias Warneke *2020-12-31 01:46:19* + +**fixes #1006 - included limit / offset test** + + +[b5514](https://github.com/JSQLParser/JSqlParser/commit/b55141b0bdb975d) Tobias Warneke *2020-12-31 00:59:36* + +**fixes #1013 - refactored fromitem grammar to drastically improve performance** + + +[36d0b](https://github.com/JSQLParser/JSqlParser/commit/36d0b7420fe9225) Tobias Warneke *2020-12-31 00:47:09* + +**** + + +[05a6f](https://github.com/JSQLParser/JSqlParser/commit/05a6f4b3cb719e6) Tobias Warneke *2020-12-30 23:12:55* + +**** + + +[b2c60](https://github.com/JSQLParser/JSqlParser/commit/b2c6097ab0a713e) Tobias Warneke *2020-12-30 22:50:48* + +**fixes #1088 - allowed CURRENT as jdbc named parameter name** + + +[4f925](https://github.com/JSQLParser/JSqlParser/commit/4f925c54cd89e12) Tobias Warneke *2020-12-30 22:12:28* + +**fixes #1089 - just included test case** + + +[4183a](https://github.com/JSQLParser/JSqlParser/commit/4183ae0a55a9455) Tobias Warneke *2020-12-30 21:45:32* + +**** + + +[f484d](https://github.com/JSQLParser/JSqlParser/commit/f484de7c4813cf9) Tobias Warneke *2020-12-18 22:15:09* + +**** + + +[10a69](https://github.com/JSQLParser/JSqlParser/commit/10a69a2dd873053) Tobias Warneke *2020-12-18 22:13:16* + +**fixes #1080** + + +[d9282](https://github.com/JSQLParser/JSqlParser/commit/d928268fb61c088) Tobias Warneke *2020-12-17 20:17:14* + +**Update README.md** + + +[624f2](https://github.com/JSQLParser/JSqlParser/commit/624f247eaab9a54) Tobias *2020-12-16 10:08:46* + +**fixes #926** + + +[97ab8](https://github.com/JSQLParser/JSqlParser/commit/97ab8e9b6cf4af8) Tobias Warneke *2020-12-11 22:13:14* + +**tested** + + +[d9da6](https://github.com/JSQLParser/JSqlParser/commit/d9da64bd9ac032b) Tobias Warneke *2020-12-06 11:53:35* + +**tested** + + +[875f7](https://github.com/JSQLParser/JSqlParser/commit/875f769e4ba353c) Tobias Warneke *2020-12-06 11:52:16* + +**upgraded to javacc 7.0.10, this time the lookahead seems to be working** + + +[881e4](https://github.com/JSQLParser/JSqlParser/commit/881e457d7520aab) Tobias Warneke *2020-11-30 06:35:59* + +**upgraded to javacc 7.0.10, this time the lookahead seems to be working** + + +[eae2e](https://github.com/JSQLParser/JSqlParser/commit/eae2e0d450c88c0) Tobias Warneke *2020-11-30 06:34:55* + +**fixes #1065** + + +[e0b3a](https://github.com/JSQLParser/JSqlParser/commit/e0b3a180da5b1f8) Tobias Warneke *2020-11-22 19:39:48* + +**support IN with value (#1065)** + +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> +* Co-authored-by: Tobias <t.warneke@gmx.net> + +[8c7ee](https://github.com/JSQLParser/JSqlParser/commit/8c7ee289e78d07d) Jan Monterrubio *2020-11-22 19:29:27* + +**fixes #1074** + + +[ece8a](https://github.com/JSQLParser/JSqlParser/commit/ece8a5a9e39abff) Tobias Warneke *2020-11-22 19:14:52* + +**fixes #1075** + + +[b74f5](https://github.com/JSQLParser/JSqlParser/commit/b74f53228295d96) Tobias Warneke *2020-11-22 19:08:39* + +**** + + +[1008e](https://github.com/JSQLParser/JSqlParser/commit/1008ebcc5a806b9) Tobias Warneke *2020-11-06 22:01:54* + +**Support CreateSynonym statement (#1064)** + +* visual +* add synonym support +* add tests +* exclude keyword +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[17e26](https://github.com/JSQLParser/JSqlParser/commit/17e2633e46778c6) Jan Monterrubio *2020-11-06 21:45:14* + +**** + + +[d5258](https://github.com/JSQLParser/JSqlParser/commit/d5258232ea77690) Tobias Warneke *2020-11-06 21:34:08* + +**Validation visitor framework (#1045)** + +* * add with prefix for fluent setters. +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* add getters +* * add with prefix for fluent setters. (revert to chaining setters, do +* not break current api) +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add with prefix for fluent setters. (revert to chaining setters, do +* not break current api) +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* remove create() methods - they do not add enough value to be justified +* * use new methods within testcases +* add some constructors +* fix and add "with" / "add" methods +* * use new methods within testcases +* * use new methods within testcases +* add some constructors +* * renamed constant +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* * use new methods within testcases +* add some with-methods +* add getter/setter named after the field without abbrivation +* * use new methods within testcases +* remove empty implicit constructor +* return the deparsed Statement - object +* compare object tree +* compare object tree +* * fix ObjectTreeToStringStyle +* compare object tree +* remove casts not needed +* * use new methods within testcases +* add some "set" "with" "add" methods missing +* * use new methods within testcases +* add empty constructors and override with-/add-methods returning concrete +* type +* * add ReflectionModelTest +* * use new methods within testcases +* fix checkstyle errors +* license header +* remove test-classes from ReflectionModelTest +* remove visitoradapter-classes from ReflectionModelTest +* * add SelectDeParser(StringBuilder) +* remove overriding setters/getters of buffer +* #1007 +* push to synbee-contrib +* org.synbee.commons.contrib:jsqlparser:3.2-0.0.6-SNAPSHOT +* add ValidationUtil for simple validation of one or more statements +* remove overrides of +* getCause +* printStackTrace variants +* why add an additional cause ? +* set cause.getMessage() the message within constructor +* JSQLParserException(Throwable cause), othewise cause.toString() will be +* set as default. +* add ValidationVisitor showcase +* https://github.com/JSQLParser/JSqlParser/issues/1005 +* add ValidationUtil for simple validation of one or more statements +* remove overrides of +* getCause +* printStackTrace variants +* why add an additional cause ? +* set cause.getMessage() the message within constructor +* JSQLParserException(Throwable cause), othewise cause.toString() will be +* set as default. +* visit(ShowTablesStatement) +* copyright/license +* add stubs (use deparsers as template) +* Merge branch 'master.validate' of +* https://github.com/gitmotte/JSqlParser.git into master.validate +* add ValidationVisitor showcase +* https://github.com/JSQLParser/JSqlParser/issues/1005 +* add ValidationUtil for simple validation of one or more statements +* remove overrides of +* getCause +* printStackTrace variants +* why add an additional cause ? +* set cause.getMessage() the message within constructor +* JSQLParserException(Throwable cause), othewise cause.toString() will be +* set as default. +* visit(ShowTablesStatement) +* add stubs (use deparsers as template) +* Merge branch 'master.validate' of +* https://github.com/gitmotte/JSqlParser.git into master.validate +* add tests for ValidationUtil +* + implements OrderByVisitor +* split Expressionvalidator which implements both ItemsListVisitor and +* Expressionvisitor into Expressionvalidator and ItemListValidator +* Merge branch 'github.validate' +* implement upsertvalidator +* add copyright +* validate through given ValidationCapability's +* * switch to new method forced by +* ValidationCapability.validate(ValidationContext context, +* Consumer<String> errorMessageConsumer); +* add AllowedTypesValidation +* add FeatureConfiguration +* use FeatureConfiguration within parser +* repair pom.xml +* repair pom.xml +* repair pom.xml +* repair pom.xml +* * make FeatureConfiguration not a singleton any more +* CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> +* add FeaturesAllowed for testing against features allowed +* implement some Validators +* basic implementation of DatabaseMetaDataValidation / +* JdbcDatabaseMetaDataCapability +* moving classes to sub-packages +* * moving classes to sub-packages +* fixing some bugs +* repair pom.xml +* add and fix validations +* add javadoc +* * force definition of ```public String getMessage(Feature feature)``` +* in FeatureSetValidation +* allow all objects as feature-value - this may be needed by the parser, +* if a none-boolean configuration is needed +* impl. +* SelectValidator.visit(PlainSelect) +* OrderByValidator +* add Version-enums +* impl. +* InsertValidator +* multiple implementations of visit(SubSelect) -> forward to +* SelectValidator +* add some known features to SqlServerVersion +* refactoring enum-name should be upper case +* add ansi sql enum +* refactoring enum-name should be upper case +* implement limitvalidator +* + validateOffset +* + validateFetch +* + validate Pivot, UnPivot, PivotXml +* + implement DropValidator +* change testcase to image a more probably usecase +* * add javadoc and +* predefined sets for EXECUTE, ALTER, DROP +* allow to combine FeatureSets +* * implement executevalidator +* implement ExpressionValidator +* implement GrantValidator +* javadoc and complete SELECT constant +* use utility methods from AbstractValidator +* more user friendly names +* javadoc +* add subtypes for ValidationException +* ValidationParseException +* DatabaseException +* UnexpectedValidationException +* and change Set<String> errors to Set<ValidationException> for collect. +* javadoc & rename exception +* rename method +* extract parsing task into package - private class for {@link +* ValidationUtil} to parse the statements +* within it's own {@link ValidationCapability} +* add null-check for parsedStatement +* bugfix - do not collect duplicates +* implement toString() for +* ValidationError +* ValidationException +* add simple caching +* + validateOptionalFromItem(s) +* * implement GroupByValidator +* implement merge-validator +* renaming ItemListValidator -> ItemsListValidator +* + validateOptionalItemsList +* + implement ReplaceValidator +* + use validateOptionalColumns, validateOptionalExpression where possible +* * remove validateOptionalColumns -> switch to +* validateOptionalExpressions +* move validateOptionalOrderByElements to AbstractValidator +* add validateOptional in AbstractValidator +* add validateOptionalList in AbstractValidator +* + SetStatementValidator +* + ValuesStatementValidator +* + UseStatementValidator +* * implement UpdateValidator +* * implement ShowStatementValidator/ShowColumnsStatementValidator +* * implement UpdateValidator +* * add Feature.jdbcParameter, Feature.jdbcNamedParameter, to all +* featuresets +* + Version.getFeaturesClone +* add javadoc to Version-enum-constructors +* + validateOptionalFeature +* * implement DeleteValidator +* ... +* fix typo +* small optimization +* * move method getFeaturesClone to FeatureSet +* implement join - validation +* add copy(), add(Collection), remove(*) methods to FeaturesAllowed +* * add join - features to sqlserver, h2 +* implementations +* bugfix - merging the errors +* copyright +* https://github.com/JSQLParser/JSqlParser/issues/1022 +* add more fine granular control for setOperations +* fix nullpointerexception +* add more fine granular control for comments +* add Features supported +* * add javadoc +* add features to *Version-files +* extract methods isNotEmpty +* check for isNotEmpty +* * add features to *Version-files +* always parse net.sf.jsqlparser.statement.Statements and validate the +* list of included net.sf.jsqlparser.statement.Statement's +* add known mariadb features +* new names-set for FeaturesAllowed +* new names-set for FeaturesAllowed +* new names-set for FeaturesAllowed +* add ature.withItem, Feature.withItemRecursive to H2 +* Feature.setOperation, Feature.setOperationUnion, +* Feature.setOperationIntersect, Feature.setOperationExcept, +* for MariaDb +* add features to SQLServer +* Merge branch 'master.orig' into github.validate +* @Override() -> @Override +* fix typing error "joinStaight" > joinStraight +* rename Feature "insertValues" -> "values" and use "insertValues" for +* INSERT INTO ... VALUES +* add javadoc +* add Feature.selectGroupByGroupingSets to PostgresqlVersion +* implement basic OracleVersion +* add Feature.mySql* - also supported by mariadb +* add some more finegraned control over "drop" Feature. +* drop, +* dropTable, +* dropIndex, +* dropView, +* dropSchema, +* dropSequence, +* dropIfExists, +* complete FeaturesAllowed groups INSERT/UPDATE/DELETE/MERGE/DML +* add link to documentation +* fix - duplicate use of feature "function" - the use of functions in +* statements and "createFunction" as a ddl statement +* TODO this feature seams very close to a jsqlparser-user usecase +* * implement MySqlVersion +* replace feature Feature.dropIfExists by features dropTableIfExists, +* dropIndexIfExists, dropViewIfExists, dropSchemaIfExists, +* dropSequenceIfExists +* add methods FeatureSet.getNotContained FeatureSet.retainAll +* remove HSQLDBVersion - do not support this variant +* remove HSQLDBVersion - do not support this variant +* add unit-test +* + add unittests for +* UpdateValidator +* DeleteValidator +* add stubs for all other Validator-classes +* + ModifyableFeatureSet +* add some utility-methods in ValidationTestAsserts +* complete unit-tests for InsertValidator +* remote Feature.insertReturningExpressionList for Oracle - +* returning_clause requires INTO clause (only PL/SQL) +* add some more select validation tests +* add DropValidatorTests +* add DropValidatorTests +* add CreateTableValidatorTests +* add CreateTableValidatorTests +* add ExpressionValidatorTests +* add OrderByValidatorTest +* use isNotEmpty +* implement GroupByValidatorTest +* implement CreateSequenceValidatorTest +* remove @Ignore - test is ok +* implement CreateIndexValidatorTest +* implement CreateViewValidatorTest +* enable validation of Feature.commentOnView (#1024 is merged already) +* change format of #toString() for better readability +* * implement MergeValidatorTest +* implement ReplaceValidatorTest +* implement StatementValidatorTest +* rename +* ValidationUtil -> Validation +* ValidatorUtil -> ValidationUtil +* add testcases for ValidationUtil +* add DatabaseMetaDataValidationTest +* checkstyle fix +* add copyright statement +* add unit-tests for show tables, show column, show statements +* * add ExecuteValidatorTest +* as there is a difference between execute <procedure> and execute +* [immediate] <dynamic sql> with USING expr, ... remove support for +* execute on MYSQL, MARIADB, ORACLE +* * add ExecuteValidatorTest for CALL fnName (mysql, mariadb, postgres) +* add upsertvalidatortest +* add GrantValidatorTest +* add AlterSequenceValidatorTest +* add AlterSequenceValidatorTest +* add AlterViewValidatorTest +* add AlterValidatorTest +* replace != null by isNotEmpty on collections +* fix formatting +* add validate commit +* add validate block +* add DeclareStatementValidatorTest +* let NamesLookup implement UnaryOperator<String> +* let NamesLookup implement UnaryOperator<String> +* add javadoc +* add more DatabaseMetaDataValidationTest's +* extract JdbcDatabaseMetaDataCapability.splitAndValidateMinMax +* add pivot/unpivot/pivotxml validation testcases +* add testcase for Feature.tableFunction +* add test for lateral joins and subjoins +* add testValidationRowMovementOption +* add values validator test +* move tests to LimitValidatorTest +* move tests to UseStatementValidatorTest +* add tests for SET - statements +* fix checkstyle error +* new serialVersionUID +* add validation for NamedObject not existing +* need table/view reference to validate column names +* fix typo +* fix errormessage (Arrays.toString(types)) +* add trigger, alias +* return null, instead of throwing exception, if not found +* extract NamesLookup to own file (jdk-bug enum inner classes) +* fix name-check AlterOperation.ALTER +* fix error message +* remove methods not needed (they only delegate to ValidationContext) +* add tests - validate metadata +* fix compile error +* fix columnExists check - depending on the statement the prefix is an +* alias, a table/view or it has no prefix (need to lookup within all +* related tables/views) +* fix javadoc warnings + +[8c735](https://github.com/JSQLParser/JSqlParser/commit/8c735be5b179e51) gitmotte *2020-11-06 21:12:25* + +**Support Create table LIKE (#1066)** + +* fixes #413 +* add coverage +* Co-authored-by: chyun <chyun_wu@163.com> + +[ac746](https://github.com/JSQLParser/JSqlParser/commit/ac7462286ae15b9) Chyun *2020-11-06 21:05:09* + +**fixes #1068** + + +[f1cf0](https://github.com/JSQLParser/JSqlParser/commit/f1cf0abc11ed783) Tobias Warneke *2020-11-06 20:59:19* + +**Bump junit from 4.12 to 4.13.1 (#1063)** + +* Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. +* - [Release notes](https://github.com/junit-team/junit4/releases) +* - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) +* - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) +* Signed-off-by: dependabot[bot] <support@github.com> +* Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +[f9a11](https://github.com/JSQLParser/JSqlParser/commit/f9a115c582dd59b) dependabot[bot] *2020-10-13 12:26:17* + +**fixes #1062** + + +[80e28](https://github.com/JSQLParser/JSqlParser/commit/80e2891e8a79402) wumpz *2020-10-11 19:59:03* + +**corrected a test failure** + + +[bc0e5](https://github.com/JSQLParser/JSqlParser/commit/bc0e5b913fc4f61) wumpz *2020-10-06 21:07:00* + +**support FILTER not only for window function (#1046)** + +* support FILTER not only for window function +* Fixed imports + +[f32fa](https://github.com/JSQLParser/JSqlParser/commit/f32fa6137d6161b) Роман Зотов *2020-10-05 19:45:36* + +**fixes #1059** + + +[3e84a](https://github.com/JSQLParser/JSqlParser/commit/3e84a377b488960) wumpz *2020-10-04 20:43:42* + +**** + + +[6b35e](https://github.com/JSQLParser/JSqlParser/commit/6b35e2fc4f39083) wumpz *2020-10-04 20:17:54* + +**fixes #1055 - added simple jdbc parameter to interval expression** + + +[68659](https://github.com/JSQLParser/JSqlParser/commit/686599b199d6d49) wumpz *2020-10-04 20:16:04* + +**Retain original value in TimestampValue (#1057)** + +* Co-authored-by: Enrico Olivelli <enrico.olivelli@diennea.com> + +[622f9](https://github.com/JSQLParser/JSqlParser/commit/622f9aebb3ebce7) Enrico Olivelli *2020-10-04 19:51:01* + +**fixes #1053** + + +[45aa8](https://github.com/JSQLParser/JSqlParser/commit/45aa8f853a10779) wumpz *2020-10-04 19:42:23* + +**Addons/fixes for Fluent API (#1049)** + +* fix unittests for setter/wither methods with primitive arguments +* add missing withAscDescPresent + +[8165e](https://github.com/JSQLParser/JSqlParser/commit/8165e29cb081080) gitmotte *2020-10-04 19:20:43* + +**fixes #1040** + + +[3f516](https://github.com/JSQLParser/JSqlParser/commit/3f5165122bc9824) wumpz *2020-09-27 21:12:11* + +**xmlserialize support patch for optional order by part** + + +[3747f](https://github.com/JSQLParser/JSqlParser/commit/3747f1c00503b54) wumpz *2020-09-10 21:21:47* + +**xmlserialize support patch for expressions** + + +[8c4e0](https://github.com/JSQLParser/JSqlParser/commit/8c4e0ca141656fd) wumpz *2020-09-08 20:35:36* + +**Make UnPivot.getUnPivotInClause() return List (#1039)** + + +[abedc](https://github.com/JSQLParser/JSqlParser/commit/abedce539515638) MoonFruit *2020-09-07 11:32:37* + +**xmlserialize support** + + +[b580a](https://github.com/JSQLParser/JSqlParser/commit/b580a093c2edda6) wumpz *2020-09-05 22:00:43* + +**** + + +[536fb](https://github.com/JSQLParser/JSqlParser/commit/536fb0348ae985e) wumpz *2020-08-30 20:23:52* + +**bugfix issue #1036: supporting DROP SEQUENCE (#1037)** + + +[e5cd7](https://github.com/JSQLParser/JSqlParser/commit/e5cd7c83e15f7f9) suiwenbo *2020-08-30 20:16:20* + +**modified Condition production to be more performant** + + +[3d7f5](https://github.com/JSQLParser/JSqlParser/commit/3d7f55c48a8dfae) wumpz *2020-08-29 22:30:01* + +**bugfix #720 #991: supporting SELECT "conditions" (#1032)** + +* bugfix issue #1020: JSON type in MySQL not supported in v3.2 +* bugfix issue #720 #991: supporting SELECT "CONDITIONS" + +[9e26b](https://github.com/JSQLParser/JSqlParser/commit/9e26b76ddbc626f) suiwenbo *2020-08-25 22:29:41* + +**** + + +[81523](https://github.com/JSQLParser/JSqlParser/commit/815235606244b01) wumpz *2020-08-23 20:33:42* + +**setting version to 4-SNAPSHOT** + + +[85286](https://github.com/JSQLParser/JSqlParser/commit/852860985832c4c) wumpz *2020-08-23 20:32:33* + +**Fluent builder api #1004 (#1014)** + +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* create(...) methods +* chaining - methods returning "this" +* overwrite chaining - methods of abstract parents/interfaces for +* returning concrete type +* add<Name> methods on collection-fields with varargs-parameter +* add public T get<Name>(Class<T>) - casting and returning an inner +* interface-type +* 1004 add chaining - methods returning "this" +* #1004 add chaining - methods returning "this" +* * add<Name> methods on collection-fields with varargs-parameter +* add<Name> methods on collection-fields with collection-parameter +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add chaining - methods returning "this" +* add<Name> methods on collection-fields with varargs-parameter +* add<Name> methods on collection-fields with collection-parameter +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add public T get<Name>(Class<T>) - casting and returning the concrete +* type +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add public T get<Name>(Class<T>) - casting and returning the concrete +* type (swap Class<? extends E> for Class<E>) +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * overwrite chaining - methods of abstract parents/interfaces for +* returning concrete type +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add with prefix for fluent setters. +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* add getters +* * add with prefix for fluent setters. (revert to chaining setters, do +* not break current api) +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* * add with prefix for fluent setters. (revert to chaining setters, do +* not break current api) +* https://github.com/JSQLParser/JSqlParser/issues/1004 +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* remove create() methods - they do not add enough value to be justified +* * use new methods within testcases +* add some constructors +* fix and add "with" / "add" methods +* * use new methods within testcases +* * use new methods within testcases +* add some constructors +* * renamed constant +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* use new methods within testcases +* * use new methods within testcases +* add some with-methods +* add getter/setter named after the field without abbrivation +* * use new methods within testcases +* remove empty implicit constructor +* return the deparsed Statement - object +* compare object tree +* compare object tree +* * fix ObjectTreeToStringStyle +* compare object tree +* remove casts not needed +* * use new methods within testcases +* add some "set" "with" "add" methods missing +* * use new methods within testcases +* add empty constructors and override with-/add-methods returning concrete +* type +* * add ReflectionModelTest +* * use new methods within testcases +* fix checkstyle errors +* license header +* remove test-classes from ReflectionModelTest +* remove visitoradapter-classes from ReflectionModelTest +* remove duplicate import declaration (checkstyle error) +* * fix RandomUtils to support used java.sql.* types +* fix RandomUtils to support enums +* fix RandomUtils to map objects by its interfaces and super-classes +* filter method "setASTNode" - do not test setters (cannot randomly +* create a SimpleNode) +* add javadoc, stating that this is a marker interface +* https://github.com/JSQLParser/JSqlParser/pull/1014#discussion_r454761902 +* revert formatting change +* https://github.com/JSQLParser/JSqlParser/pull/1014#discussion_r454762463 +* change to EXEC_TYPE.EXECUTE just so the assertion didn't change +* https://github.com/JSQLParser/JSqlParser/pull/1014#discussion_r454763565 +* try to revert format changes +* https://github.com/JSQLParser/JSqlParser/pull/1014#discussion_r454800430 +* try to revert format changes +* https://github.com/JSQLParser/JSqlParser/pull/1014#discussion_r454800430 +* remove brackets on @Override() -> @Override +* add with-methods to new fields + +[6cff1](https://github.com/JSQLParser/JSqlParser/commit/6cff161dacc1e6f) gitmotte *2020-08-23 20:07:53* + +**** + + +[02d58](https://github.com/JSQLParser/JSqlParser/commit/02d5837c5ee8c92) wumpz *2020-08-09 21:26:57* + +**** + + +[574a6](https://github.com/JSQLParser/JSqlParser/commit/574a6b7fda44857) wumpz *2020-08-09 21:22:24* + +**Support Foreign Key ON UPDATE CASCADE (#1025)** + +* https://github.com/JSQLParser/JSqlParser/issues/985 +* add 2 unit-tests for given statements +* https://github.com/JSQLParser/JSqlParser/issues/985 +* fix formating (line width) +* https://github.com/JSQLParser/JSqlParser/issues/985 +* * fix nullpointerexceptions +* add more unittest-assertions +* https://github.com/JSQLParser/JSqlParser/issues/985 +* change order to match the same order as in ForeignKeyIndex +* byAction should not throw an exception (is used by deprecated +* string-setters) +* add unit-tests for ReferentialAction within AlterExpression +* fix toString (added bug on refactoring) +* javadoc +* test set from get on null-values too +* refactoring: add and use ReferentialAction() to evaluate enum +* https://github.com/JSQLParser/JSqlParser/issues/985 +* refactoring: fix parser that order of referential actions does not +* matter +* https://github.com/JSQLParser/JSqlParser/issues/985 +* add empty constructor + +[1e88d](https://github.com/JSQLParser/JSqlParser/commit/1e88dd57eb48ebf) gitmotte *2020-08-09 21:01:34* + +**bugfix issue #1020: JSON type in MySQL not supported in v3.2 (#1028)** + + +[685f6](https://github.com/JSQLParser/JSqlParser/commit/685f6fe43fb35d7) suiwenbo *2020-08-09 20:59:52* + +**** + + +[cfe5a](https://github.com/JSQLParser/JSqlParser/commit/cfe5a2e725b555b) wumpz *2020-08-09 20:58:15* + +**Add generated sources to classpath. (#804)** + + +[14fb8](https://github.com/JSQLParser/JSqlParser/commit/14fb80d947d9bf0) Matthieu Vergne *2020-08-09 20:53:38* + +**** + + +[008d9](https://github.com/JSQLParser/JSqlParser/commit/008d9ad7f28a7b9) wumpz *2020-08-09 20:51:34* + +**COMMENT ON VIEW (#1024)** + +* * implement COMMENT ON VIEW +* testcase "testCommentOnView" +* https://github.com/JSQLParser/JSqlParser/issues/1023 +* add more asserts + +[449f5](https://github.com/JSQLParser/JSqlParser/commit/449f55219fc39eb) gitmotte *2020-08-09 20:49:05* + +**fixes #1026** + + +[4f888](https://github.com/JSQLParser/JSqlParser/commit/4f8882dd143469d) wumpz *2020-08-09 20:46:07* + +**fixes #1026** + + +[4c323](https://github.com/JSQLParser/JSqlParser/commit/4c32302d386ec88) wumpz *2020-08-09 20:39:48* + +**fixes #1027** + + +[a923e](https://github.com/JSQLParser/JSqlParser/commit/a923e7e00ef3518) wumpz *2020-08-09 20:31:26* + +**fixes #1029** + + +[db6ac](https://github.com/JSQLParser/JSqlParser/commit/db6acef1c38e09e) wumpz *2020-08-09 19:55:55* + +**fixes #732** + + +[57a7d](https://github.com/JSQLParser/JSqlParser/commit/57a7dcdf2ede8a0) wumpz *2020-07-15 21:07:09* + +**variable assignment implemented** + + +[cdd0f](https://github.com/JSQLParser/JSqlParser/commit/cdd0fa244dadca1) wumpz *2020-07-13 22:03:12* + +**allowed Jdbc named parameters within interval expressions** + + +[869a7](https://github.com/JSQLParser/JSqlParser/commit/869a7b2088ff54f) wumpz *2020-07-12 21:25:43* + +**allowed Jdbc named parameters within interval expressions** + + +[3602c](https://github.com/JSQLParser/JSqlParser/commit/3602c5f6d0a1766) wumpz *2020-07-12 21:25:05* + +**some house keeping** + + +[8bcf2](https://github.com/JSQLParser/JSqlParser/commit/8bcf2dc4f64cde3) wumpz *2020-07-11 20:39:37* + +**fixes #1009** + + +[71d65](https://github.com/JSQLParser/JSqlParser/commit/71d6523f2150bc2) wumpz *2020-07-11 20:30:30* + +**Add show tables support (#1015)** + +* visual +* implement show tables +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[c0373](https://github.com/JSQLParser/JSqlParser/commit/c03733b3cfcb758) Jan Monterrubio *2020-07-11 16:43:42* + +**let all deparsers extend AbstractDeParser (#1007)** + +* let all deparsers extend AbstractDeParser +* * add SelectDeParser(StringBuilder) +* remove overriding setters/getters of buffer +* #1007 + +[2b790](https://github.com/JSQLParser/JSqlParser/commit/2b7909c3be31ca8) gitmotte *2020-07-11 16:40:11* + +**** + + +[ea88e](https://github.com/JSQLParser/JSqlParser/commit/ea88e1b2899176e) wumpz *2020-06-28 19:22:52* + +**** + + +[51e84](https://github.com/JSQLParser/JSqlParser/commit/51e8428d7dcf7dc) wumpz *2020-06-27 23:01:20* + + +## jsqlparser-3.2 (2020-06-28) + +### Other changes + +**** + + +[cd742](https://github.com/JSQLParser/JSqlParser/commit/cd742d3104218ab) wumpz *2020-06-27 22:29:23* + +**partial func support (#1000)** + + +[9df19](https://github.com/JSQLParser/JSqlParser/commit/9df19b9517112b8) Jan Monterrubio *2020-06-25 05:31:27* + +**** + + +[7a19a](https://github.com/JSQLParser/JSqlParser/commit/7a19a9b71c2a44d) wumpz *2020-06-23 21:56:47* + +**Support options for Explain (#996)** + +* visual +* issue-995 +* support verbose +* postgres explain +* tests +* no text +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[13873](https://github.com/JSQLParser/JSqlParser/commit/1387354712285e4) Jan Monterrubio *2020-06-23 21:52:42* + +**** + + +[8c307](https://github.com/JSQLParser/JSqlParser/commit/8c3076efc9544cb) wumpz *2020-06-23 20:45:19* + +**Support multiple lists for an IN clause (#997)** + +* visual +* wip +* cleanup n test +* polish +* lookahead +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[5de4a](https://github.com/JSQLParser/JSqlParser/commit/5de4ae597fbeda3) Jan Monterrubio *2020-06-20 22:10:38* + +**fixes #999** + + +[ce8ee](https://github.com/JSQLParser/JSqlParser/commit/ce8eef8bb6c2526) wumpz *2020-06-20 22:06:17* + +**fixes #999** + + +[325cc](https://github.com/JSQLParser/JSqlParser/commit/325ccb0fc2cf067) wumpz *2020-06-20 21:57:10* + +**Support ALTER SEQUENCE (#980)** + +* support alter sequence +* improve coverage + +[d34c8](https://github.com/JSQLParser/JSqlParser/commit/d34c885ba5a8c93) Jan Monterrubio *2020-05-23 10:16:07* + +**** + + +[779a7](https://github.com/JSQLParser/JSqlParser/commit/779a744a8ab80c7) wumpz *2020-05-23 10:12:52* + +**fixes #984** + + +[38597](https://github.com/JSQLParser/JSqlParser/commit/38597f347c820a7) wumpz *2020-05-16 21:14:26* + +**fixes #984** + + +[60ac1](https://github.com/JSQLParser/JSqlParser/commit/60ac16a98022455) wumpz *2020-05-16 21:00:28* + +**tests for issue** + + +[82894](https://github.com/JSQLParser/JSqlParser/commit/8289406bbcbba45) wumpz *2020-05-14 21:16:52* + +**** + + +[d6bbc](https://github.com/JSQLParser/JSqlParser/commit/d6bbc3fa8a10d58) wumpz *2020-05-08 21:12:13* + +**** + + +[1ee7c](https://github.com/JSQLParser/JSqlParser/commit/1ee7c417bf0936e) wumpz *2020-05-08 20:19:13* + +**fixes #981** + + +[d79b4](https://github.com/JSQLParser/JSqlParser/commit/d79b44db122652e) wumpz *2020-05-08 20:14:21* + +**fixbuild (#978)** + + +[08b94](https://github.com/JSQLParser/JSqlParser/commit/08b9477ef28a377) Jan Monterrubio *2020-04-30 04:42:04* + +**Implement row movement clause for table creation (#974)** + +* visual +* implement row movement +* support row + AS +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[79b5f](https://github.com/JSQLParser/JSqlParser/commit/79b5fe9c5681961) Jan Monterrubio *2020-04-28 07:02:51* + +**Support CREATE SEQUENCE (#977)** + +* wip +* wip, some parsing +* support sequence +* implement feature +* delete issue tests +* compile it + +[a6a3c](https://github.com/JSQLParser/JSqlParser/commit/a6a3c616b8994f1) Jan Monterrubio *2020-04-28 07:01:10* + +**** + + +[ca76f](https://github.com/JSQLParser/JSqlParser/commit/ca76fed4be73522) wumpz *2020-04-19 19:50:28* + +**fixes #962** + + +[3f918](https://github.com/JSQLParser/JSqlParser/commit/3f918501bda7fc4) wumpz *2020-04-18 21:53:14* + +**implement feature (#972)** + +* Co-authored-by: Jan Monterrubio <Jan.Monterrubio@Cerner.com> + +[aee39](https://github.com/JSQLParser/JSqlParser/commit/aee3947757eecf4) Jan Monterrubio *2020-04-17 21:01:22* + +**test method names changed** + + +[2b564](https://github.com/JSQLParser/JSqlParser/commit/2b5647b5af32b74) zhumaliev-rv *2020-04-03 05:31:40* + +**added Oracle GRANT statement** + + +[fa215](https://github.com/JSQLParser/JSqlParser/commit/fa21512ea2f2dd8) zhumaliev-rv *2020-04-02 12:03:43* + +**fixes #855** + + +[f3ecd](https://github.com/JSQLParser/JSqlParser/commit/f3ecdcb1a8fe8b0) wumpz *2020-03-25 22:42:33* + +**fixes #915** + + +[9ce74](https://github.com/JSQLParser/JSqlParser/commit/9ce74e234e09525) wumpz *2020-03-04 22:04:40* + +**fixes #922** + + +[8abd6](https://github.com/JSQLParser/JSqlParser/commit/8abd6e732c926c2) wumpz *2020-03-01 00:00:26* + +**** + + +[65ad8](https://github.com/JSQLParser/JSqlParser/commit/65ad8f9b8b05835) wumpz *2020-02-29 23:22:26* + +**fixes #864** + + +[5783b](https://github.com/JSQLParser/JSqlParser/commit/5783b65f169560a) wumpz *2020-02-15 21:31:55* + +**fixes #701** + + +[8d43f](https://github.com/JSQLParser/JSqlParser/commit/8d43facbc33c803) wumpz *2020-02-15 20:43:38* + +**fixes #945** + + +[ab405](https://github.com/JSQLParser/JSqlParser/commit/ab4054ce5c1917e) wumpz *2020-02-14 23:19:47* + +**fixes #944** + + +[e1ff1](https://github.com/JSQLParser/JSqlParser/commit/e1ff1f09e9ad946) wumpz *2020-02-14 23:02:57* + +**fixes #944** + + +[22117](https://github.com/JSQLParser/JSqlParser/commit/22117c40613778b) wumpz *2020-02-14 22:58:06* + +**introduces sql server hints** + + +[92c74](https://github.com/JSQLParser/JSqlParser/commit/92c74bfb15b18ac) wumpz *2020-02-14 19:40:15* + +**introduces sql server hints** + + +[6a414](https://github.com/JSQLParser/JSqlParser/commit/6a414aa703b9a5b) wumpz *2020-02-14 19:04:41* + +**introduced view keyword** + + +[f12bb](https://github.com/JSQLParser/JSqlParser/commit/f12bb31a14973ac) wumpz *2020-02-12 23:54:37* + +**fixes #909** + + +[9b998](https://github.com/JSQLParser/JSqlParser/commit/9b998d67699bf5c) wumpz *2020-02-02 21:51:56* + +**fixes #930** + + +[4c4a5](https://github.com/JSQLParser/JSqlParser/commit/4c4a5361453c434) wumpz *2020-02-02 21:09:52* + +**fixes #940** + + +[dc93a](https://github.com/JSQLParser/JSqlParser/commit/dc93a07e38341de) wumpz *2020-02-02 20:43:09* + +**fixes #941 again :)** + + +[782dc](https://github.com/JSQLParser/JSqlParser/commit/782dce8d20ce99f) wumpz *2020-02-02 20:22:40* + +**fixes #941** + + +[ce392](https://github.com/JSQLParser/JSqlParser/commit/ce392b3739dcfbb) wumpz *2020-02-01 23:49:17* + +**fixes #924** + + +[d0cd8](https://github.com/JSQLParser/JSqlParser/commit/d0cd8f869bb1173) wumpz *2020-02-01 23:21:52* + +**Update README.md** + + +[a03d2](https://github.com/JSQLParser/JSqlParser/commit/a03d235d91de445) Tobias *2020-02-01 00:34:26* + +**updated some maven plugins** + + +[3ba29](https://github.com/JSQLParser/JSqlParser/commit/3ba29f1fdc76a7a) wumpz *2020-02-01 00:33:17* + +**fixes #936** + +* fixes #938 + +[39e92](https://github.com/JSQLParser/JSqlParser/commit/39e920df15fefd7) wumpz *2020-02-01 00:08:17* + +**fixes #936** + + +[abf44](https://github.com/JSQLParser/JSqlParser/commit/abf440d2be0fbc6) wumpz *2020-01-31 23:47:06* + +**added keyword group to possible object names** + + +[430b3](https://github.com/JSQLParser/JSqlParser/commit/430b3ee8f506173) wumpz *2020-01-27 06:42:20* + +**fixes #923** + + +[775a0](https://github.com/JSQLParser/JSqlParser/commit/775a09b0a763f55) wumpz *2020-01-25 23:09:35* + +**fixes #923** + + +[57d50](https://github.com/JSQLParser/JSqlParser/commit/57d5044a1a1d6bc) wumpz *2020-01-25 23:09:18* + +**started fixing #923** + + +[0f78d](https://github.com/JSQLParser/JSqlParser/commit/0f78dfdf5dfa6a7) wumpz *2020-01-23 23:19:41* + +**fixes #932** + + +[3490e](https://github.com/JSQLParser/JSqlParser/commit/3490e61dbc6b9b0) wumpz *2020-01-23 21:57:59* + +**fixes #918** + + +[3b89c](https://github.com/JSQLParser/JSqlParser/commit/3b89cd28ad893ae) wumpz *2020-01-23 21:26:58* + +**fixes #921** + + +[f4b10](https://github.com/JSQLParser/JSqlParser/commit/f4b10cff44e90f4) wumpz *2020-01-21 07:27:10* + +**fixes #921** + + +[a23d3](https://github.com/JSQLParser/JSqlParser/commit/a23d30bc9425b19) wumpz *2020-01-21 07:26:35* + +**fixes #929** + + +[a3c95](https://github.com/JSQLParser/JSqlParser/commit/a3c95d4712852f2) wumpz *2020-01-21 07:11:38* + +**fixes #928** + + +[0bae6](https://github.com/JSQLParser/JSqlParser/commit/0bae629dba2459c) wumpz *2020-01-21 06:58:58* + +**fixes #927** + + +[62648](https://github.com/JSQLParser/JSqlParser/commit/6264801af1c0bef) wumpz *2020-01-21 06:49:23* + +**fixes #917** + + +[8de0f](https://github.com/JSQLParser/JSqlParser/commit/8de0fd9971b6e07) wumpz *2020-01-05 22:08:03* + +**rewind #910** + + +[9ca4f](https://github.com/JSQLParser/JSqlParser/commit/9ca4f3e63b26353) wumpz *2020-01-03 00:03:35* + +**Adding support for simple expressions in INTERVAL expressions (#910)** + + +[ebac9](https://github.com/JSQLParser/JSqlParser/commit/ebac9dbcadb4df8) Tomer Shay (Shimshi) *2019-12-20 06:14:04* + +**removed null check** + + +[aba6f](https://github.com/JSQLParser/JSqlParser/commit/aba6f3ae2148d51) wumpz *2019-12-18 14:01:17* + +**Update README.md** + + +[6fd3c](https://github.com/JSQLParser/JSqlParser/commit/6fd3c9c0e6fa4b6) Tobias *2019-12-02 15:55:47* + +**** + + +[5be06](https://github.com/JSQLParser/JSqlParser/commit/5be0646d9004b6e) wumpz *2019-12-01 22:12:59* + +**** + + +[82d8f](https://github.com/JSQLParser/JSqlParser/commit/82d8f59db9f1c33) wumpz *2019-12-01 22:12:54* + +**Update README.md** + + +[f7ae7](https://github.com/JSQLParser/JSqlParser/commit/f7ae75ace8ecb98) Tobias *2019-11-27 20:26:12* + +**fixes #899** + +* switched to assertj from hamcrest + +[9707e](https://github.com/JSQLParser/JSqlParser/commit/9707e4f0aacff16) wumpz *2019-11-23 23:18:56* + +**Adding support for casting to SIGNED (#900)** + + +[73b3d](https://github.com/JSQLParser/JSqlParser/commit/73b3d44f16a57c9) Tomer Shay (Shimshi) *2019-11-20 09:39:47* + +**Support parsing SELECT FOR UPDATE NOWAIT - Refer to documents on https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-locking-reads.html#innodb-locking-reads-nowait-skip-locked (#896)** + + +[596e6](https://github.com/JSQLParser/JSqlParser/commit/596e631ff985c10) Yoon Kyong Sik *2019-11-16 10:07:59* + +**added some doc to CCJSqlParserUtil** + + +[5242a](https://github.com/JSQLParser/JSqlParser/commit/5242a18d20a7c2a) wumpz *2019-11-13 08:31:40* + +**Adding support for STRAIGHT_JOIN in the select clause (#861)** + +* Adding support for straight_join in the select clause +* Renaming the field name to reflect that this is a MySQL hint + +[3cdea](https://github.com/JSQLParser/JSqlParser/commit/3cdea6bd3d9ce21) Tomer Shay (Shimshi) *2019-11-09 20:30:54* + +**Update README.md** + + +[a0077](https://github.com/JSQLParser/JSqlParser/commit/a0077a1e3b4c0c1) Tobias *2019-11-08 07:53:42* + +**** + + +[47a94](https://github.com/JSQLParser/JSqlParser/commit/47a944eb4571b02) wumpz *2019-11-06 22:36:04* + + +## jsqlparser-3.1 (2019-11-06) + +### Other changes + +**fixes #344** + + +[43862](https://github.com/JSQLParser/JSqlParser/commit/43862ddf607493d) wumpz *2019-11-06 22:23:56* + +**fixes #344** + + +[782de](https://github.com/JSQLParser/JSqlParser/commit/782de006989e787) wumpz *2019-11-06 22:23:06* + +**Adding support for complex expressions in the ORDER BY clause (#890)** + + +[678ac](https://github.com/JSQLParser/JSqlParser/commit/678ac96b5948175) Tomer Shay (Shimshi) *2019-10-31 07:19:03* + +**fixes #884** + + +[1d8a9](https://github.com/JSQLParser/JSqlParser/commit/1d8a9479ff3fc6f) wumpz *2019-10-26 21:38:48* + +**fixes #880** + + +[7746b](https://github.com/JSQLParser/JSqlParser/commit/7746bbb7ffa8fb4) wumpz *2019-10-26 21:25:47* + +**** + + +[552bf](https://github.com/JSQLParser/JSqlParser/commit/552bf605ec075ec) wumpz *2019-10-26 20:41:45* + +**Added support for Oracle UNPIVOT keyword. (#882)** + +* Added support for Oracle UNPIVOT keyword. +* Back to original version number. +* Updated imports. +* Added missing import. + +[bcc27](https://github.com/JSQLParser/JSqlParser/commit/bcc271870ad767f) Pascal Mulder *2019-10-26 20:35:43* + +**fixes #878** + + +[c2836](https://github.com/JSQLParser/JSqlParser/commit/c2836f6a276879e) wumpz *2019-10-26 20:27:03* + +**fixes #869** + + +[5b781](https://github.com/JSQLParser/JSqlParser/commit/5b78153ad5b8eb1) wumpz *2019-10-18 23:02:59* + +**fixes #876** + + +[144e6](https://github.com/JSQLParser/JSqlParser/commit/144e60b43fd24ab) wumpz *2019-10-18 21:19:50* + +**fixes #866** + + +[25e1d](https://github.com/JSQLParser/JSqlParser/commit/25e1dcc3fc83440) wumpz *2019-10-16 22:44:27* + +**fixes #862** + + +[51c92](https://github.com/JSQLParser/JSqlParser/commit/51c92d89389f780) wumpz *2019-10-16 21:40:42* + +**tests #874** + + +[1ecfc](https://github.com/JSQLParser/JSqlParser/commit/1ecfcbc4abfd054) wumpz *2019-10-16 20:46:13* + +**fixes #865** + + +[8a965](https://github.com/JSQLParser/JSqlParser/commit/8a965554e1005ca) wumpz *2019-10-14 21:12:05* + +**fixes #867** + + +[22229](https://github.com/JSQLParser/JSqlParser/commit/22229459fb65b6f) wumpz *2019-10-09 08:40:11* + +**fixes #867** + + +[6ef7e](https://github.com/JSQLParser/JSqlParser/commit/6ef7ebbad314090) wumpz *2019-10-09 08:38:23* + +**fixes #847** + + +[2147a](https://github.com/JSQLParser/JSqlParser/commit/2147a21b0caee90) wumpz *2019-10-05 22:41:29* + +**allowing start as keyword for column and tablenames** + + +[f9bba](https://github.com/JSQLParser/JSqlParser/commit/f9bba25386300ca) wumpz *2019-10-05 22:39:45* + +**allowing start as keyword for column and tablenames** + + +[cc6a4](https://github.com/JSQLParser/JSqlParser/commit/cc6a4c5cba1e523) wumpz *2019-10-05 22:37:57* + +**fixes #859** + + +[8e61a](https://github.com/JSQLParser/JSqlParser/commit/8e61a1884297af9) wumpz *2019-10-01 06:14:39* + +**Update README.md** + + +[c6441](https://github.com/JSQLParser/JSqlParser/commit/c6441e05b5d3c59) Tobias *2019-09-30 23:04:05* + +**Fixes linkage of SubSelect to Node** + + +[55783](https://github.com/JSQLParser/JSqlParser/commit/557831dc6621141) PGrafkin *2019-09-22 19:02:33* + +**fixes #845** + + +[d6b4e](https://github.com/JSQLParser/JSqlParser/commit/d6b4e4d7bec895a) wumpz *2019-09-20 15:01:04* + +**** + + +[56ddc](https://github.com/JSQLParser/JSqlParser/commit/56ddc2d8fe4e898) wumpz *2019-09-20 14:41:27* + +**fixes #849** + + +[62a03](https://github.com/JSQLParser/JSqlParser/commit/62a0341a35690fe) wumpz *2019-09-20 14:39:58* + +**fixes #848** + + +[1d2c2](https://github.com/JSQLParser/JSqlParser/commit/1d2c261721d0d61) wumpz *2019-09-20 13:05:40* + +**** + + +[484ea](https://github.com/JSQLParser/JSqlParser/commit/484ea9dd02a9c4c) wumpz *2019-09-20 13:05:14* + +**fixes #850** + + +[1cd3c](https://github.com/JSQLParser/JSqlParser/commit/1cd3c27f32aed64) wumpz *2019-09-20 12:26:44* + +**Update README.md** + + +[6191a](https://github.com/JSQLParser/JSqlParser/commit/6191ae0646e1e40) Tobias *2019-08-29 21:32:25* + + +## jsqlparser-3.0 (2019-08-29) + +### Other changes + +**fixes #842** + + +[516ea](https://github.com/JSQLParser/JSqlParser/commit/516ea8a3a6988b0) wumpz *2019-08-26 22:12:59* + +**fixes #750 - duplicate** + + +[dd7ed](https://github.com/JSQLParser/JSqlParser/commit/dd7eda0c4c6ab8c) wumpz *2019-08-19 08:07:41* + +**** + + +[55974](https://github.com/JSQLParser/JSqlParser/commit/55974c31d955565) wumpz *2019-08-14 15:23:23* + +**** + + +[c481c](https://github.com/JSQLParser/JSqlParser/commit/c481ce03c35ea0d) wumpz *2019-08-13 19:44:50* + +**fixes #677** + + +[695d5](https://github.com/JSQLParser/JSqlParser/commit/695d532571c02c1) wumpz *2019-08-13 19:33:14* + +**fixes #378** + + +[7a133](https://github.com/JSQLParser/JSqlParser/commit/7a133446d0c7fe4) wumpz *2019-08-13 19:26:13* + +**fixes #377** + + +[9b6c4](https://github.com/JSQLParser/JSqlParser/commit/9b6c46c376f4591) wumpz *2019-08-13 19:24:23* + +**fixes #489** + + +[27139](https://github.com/JSQLParser/JSqlParser/commit/27139a034edda7b) wumpz *2019-08-13 19:21:27* + +**fixes #648** + +* fixes #638 + +[74e02](https://github.com/JSQLParser/JSqlParser/commit/74e02267404da4e) wumpz *2019-08-13 19:19:12* + +**** + + +[36907](https://github.com/JSQLParser/JSqlParser/commit/36907e4e1295fc1) wumpz *2019-08-11 22:25:40* + +**** + + +[48dbd](https://github.com/JSQLParser/JSqlParser/commit/48dbd58c6ad38bc) wumpz *2019-08-11 20:54:19* + +**** + + +[089e6](https://github.com/JSQLParser/JSqlParser/commit/089e6b4667ca921) wumpz *2019-08-11 20:32:24* + +**** + + +[ca821](https://github.com/JSQLParser/JSqlParser/commit/ca821e5277c8ffd) wumpz *2019-08-11 20:31:58* + +**** + + +[b3cfd](https://github.com/JSQLParser/JSqlParser/commit/b3cfdac1a31a8de) wumpz *2019-08-11 08:36:52* + +**** + + +[d86cb](https://github.com/JSQLParser/JSqlParser/commit/d86cb90b0f0ff5b) wumpz *2019-08-11 08:08:22* + +**** + + +[68d01](https://github.com/JSQLParser/JSqlParser/commit/68d01212af90b3d) wumpz *2019-08-11 08:06:16* + +**fixes #838** + + +[1d1b6](https://github.com/JSQLParser/JSqlParser/commit/1d1b62507670a9b) wumpz *2019-08-09 21:22:53* + +**fixes #826** + + +[7567d](https://github.com/JSQLParser/JSqlParser/commit/7567d25fdabf631) wumpz *2019-08-09 20:59:36* + +**fixes #826** + + +[01296](https://github.com/JSQLParser/JSqlParser/commit/01296c302471a9c) wumpz *2019-08-09 20:49:18* + +**** + + +[30619](https://github.com/JSQLParser/JSqlParser/commit/30619d8f214d876) wumpz *2019-08-09 14:07:15* + +**Delete ISSUE_TEMPLATE.md** + + +[9bea1](https://github.com/JSQLParser/JSqlParser/commit/9bea1e3850e2078) Tobias *2019-08-09 06:31:24* + +**Update issue templates** + + +[1182e](https://github.com/JSQLParser/JSqlParser/commit/1182e8b792beac4) Tobias *2019-08-09 06:31:05* + +**fixes #828** + + +[5139f](https://github.com/JSQLParser/JSqlParser/commit/5139fb279960013) wumpz *2019-08-08 21:16:23* + +**fixes #828** + + +[8d0de](https://github.com/JSQLParser/JSqlParser/commit/8d0dec177748bdf) wumpz *2019-08-08 21:11:19* + +**** + + +[c766e](https://github.com/JSQLParser/JSqlParser/commit/c766ebce151708c) wumpz *2019-08-07 23:24:17* + +**** + + +[1a732](https://github.com/JSQLParser/JSqlParser/commit/1a732025a27872d) wumpz *2019-08-07 23:22:23* + +**** + + +[5c530](https://github.com/JSQLParser/JSqlParser/commit/5c5303eb8997f03) wumpz *2019-08-07 18:20:34* + +**Updated test** + + +[47457](https://github.com/JSQLParser/JSqlParser/commit/47457ed95a8e688) Tomer S *2019-08-05 20:14:23* + +**Fix issue of missing comma between joins in subjoin** + + +[92db2](https://github.com/JSQLParser/JSqlParser/commit/92db2d81fbed39d) Tomer S *2019-08-05 19:43:18* + +**Fix issue of missing comma between joins in subjoin** + + +[449c4](https://github.com/JSQLParser/JSqlParser/commit/449c4e89c2a9c6a) Tomer S *2019-08-05 19:32:41* + +**** + + +[e586f](https://github.com/JSQLParser/JSqlParser/commit/e586fa31e251221) t.warneke@gmx.net *2019-08-03 23:27:55* + +**Update latest version(1.4 => 2.1)** + + +[5768e](https://github.com/JSQLParser/JSqlParser/commit/5768ea92f63c2ab) yidasanqian *2019-08-02 09:29:48* + +**added linkast to table** + + +[9c5f5](https://github.com/JSQLParser/JSqlParser/commit/9c5f52f3dddb10c) wumpz *2019-08-01 06:44:58* + +**The duration part in INTERVAL expressions can contain a column and not only a constant - now supporting that use case** + + +[5492f](https://github.com/JSQLParser/JSqlParser/commit/5492f5105a75781) Tomer S *2019-07-26 17:15:25* + +**** + + +[1314c](https://github.com/JSQLParser/JSqlParser/commit/1314cd0e7f05543) wumpz *2019-07-22 22:00:36* + +**** + + +[2b944](https://github.com/JSQLParser/JSqlParser/commit/2b944807b6e9058) wumpz *2019-07-22 21:17:54* + +**** + + +[86693](https://github.com/JSQLParser/JSqlParser/commit/86693e0bf34fbf9) wumpz *2019-07-21 21:33:59* + +**proof of correct parsing for #829** + + +[12ff2](https://github.com/JSQLParser/JSqlParser/commit/12ff225b0afd16f) wumpz *2019-07-21 21:27:36* + +**fixes #830** + + +[a416b](https://github.com/JSQLParser/JSqlParser/commit/a416b96e7576dd0) wumpz *2019-07-21 21:11:51* + +**fixes #830** + + +[5fc7c](https://github.com/JSQLParser/JSqlParser/commit/5fc7ce8f6cfeef6) wumpz *2019-07-21 21:08:22* + +**** + + +[914ee](https://github.com/JSQLParser/JSqlParser/commit/914ee73b6de95ae) wumpz *2019-07-21 20:42:54* + +**** + + +[0b404](https://github.com/JSQLParser/JSqlParser/commit/0b404539ab6e985) wumpz *2019-07-21 20:42:38* + +**Update README.md** + + +[216bd](https://github.com/JSQLParser/JSqlParser/commit/216bd3733cacfee) Tobias *2019-07-19 06:23:59* + +**Update README.md** + + +[7077d](https://github.com/JSQLParser/JSqlParser/commit/7077d2148bf9e06) Tobias *2019-07-18 05:58:47* + +**Update README.md** + + +[6148a](https://github.com/JSQLParser/JSqlParser/commit/6148a895113ed5b) Tobias *2019-07-18 05:57:14* + +**Update README.md** + + +[f28b6](https://github.com/JSQLParser/JSqlParser/commit/f28b6252683d2d4) Tobias *2019-07-18 05:56:14* + +**** + + +[34014](https://github.com/JSQLParser/JSqlParser/commit/34014c2b9ac862f) wumpz *2019-07-17 22:46:55* + +**allow jdk 11 build** + + +[73be3](https://github.com/JSQLParser/JSqlParser/commit/73be39017363a4e) wumpz *2019-07-17 22:36:28* + +**allow jdk 11 build** + + +[2cf8e](https://github.com/JSQLParser/JSqlParser/commit/2cf8e15b8987458) wumpz *2019-07-17 22:35:51* + +**fixes limit as name for jdbc named parameters** + + +[7034c](https://github.com/JSQLParser/JSqlParser/commit/7034cb10c6abe11) wumpz *2019-07-17 22:03:55* + +**Update README.md** + + +[bf942](https://github.com/JSQLParser/JSqlParser/commit/bf942f92098f5cc) Tobias *2019-07-12 20:37:33* + +**Update FUNDING.yml** + + +[448da](https://github.com/JSQLParser/JSqlParser/commit/448da80f820a270) Tobias *2019-07-12 20:33:32* + +**Create FUNDING.yml** + + +[73c82](https://github.com/JSQLParser/JSqlParser/commit/73c82ad776db592) Tobias *2019-07-12 20:32:32* + +**** + + +[55f20](https://github.com/JSQLParser/JSqlParser/commit/55f20e07faa13ee) wumpz *2019-07-10 23:12:27* + +**** + + +[27552](https://github.com/JSQLParser/JSqlParser/commit/275522f53782871) wumpz *2019-07-10 21:43:51* + +**moved to java 8** + + +[bfb8e](https://github.com/JSQLParser/JSqlParser/commit/bfb8e274f247350) wumpz *2019-07-09 22:41:18* + +**** + + +[39c6a](https://github.com/JSQLParser/JSqlParser/commit/39c6a4885f7bd20) wumpz *2019-07-09 22:31:35* + +**** + + +[6001f](https://github.com/JSQLParser/JSqlParser/commit/6001fdecada77fa) wumpz *2019-07-09 21:15:42* + +**** + + +[cfc3f](https://github.com/JSQLParser/JSqlParser/commit/cfc3f64850410bc) wumpz *2019-07-09 21:12:01* + +**Support default mode in full text search** + + +[ecb54](https://github.com/JSQLParser/JSqlParser/commit/ecb5464ccb6bab4) Tomer S *2019-07-07 18:04:00* + +**** + + +[0022e](https://github.com/JSQLParser/JSqlParser/commit/0022ef4889f39de) wumpz *2019-07-07 12:11:44* + +**** + + +[694d0](https://github.com/JSQLParser/JSqlParser/commit/694d06ccf707494) wumpz *2019-07-04 21:51:34* + +**Add support for full text search (MATCH..AGAINST)** + + +[6750a](https://github.com/JSQLParser/JSqlParser/commit/6750a5360084439) Tomer S *2019-07-04 21:23:25* + +**** + + +[c88f5](https://github.com/JSQLParser/JSqlParser/commit/c88f5ba08f4ee41) wumpz *2019-07-04 20:51:01* + +**Adding support for IS [NOT] TRUE/FALSE expressions** + + +[00839](https://github.com/JSQLParser/JSqlParser/commit/0083971851df6d4) Tomer S *2019-07-02 21:39:16* + +**Adding support for the DIV operator** + + +[c8bbc](https://github.com/JSQLParser/JSqlParser/commit/c8bbc0f7ecf198e) Tomer S *2019-07-02 19:28:47* + +**fixes #200 - was already fixed, introduced test case** + + +[4d100](https://github.com/JSQLParser/JSqlParser/commit/4d100a7c011abda) wumpz *2019-07-02 12:43:46* + +**fixes #259 - was already fixed, introduced test case** + + +[500ee](https://github.com/JSQLParser/JSqlParser/commit/500ee6e5010fe79) wumpz *2019-07-02 12:40:33* + +**fixes #262 - was already fixed, introduced test case** + + +[dbdfb](https://github.com/JSQLParser/JSqlParser/commit/dbdfb4ea45121c9) wumpz *2019-07-02 12:36:31* + +**fixes #113** + + +[cd16a](https://github.com/JSQLParser/JSqlParser/commit/cd16a6d911fe8b2) wumpz *2019-07-02 12:28:02* + +**** + + +[424c8](https://github.com/JSQLParser/JSqlParser/commit/424c81ce91887d5) wumpz *2019-06-30 19:55:27* + +**** + + +[d6949](https://github.com/JSQLParser/JSqlParser/commit/d6949999cd77c97) wumpz *2019-06-30 17:08:23* + +**Add support for STRAIGHT_JOIN** + + +[89089](https://github.com/JSQLParser/JSqlParser/commit/890898806d2b6b3) Tomer S *2019-04-04 17:15:48* + + +## jsqlparser-2.1 (2019-06-30) + +### Other changes + +**fixes #812** + + +[38aad](https://github.com/JSQLParser/JSqlParser/commit/38aadee9b2a941b) wumpz *2019-06-25 23:07:07* + +**Update README.md** + + +[4763d](https://github.com/JSQLParser/JSqlParser/commit/4763d455148bb75) Tobias *2019-06-25 12:28:29* + +**Update README.md** + + +[334b5](https://github.com/JSQLParser/JSqlParser/commit/334b5498859733d) Tobias *2019-06-25 12:27:52* + +**Support KSQL's WINDOW** + +* Add support for KSQL's WINDOW (HOPPING, TUMBLING and SESSION window) + +[ef911](https://github.com/JSQLParser/JSqlParser/commit/ef9119806146f25) Suyash Garg *2019-06-21 12:00:06* + +**downgraded javacc version to allow java 7 build** + + +[6e7b9](https://github.com/JSQLParser/JSqlParser/commit/6e7b976d65d7eb6) wumpz *2019-06-19 07:33:53* + +**downgraded checkstyle version to allow java 7 build** + + +[a9c29](https://github.com/JSQLParser/JSqlParser/commit/a9c29ffceab9e58) wumpz *2019-06-19 07:29:55* + +**Update README.md** + + +[b5915](https://github.com/JSQLParser/JSqlParser/commit/b59151eae9d2ac5) Tobias *2019-06-16 22:11:11* + +**** + + +[afcc0](https://github.com/JSQLParser/JSqlParser/commit/afcc0a9b2063ade) wumpz *2019-06-16 21:49:09* + +**** + + +[1d203](https://github.com/JSQLParser/JSqlParser/commit/1d203850be1679c) wumpz *2019-06-16 21:06:13* + +**fixes #789** + + +[cdf80](https://github.com/JSQLParser/JSqlParser/commit/cdf805f4028b801) wumpz *2019-06-16 21:02:47* + +**fixes #450** + + +[83dba](https://github.com/JSQLParser/JSqlParser/commit/83dbac2d9841d21) wumpz *2019-06-13 22:11:29* + +**support postgresql create index syntax** + + +[9d74c](https://github.com/JSQLParser/JSqlParser/commit/9d74c6da03976ea) theodore johnson *2019-06-13 22:02:11* + +**fixes #705** + + +[9ce65](https://github.com/JSQLParser/JSqlParser/commit/9ce65cde0f25ae1) wumpz *2019-06-13 21:38:14* + +**site update** + + +[89f20](https://github.com/JSQLParser/JSqlParser/commit/89f202a3062b30a) wumpz *2019-05-29 13:40:18* + +**fixes #798** + + +[dd806](https://github.com/JSQLParser/JSqlParser/commit/dd806991c4283d0) wumpz *2019-05-24 21:09:13* + +**fixes #796** + + +[aecc4](https://github.com/JSQLParser/JSqlParser/commit/aecc41442a8dfd3) wumpz *2019-05-18 21:00:13* + +**fixes #785** + + +[f59f2](https://github.com/JSQLParser/JSqlParser/commit/f59f2b5c9b8e33e) wumpz *2019-05-04 22:54:28* + +**Fix #786 (#787)** + + +[f2aba](https://github.com/JSQLParser/JSqlParser/commit/f2aba0b4ef018a1) Ryan J Murphy *2019-04-22 22:28:38* + +**** + + +[44ff9](https://github.com/JSQLParser/JSqlParser/commit/44ff9ed6bd0d39d) wumpz *2019-04-22 22:28:10* + +**fixes #773 added nextval as a valid object name** + + +[94a2a](https://github.com/JSQLParser/JSqlParser/commit/94a2a40fa7f93a2) wumpz *2019-04-17 08:15:50* + +**** + + +[85a3e](https://github.com/JSQLParser/JSqlParser/commit/85a3e69fed2db1a) wumpz *2019-04-17 07:05:47* + +**** + + +[8d4b3](https://github.com/JSQLParser/JSqlParser/commit/8d4b32a28e3eac1) wumpz *2019-04-17 07:00:01* + +**** + + +[703a7](https://github.com/JSQLParser/JSqlParser/commit/703a7459a529343) wumpz *2019-04-17 06:43:37* + +**recreated "old" javadocs (without improving it)** + + +[74e2a](https://github.com/JSQLParser/JSqlParser/commit/74e2a4b4498088e) wumpz *2019-04-17 06:19:27* + +**recreated "old" javadocs (without improving it)** + + +[4fed7](https://github.com/JSQLParser/JSqlParser/commit/4fed7536c8036ed) wumpz *2019-04-16 07:59:20* + +**JavaDoc for Column#getTable (#782)** + + +[4f500](https://github.com/JSQLParser/JSqlParser/commit/4f500a48572234a) Andrea Arcuri *2019-04-15 12:01:37* + +**** + + +[e2168](https://github.com/JSQLParser/JSqlParser/commit/e2168407d929c77) wumpz *2019-04-13 23:57:14* + +**fixes #777** + + +[35a1c](https://github.com/JSQLParser/JSqlParser/commit/35a1c97f3609007) wumpz *2019-04-12 22:30:00* + +**tests #775** + +* removed some not flags from some classes + +[8dda4](https://github.com/JSQLParser/JSqlParser/commit/8dda4a60a8e558d) wumpz *2019-04-08 21:36:40* + +**tests #754** + + +[97797](https://github.com/JSQLParser/JSqlParser/commit/97797425f635621) wumpz *2019-03-31 21:22:51* + +**fixes #770** + + +[86ea6](https://github.com/JSQLParser/JSqlParser/commit/86ea6016636fe5b) wumpz *2019-03-28 22:19:33* + +**** + + +[f958f](https://github.com/JSQLParser/JSqlParser/commit/f958fa741dea3d0) wumpz *2019-03-20 22:41:16* + +**** + + +[b1da6](https://github.com/JSQLParser/JSqlParser/commit/b1da6e5225a2269) wumpz *2019-03-20 22:37:59* + +**fixes #766** + + +[1bb5c](https://github.com/JSQLParser/JSqlParser/commit/1bb5c3d5823560d) wumpz *2019-03-20 22:05:30* + +**fixes #755 - corrected error introduced due to corrected ExpressionDeParser.** + + +[0002c](https://github.com/JSQLParser/JSqlParser/commit/0002cb717106722) wumpz *2019-03-20 09:57:29* + +**fixes #755** + + +[a6905](https://github.com/JSQLParser/JSqlParser/commit/a690558d1d8f19d) wumpz *2019-03-20 09:38:36* + +**** + + +[aff50](https://github.com/JSQLParser/JSqlParser/commit/aff505390efcb9c) wumpz *2019-03-20 06:46:44* + +**** + + +[7da90](https://github.com/JSQLParser/JSqlParser/commit/7da901adcb0370d) wumpz *2019-03-20 06:45:31* + +**** + + +[18a3c](https://github.com/JSQLParser/JSqlParser/commit/18a3c4acb6f84bb) wumpz *2019-03-20 06:35:17* + +**activated new checkstyle plugin only if used java is at least 1.8** + + +[1b4e9](https://github.com/JSQLParser/JSqlParser/commit/1b4e9957ecd9daf) wumpz *2019-03-17 23:00:12* + +**** + + +[6ceb4](https://github.com/JSQLParser/JSqlParser/commit/6ceb4062d3ccb2c) wumpz *2019-03-16 22:56:17* + +**upgraded checkstyle due to security alert** + + +[cb172](https://github.com/JSQLParser/JSqlParser/commit/cb1726e478d39e6) wumpz *2019-03-16 22:40:36* + +**Fixed typos in README.md (#760)** + + +[67dce](https://github.com/JSQLParser/JSqlParser/commit/67dce2f40b4e484) alterdego *2019-03-14 12:20:26* + +**update README.md (#762)** + +* update latest version(1.4) + +[13d6a](https://github.com/JSQLParser/JSqlParser/commit/13d6a9fe183a5ab) r548 *2019-03-14 12:19:58* + +**** + + +[46323](https://github.com/JSQLParser/JSqlParser/commit/46323b4df4119e6) wumpz *2019-03-12 07:56:12* + + +## jsqlparser-2.0 (2019-03-16) + +### Other changes + +**** + + +[526b9](https://github.com/JSQLParser/JSqlParser/commit/526b90b8d353a01) wumpz *2019-03-16 22:16:01* + +**corrected test** + + +[4ad79](https://github.com/JSQLParser/JSqlParser/commit/4ad79d05b5306c2) wumpz *2019-03-04 18:46:57* + +**fixes #17** + + +[1ef39](https://github.com/JSQLParser/JSqlParser/commit/1ef39301666c3e3) wumpz *2019-03-04 00:26:21* + +**refactored group by expressions into separate class, first step to support grouping sets** + + +[82f3d](https://github.com/JSQLParser/JSqlParser/commit/82f3da8ce946d70) wumpz *2019-03-03 22:25:31* + +**** + + +[749ad](https://github.com/JSQLParser/JSqlParser/commit/749ad556d917a01) wumpz *2019-02-26 23:09:43* + +**Fixes 649 to add support for HOUR, MINUTE, SECOND date literals and support for identifiers as the interval parameter. (#756)** + + +[cbcf0](https://github.com/JSQLParser/JSqlParser/commit/cbcf0a73d516bfc) thebiguno *2019-02-25 22:23:16* + +**** + + +[c85e7](https://github.com/JSQLParser/JSqlParser/commit/c85e79b3cd75119) wumpz *2019-02-24 22:17:37* + +**** + + +[0f9bb](https://github.com/JSQLParser/JSqlParser/commit/0f9bb4e6272f71b) wumpz *2019-02-24 19:59:06* + +**fixes #649** + +* and implemented ! for not and extended not expression + +[10e8e](https://github.com/JSQLParser/JSqlParser/commit/10e8e2568eb7711) wumpz *2019-02-23 23:32:38* + +**** + + +[15297](https://github.com/JSQLParser/JSqlParser/commit/15297868572dba9) wumpz *2019-02-20 23:30:16* + +**** + + +[12c05](https://github.com/JSQLParser/JSqlParser/commit/12c056451444678) wumpz *2019-02-20 23:20:35* + +**** + + +[14f92](https://github.com/JSQLParser/JSqlParser/commit/14f92b13cc4503f) wumpz *2019-02-20 23:05:20* + +**fixes #164** + + +[8c057](https://github.com/JSQLParser/JSqlParser/commit/8c057ab735f0249) wumpz *2019-02-20 22:41:50* + +**fixes #169** + + +[e1193](https://github.com/JSQLParser/JSqlParser/commit/e1193a63a6551ba) wumpz *2019-02-20 21:43:45* + +**fixes #479** + + +[0b5f5](https://github.com/JSQLParser/JSqlParser/commit/0b5f586cf3f9250) wumpz *2019-02-19 22:29:58* + +**fixes #479** + + +[b029b](https://github.com/JSQLParser/JSqlParser/commit/b029bb5860b3ed3) wumpz *2019-02-19 22:28:06* + +**Update README.md** + + +[fa162](https://github.com/JSQLParser/JSqlParser/commit/fa1624165e80895) Tobias *2019-02-19 17:31:13* + +**Added support for DROP INDEX, ADD UNIQUE INDEX, ALGORITHM and USING (#752)** + +* Merge recent changes in the master from the master (#1) +* changed license header to represent the projects dual license +* changed license header to represent the projects dual license +* changed license header to represent the projects dual license +* changed license header to represent the projects dual license +* Added support for comment(s) for column definitions in CREATE TABLE s… (#743) +* Added support for comment(s) for column definitions in CREATE TABLE statements +* Added support for comment(s) for column definitions in CREATE TABLE statements #2 +* To increase code coverage +* To increase code coverage #2 +* Added support for 'ALTER TABLE CHANGE COLUMN' (#741) +* Added support for 'ALTER TABLE CHANGE COLUMN oldName newName columnDefinition'. Please see https://dev.mysql.com/doc/refman/8.0/en/alter-table.html for reference. +* Returned import ordering to avoid conflicts +* Improved the tests somewhat +* Now also test the getOptionalSpecifier() for both cases (null and not-null) +* Expanded tests for ALTER TABLE ... CHANGE +* implemented optimize for, fixes #348 +* implemented optimize for, fixes #348 +* Support for simple informix outer joins. (#745) +* added support for simple informix outer joins +* added some test code +* added support for simple informix outer joins +* added some test code +* more testing for better code coverage +* added support for simple informix outer joins +* added some test code +* more testing for better code coverage +* fixes #747 +* fixes #733 +* fixes #707 +* Update README.md +* Update README.md +* Fix handles the following cases: 1) DROP INDEX 2) ADD UNIQUE INDEX 3) ALGORITHM 4) USING <index type> + +[2830c](https://github.com/JSQLParser/JSqlParser/commit/2830c17ea226635) Prateek Gupta *2019-02-19 00:44:35* + +**fixes #753** + + +[3209a](https://github.com/JSQLParser/JSqlParser/commit/3209a16c55c1976) wumpz *2019-02-19 00:35:14* + +**Update README.md** + + +[4f74f](https://github.com/JSQLParser/JSqlParser/commit/4f74f6d110166a8) Tobias *2019-02-15 21:12:05* + +**Update README.md** + + +[f9609](https://github.com/JSQLParser/JSqlParser/commit/f960991759ed604) Tobias *2019-02-15 21:07:41* + +**fixes #707** + + +[a1c4f](https://github.com/JSQLParser/JSqlParser/commit/a1c4f4a7ddda62e) wumpz *2019-02-14 22:50:16* + +**** + + +[6c413](https://github.com/JSQLParser/JSqlParser/commit/6c413b404b1bd27) wumpz *2019-02-11 23:07:46* + +**fixes #733** + + +[6da69](https://github.com/JSQLParser/JSqlParser/commit/6da696b496eb794) wumpz *2019-02-10 23:11:54* + +**fixes #747** + + +[d3553](https://github.com/JSQLParser/JSqlParser/commit/d3553bc7f8c3b12) wumpz *2019-02-10 23:00:02* + +**** + + +[73305](https://github.com/JSQLParser/JSqlParser/commit/73305fe6a6efec1) wumpz *2019-02-10 22:55:01* + +**** + + +[f79f5](https://github.com/JSQLParser/JSqlParser/commit/f79f58d9f8f5c73) wumpz *2019-02-10 22:38:19* + +**** + + +[154cf](https://github.com/JSQLParser/JSqlParser/commit/154cf371d775b9b) wumpz *2019-02-10 21:54:45* + +**** + + +[80153](https://github.com/JSQLParser/JSqlParser/commit/80153dfdf60f9b4) wumpz *2019-02-10 21:14:10* + +**** + + +[04151](https://github.com/JSQLParser/JSqlParser/commit/0415140ecf58894) wumpz *2019-02-08 07:13:18* + +**Support for simple informix outer joins. (#745)** + +* added support for simple informix outer joins +* added some test code +* added support for simple informix outer joins +* added some test code +* more testing for better code coverage +* added support for simple informix outer joins +* added some test code +* more testing for better code coverage + +[53e24](https://github.com/JSQLParser/JSqlParser/commit/53e247bffdae557) Kurt Schwitters *2019-02-08 05:52:51* + +**** + + +[1a3d2](https://github.com/JSQLParser/JSqlParser/commit/1a3d289238eec35) wumpz *2019-02-07 23:30:55* + +**** + + +[9ec7d](https://github.com/JSQLParser/JSqlParser/commit/9ec7d8572ca0424) wumpz *2019-02-07 23:30:00* + +**** + + +[63477](https://github.com/JSQLParser/JSqlParser/commit/6347776ad571d92) wumpz *2019-02-07 23:25:29* + +**implemented optimize for, fixes #348** + + +[ff23d](https://github.com/JSQLParser/JSqlParser/commit/ff23dde74433355) wumpz *2019-02-07 23:21:22* + +**implemented optimize for, fixes #348** + + +[4b0b5](https://github.com/JSQLParser/JSqlParser/commit/4b0b5cb044bc973) wumpz *2019-02-07 23:19:46* + +**Added support for 'ALTER TABLE CHANGE COLUMN' (#741)** + +* Added support for 'ALTER TABLE CHANGE COLUMN oldName newName columnDefinition'. Please see https://dev.mysql.com/doc/refman/8.0/en/alter-table.html for reference. +* Returned import ordering to avoid conflicts +* Improved the tests somewhat +* Now also test the getOptionalSpecifier() for both cases (null and not-null) +* Expanded tests for ALTER TABLE ... CHANGE + +[bfb80](https://github.com/JSQLParser/JSqlParser/commit/bfb8023318c31b2) Simon *2019-02-07 14:49:28* + +**Added support for comment(s) for column definitions in CREATE TABLE s… (#743)** + +* Added support for comment(s) for column definitions in CREATE TABLE statements +* Added support for comment(s) for column definitions in CREATE TABLE statements #2 +* To increase code coverage +* To increase code coverage #2 + +[07b86](https://github.com/JSQLParser/JSqlParser/commit/07b86761d0b4aee) Prateek Gupta *2019-02-07 07:09:26* + +**changed license header to represent the projects dual license** + + +[b9023](https://github.com/JSQLParser/JSqlParser/commit/b90234f0fc39d34) wumpz *2019-02-06 20:53:15* + +**changed license header to represent the projects dual license** + + +[2adec](https://github.com/JSQLParser/JSqlParser/commit/2adec6ad552f770) wumpz *2019-02-06 20:48:58* + +**changed license header to represent the projects dual license** + + +[4ad99](https://github.com/JSQLParser/JSqlParser/commit/4ad996f778f043b) wumpz *2019-02-06 20:47:19* + +**changed license header to represent the projects dual license** + + +[373c6](https://github.com/JSQLParser/JSqlParser/commit/373c6cb59734091) wumpz *2019-02-05 23:04:45* + +**integrated some additional AST - Nodes for InExpression and SimpleExpressionList** + + +[cb0e0](https://github.com/JSQLParser/JSqlParser/commit/cb0e0b79564258a) wumpz *2019-02-04 01:17:35* + +**** + + +[4e0a7](https://github.com/JSQLParser/JSqlParser/commit/4e0a7326a9d9e9e) wumpz *2019-02-03 23:20:03* + +**case else corrected to allow conditions here as well** + + +[4f7a1](https://github.com/JSQLParser/JSqlParser/commit/4f7a1537e7ba368) wumpz *2019-02-03 22:53:22* + +**refactored outer not from sqlconditions, regularconditions to condition** + + +[aae36](https://github.com/JSQLParser/JSqlParser/commit/aae36da486303f8) wumpz *2019-02-03 21:07:08* + +**refactored outer not from sqlconditions, regularconditions to condition** + + +[1956b](https://github.com/JSQLParser/JSqlParser/commit/1956b84395fcab9) wumpz *2019-02-03 20:57:41* + +**strange not problem** + + +[ba3bf](https://github.com/JSQLParser/JSqlParser/commit/ba3bf2241c1021b) wumpz *2019-02-03 19:57:00* + +**named exec procedure parameters** + + +[82b28](https://github.com/JSQLParser/JSqlParser/commit/82b287dae64ac43) wumpz *2019-02-01 23:51:28* + +**finished multi value set** + + +[479ee](https://github.com/JSQLParser/JSqlParser/commit/479ee39d6efbb6d) wumpz *2019-01-27 00:37:33* + +**finished multi value set** + + +[ba4b0](https://github.com/JSQLParser/JSqlParser/commit/ba4b0ccee2cf20a) wumpz *2019-01-27 00:35:17* + +**started multivalue set** + + +[d991b](https://github.com/JSQLParser/JSqlParser/commit/d991bbe377418a1) wumpz *2019-01-26 00:44:59* + +**corrected typing error. Both licenses could not be applied at the same time.** + + +[7cd18](https://github.com/JSQLParser/JSqlParser/commit/7cd189c326d3d84) wumpz *2019-01-23 23:22:12* + +**allow top keyword as column / table / alias name** + +* implemented tests + +[9e81e](https://github.com/JSQLParser/JSqlParser/commit/9e81e1592200952) wumpz *2019-01-23 23:00:12* + +**allow top keyword as column / table / alias name** + +* implemented tests + +[ed95e](https://github.com/JSQLParser/JSqlParser/commit/ed95e877802f46e) wumpz *2019-01-23 22:58:39* + +**implemented _utf8** + + +[fe28e](https://github.com/JSQLParser/JSqlParser/commit/fe28e88d948dc7e) wumpz *2019-01-23 21:36:42* + +**implemented explain select** + + +[e5c6f](https://github.com/JSQLParser/JSqlParser/commit/e5c6ff6fdf3d4b2) wumpz *2019-01-22 23:28:33* + +**implemented explain select** + + +[fb45d](https://github.com/JSQLParser/JSqlParser/commit/fb45dd7c77ccff0) wumpz *2019-01-22 23:06:34* + +**Add support for casting to signed integer (#734)** + + +[5b00a](https://github.com/JSQLParser/JSqlParser/commit/5b00ace4d49b731) tomershay *2019-01-21 22:58:57* + +**corrected stackoverflow while tables extraction** + +* updated readme + +[04db1](https://github.com/JSQLParser/JSqlParser/commit/04db124b85dea22) wumpz *2019-01-20 22:33:51* + +**implemented DescribeStatement, corrected TableNamesFinder, corrected corresponding interfaces and adapters, implemented tests.** + + +[1c411](https://github.com/JSQLParser/JSqlParser/commit/1c411f490e91f16) wumpz *2019-01-20 22:24:47* + +**started describe** + +* some cleanup + +[25fa3](https://github.com/JSQLParser/JSqlParser/commit/25fa31153a9a2d0) wumpz *2019-01-20 21:48:12* + + +## jsqlparser-1.4 (2019-01-09) + +### Other changes + +**Support Alter Table Add Unique Constraint (#708)** + + +[a54ea](https://github.com/JSQLParser/JSqlParser/commit/a54ea143e7eeffe) Robert Scholte *2018-12-30 23:37:29* + +**corrected some failing tests** + +* included a regression test for oracle files + +[aa932](https://github.com/JSQLParser/JSqlParser/commit/aa932c4a28d8021) wumpz *2018-12-30 23:06:59* + +**Add 'SHOW COLUMNS FROM table' (#728)** + + +[f1724](https://github.com/JSQLParser/JSqlParser/commit/f1724a468577935) Ohad Shai *2018-12-28 11:45:53* + +**Support Alter Table Drop Constraint If Exists (#709)** + +* Support Alter Table Drop Constraint If Exists +* #709 add constraintIfExists flag + +[08fed](https://github.com/JSQLParser/JSqlParser/commit/08fedf752a3f99d) Robert Scholte *2018-12-13 07:14:10* + +**Support Alter Table Alter Column Type (#724)** + + +[b3263](https://github.com/JSQLParser/JSqlParser/commit/b3263c8cbae9296) Robert Scholte *2018-12-13 07:13:12* + +**Support KSQL's WITHIN (#722)** + +* Implements WITHIN for KSQL windowed joins +* Clean up +* Improve test +* Implements WITHIN ( before TimeUnit, after TimeUnit ) for KSQL +* Also restricts TimeUnit to units accepted by KSQL +* WITHIN should come before ON + +[ae665](https://github.com/JSQLParser/JSqlParser/commit/ae665e60655f45f) Lionel Montrieux *2018-12-11 21:53:07* + +**Add support for truncate table (#719)** + + +[11be7](https://github.com/JSQLParser/JSqlParser/commit/11be71561824c36) Bartosz Firyn *2018-12-06 06:41:30* + +**fixes #718** + + +[c0801](https://github.com/JSQLParser/JSqlParser/commit/c0801a742c57ea0) wumpz *2018-12-04 15:23:42* + +**added test for issue #716** + + +[f06b1](https://github.com/JSQLParser/JSqlParser/commit/f06b19769b2eb2a) wumpz *2018-11-22 21:11:12* + +**REPLACE VIEW as a synonym to ALTER VIEW (#711)** + + +[58d39](https://github.com/JSQLParser/JSqlParser/commit/58d3965914376bf) theodore johnson *2018-11-19 14:50:36* + +**Update README.md** + + +[7b6cf](https://github.com/JSQLParser/JSqlParser/commit/7b6cff1222e1314) Tobias *2018-10-26 19:39:58* + +**Update README.md** + + +[78ebf](https://github.com/JSQLParser/JSqlParser/commit/78ebf2093a98fb5) Tobias *2018-10-26 19:38:42* + +**** + + +[22c04](https://github.com/JSQLParser/JSqlParser/commit/22c04947e3834e6) wumpz *2018-10-26 11:12:37* + +**some cleaning up for pr #702** + + +[b7754](https://github.com/JSQLParser/JSqlParser/commit/b7754e8003adec6) wumpz *2018-10-25 12:40:09* + +**support named parameters (#702)** + + +[eacb1](https://github.com/JSQLParser/JSqlParser/commit/eacb161fe848237) theodore johnson *2018-10-25 10:52:41* + +**Added Oracle COMMENT statement (#685)** + + +[e79cc](https://github.com/JSQLParser/JSqlParser/commit/e79ccc61b5bc658) hishidama *2018-10-25 10:40:33* + +**fix JSQLParser/JSqlParser #679 (#703)** + + +[0e35e](https://github.com/JSQLParser/JSqlParser/commit/0e35e224766ebb7) softommy *2018-10-25 10:35:19* + +**fixes #694** + + +[48544](https://github.com/JSQLParser/JSqlParser/commit/48544387cf2e3b5) wumpz *2018-10-18 20:50:58* + +**fixes #675** + + +[d95e0](https://github.com/JSQLParser/JSqlParser/commit/d95e034f4c1b079) wumpz *2018-10-12 22:04:57* + +**** + + +[5aa63](https://github.com/JSQLParser/JSqlParser/commit/5aa6304559a5863) wumpz *2018-10-12 21:26:26* + +**** + + +[295c1](https://github.com/JSQLParser/JSqlParser/commit/295c1147e4ef513) wumpz *2018-10-10 21:02:12* + +**** + + +[a838f](https://github.com/JSQLParser/JSqlParser/commit/a838fec1051db27) wumpz *2018-10-06 23:43:29* + +**fixes #561** + + +[f5982](https://github.com/JSQLParser/JSqlParser/commit/f598213f071d205) wumpz *2018-10-05 20:17:59* + +**fixes #561** + + +[e170c](https://github.com/JSQLParser/JSqlParser/commit/e170c4f17dc9ad7) wumpz *2018-10-05 20:15:58* + +**integrated test for values query** + + +[96499](https://github.com/JSQLParser/JSqlParser/commit/964991c4207c3bf) wumpz *2018-10-04 23:19:12* + +**integrated values statement** + + +[c0327](https://github.com/JSQLParser/JSqlParser/commit/c032744b9e083e0) wumpz *2018-10-04 22:29:11* + +**fixes some lgtm alerts** + + +[de8ad](https://github.com/JSQLParser/JSqlParser/commit/de8ad10a791705e) wumpz *2018-10-04 08:14:00* + +**fixes #684 (second)** + + +[2742a](https://github.com/JSQLParser/JSqlParser/commit/2742a889c4c4f0b) wumpz *2018-10-03 19:40:47* + +**Update README.md** + + +[77026](https://github.com/JSQLParser/JSqlParser/commit/770264da8955512) Tobias *2018-10-02 22:17:03* + + +## jsqlparser-1.3 (2018-10-02) + +### Other changes + +**fixes #684** + + +[a8b3e](https://github.com/JSQLParser/JSqlParser/commit/a8b3e71a88735dc) wumpz *2018-10-02 21:59:16* + +**fixes #682** + + +[c2833](https://github.com/JSQLParser/JSqlParser/commit/c28331102e5754e) wumpz *2018-09-20 05:48:34* + +**Add LGTM.com code quality badges (#680)** + + +[3f620](https://github.com/JSQLParser/JSqlParser/commit/3f620c9e2ddeeb4) Xavier RENE-CORAIL *2018-09-15 21:17:16* + +**fixes #670** + +* added testcase, corrected deparser + +[455c5](https://github.com/JSQLParser/JSqlParser/commit/455c5f50671eed9) wumpz *2018-09-10 15:38:54* + +**#670 (#671)** + + +[3950b](https://github.com/JSQLParser/JSqlParser/commit/3950b1962f32043) mgierw *2018-09-10 15:21:40* + +**testcase for #670** + + +[e6b9a](https://github.com/JSQLParser/JSqlParser/commit/e6b9afdb205bf2b) wumpz *2018-09-10 15:13:58* + +**fixes #676** + + +[1786e](https://github.com/JSQLParser/JSqlParser/commit/1786e215474e8da) wumpz *2018-09-08 23:44:37* + +**fixes #676** + + +[e32c5](https://github.com/JSQLParser/JSqlParser/commit/e32c502f91ed04a) wumpz *2018-09-08 22:12:46* + +**** + + +[26b2c](https://github.com/JSQLParser/JSqlParser/commit/26b2c11df4c4ac5) wumpz *2018-09-07 21:59:47* + +**** + + +[0b03c](https://github.com/JSQLParser/JSqlParser/commit/0b03c858b897713) wumpz *2018-09-07 21:48:03* + +**Update README.md (#667)** + +* Fix a couple typos/grammar issues + +[a822f](https://github.com/JSQLParser/JSqlParser/commit/a822fead1b21793) Kai Presler-Marshall *2018-08-29 13:11:41* + +**fixes #665** + + +[b806e](https://github.com/JSQLParser/JSqlParser/commit/b806e9c1897a0f3) wumpz *2018-08-27 06:51:39* + +**fixes #367** + + +[14791](https://github.com/JSQLParser/JSqlParser/commit/1479149af6a0c5c) wumpz *2018-08-25 23:12:32* + +**fixes #367** + + +[f6abb](https://github.com/JSQLParser/JSqlParser/commit/f6abb9e7edec3f1) wumpz *2018-08-25 23:10:45* + +**fixes #367** + + +[01bcb](https://github.com/JSQLParser/JSqlParser/commit/01bcbd5255a0ebd) wumpz *2018-08-25 23:07:14* + +**** + + +[1a90b](https://github.com/JSQLParser/JSqlParser/commit/1a90b16e215ac80) wumpz *2018-08-23 22:11:35* + +**** + + +[bfbfc](https://github.com/JSQLParser/JSqlParser/commit/bfbfc76eb006201) wumpz *2018-08-23 20:26:56* + +**make the CreateTable deparser use the accept/visit schema instead of the toString path (#663)** + + +[68194](https://github.com/JSQLParser/JSqlParser/commit/68194bfd6bf57d1) theodore johnson *2018-08-23 04:21:10* + +**fixes #661** + + +[44ea8](https://github.com/JSQLParser/JSqlParser/commit/44ea8bd33e01f62) wumpz *2018-08-17 06:22:30* + +**Parse Cloud Spanner raw string and byte prefixes (#659)** + +* #656 parse cloud spanner raw string and byte literals +* #656 fixed raw byte string prefix +* #656 fixed test case +* fixed reported codacy issue + +[a57db](https://github.com/JSQLParser/JSqlParser/commit/a57db5d031a5229) Knut Olav Løite *2018-08-14 08:12:26* + +**** + + +[78ff2](https://github.com/JSQLParser/JSqlParser/commit/78ff2ad4bc7496b) wumpz *2018-08-14 08:08:17* + +**** + + +[1d138](https://github.com/JSQLParser/JSqlParser/commit/1d13897883c1448) wumpz *2018-07-26 19:58:18* + +**** + + +[62bfd](https://github.com/JSQLParser/JSqlParser/commit/62bfda765247f41) wumpz *2018-07-26 09:03:10* + +**fixes #643** + + +[dc779](https://github.com/JSQLParser/JSqlParser/commit/dc779cae57b993e) wumpz *2018-07-23 14:57:23* + +**add test, fix style** + + +[98f87](https://github.com/JSQLParser/JSqlParser/commit/98f873e244046ff) theodore johnson *2018-07-16 21:35:35* + +**added a test** + + +[cfa7e](https://github.com/JSQLParser/JSqlParser/commit/cfa7e8986c98701) theodore johnson *2018-07-16 20:09:34* + +**support teradata sortcut for Select** + + +[53c90](https://github.com/JSQLParser/JSqlParser/commit/53c90e9988aec49) theodore johnson *2018-07-11 18:46:52* + +**fix parsing and rendering of Truncate** + + +[f126d](https://github.com/JSQLParser/JSqlParser/commit/f126d1575bc2ea5) theodore johnson *2018-07-11 17:56:14* + +**fixes #273** + + +[6cd54](https://github.com/JSQLParser/JSqlParser/commit/6cd5481af400e20) wumpz *2018-07-06 08:44:03* + +**fixes #273** + + +[12b4a](https://github.com/JSQLParser/JSqlParser/commit/12b4a1ecaa1090c) wumpz *2018-07-06 08:31:55* + +**fixes #573** + + +[3a5a6](https://github.com/JSQLParser/JSqlParser/commit/3a5a625d15d7b30) wumpz *2018-07-06 07:01:12* + +**add support for && operator** + + +[b59b4](https://github.com/JSQLParser/JSqlParser/commit/b59b48ec2e7e88a) Tomer S *2018-07-03 14:19:34* + +**Extract "orderBy" and "Partition" classes from AnalyticExpression.** + + +[8da6e](https://github.com/JSQLParser/JSqlParser/commit/8da6e2e538ceea9) Assaf *2018-06-20 06:41:56* + +**Update README.md** + + +[aff65](https://github.com/JSQLParser/JSqlParser/commit/aff651624e6fb48) Tobias *2018-06-18 06:22:15* + +**fixes #608** + + +[d529c](https://github.com/JSQLParser/JSqlParser/commit/d529c82d24cbaba) wumpz *2018-06-17 09:57:15* + +**fixes #608** + + +[3f5e3](https://github.com/JSQLParser/JSqlParser/commit/3f5e3c9805bd2fe) wumpz *2018-06-17 09:48:18* + +**fixes #163** + + +[6d954](https://github.com/JSQLParser/JSqlParser/commit/6d95472726574cc) wumpz *2018-06-17 09:39:36* + +**fixes #163** + + +[1db3f](https://github.com/JSQLParser/JSqlParser/commit/1db3ff5f9b5837b) wumpz *2018-06-17 09:33:54* + +**first try dotted** + + +[2fab8](https://github.com/JSQLParser/JSqlParser/commit/2fab86081a56673) wumpz *2018-06-16 21:07:22* + +**fixes #620** + + +[645d0](https://github.com/JSQLParser/JSqlParser/commit/645d06e0a31206b) wumpz *2018-06-08 23:22:16* + +**fixes #612** + + +[36ee6](https://github.com/JSQLParser/JSqlParser/commit/36ee6c54c21965a) wumpz *2018-06-08 22:51:12* + +**fixes #612** + + +[60473](https://github.com/JSQLParser/JSqlParser/commit/60473edf4efbd85) wumpz *2018-06-08 22:50:02* + +**Update README.md** + + +[c5a0b](https://github.com/JSQLParser/JSqlParser/commit/c5a0b02b5f5c077) Tobias *2018-05-16 06:18:32* + +**Add javadoc badge** + + +[9c2c9](https://github.com/JSQLParser/JSqlParser/commit/9c2c96772ba9b5c) Jeremy Lin *2018-05-15 20:32:26* + +**add maven-central badge (#616)** + + +[4d67d](https://github.com/JSQLParser/JSqlParser/commit/4d67d10bbf9a033) Benedikt Waldvogel *2018-05-14 09:13:39* + +**fixes #614** + + +[32c4d](https://github.com/JSQLParser/JSqlParser/commit/32c4d8a04244fd5) wumpz *2018-05-12 22:51:33* + +**** + + +[094cc](https://github.com/JSQLParser/JSqlParser/commit/094cc8082e40442) wumpz *2018-05-02 21:16:26* + +**introduced junit annotations** + + +[d7c1e](https://github.com/JSQLParser/JSqlParser/commit/d7c1e438c8f0032) wumpz *2018-05-02 21:13:11* + +**fixes #611** + + +[35cf1](https://github.com/JSQLParser/JSqlParser/commit/35cf1d8b1b80d29) wumpz *2018-05-02 21:08:22* + +**fixes #610** + + +[5a60e](https://github.com/JSQLParser/JSqlParser/commit/5a60e1b57b7de4b) wumpz *2018-05-02 20:48:08* + +**fixes #610** + + +[c5c26](https://github.com/JSQLParser/JSqlParser/commit/c5c26ca4d18092b) wumpz *2018-05-02 20:45:56* + +**Update README.md** + + +[49b28](https://github.com/JSQLParser/JSqlParser/commit/49b2800bf7533e9) Tobias *2018-05-01 21:58:41* + +**Adding support for MySQL's SQL_NO_CACHE flag** + + +[403e7](https://github.com/JSQLParser/JSqlParser/commit/403e722e6ee12b4) Tomer S *2018-03-25 09:03:23* + + +## jsqlparser-1.2 (2018-05-01) + +### Other changes + +**fixes #605** + + +[6e309](https://github.com/JSQLParser/JSqlParser/commit/6e3099c50352966) wumpz *2018-04-22 21:49:56* + +**fixes #604** + + +[c8913](https://github.com/JSQLParser/JSqlParser/commit/c89139cfecb8e8d) wumpz *2018-04-20 22:38:48* + +**moved some jjt options from pom.xml to JSqlParserCC.jjt** + + +[e9a6c](https://github.com/JSQLParser/JSqlParser/commit/e9a6cd3b79ed501) wumpz *2018-04-19 13:29:22* + +**fixes #603** + + +[32930](https://github.com/JSQLParser/JSqlParser/commit/3293023e059de4d) wumpz *2018-04-19 08:35:31* + +**fixes #600** + + +[e80ea](https://github.com/JSQLParser/JSqlParser/commit/e80ea6803591783) wumpz *2018-04-13 07:55:00* + +**change standard to jdk 8 with java 1.7 file compliance** + + +[c28a5](https://github.com/JSQLParser/JSqlParser/commit/c28a549ef9895b4) wumpz *2018-04-13 07:46:19* + +**fixes #593** + + +[65276](https://github.com/JSQLParser/JSqlParser/commit/652766264a2bb61) wumpz *2018-04-08 22:37:28* + +**fixes #597** + + +[ac34e](https://github.com/JSQLParser/JSqlParser/commit/ac34efb0279a6af) wumpz *2018-04-08 21:17:12* + +**** + + +[4f63b](https://github.com/JSQLParser/JSqlParser/commit/4f63b1c085634f2) wumpz *2018-04-02 23:42:44* + +**fixes #592** + + +[1b5d2](https://github.com/JSQLParser/JSqlParser/commit/1b5d24dcf7d6fc8) wumpz *2018-04-02 22:37:47* + +**- allow parenthesis around from item** + +* - allow whitespace between bars from concat + +[2cea3](https://github.com/JSQLParser/JSqlParser/commit/2cea3ee94d83447) wumpz *2018-03-29 22:25:48* + +**- allow parenthesis around from item** + +* - allow whitespace between bars from concat + +[dabb0](https://github.com/JSQLParser/JSqlParser/commit/dabb03f0094e4c7) wumpz *2018-03-29 22:24:33* + +**** + + +[7d366](https://github.com/JSQLParser/JSqlParser/commit/7d36615ee5b5837) wumpz *2018-03-23 07:26:30* + +**fixes #588** + + +[a04cc](https://github.com/JSQLParser/JSqlParser/commit/a04ccb1c05204e5) wumpz *2018-03-17 00:40:36* + +**fixes #588** + + +[801cd](https://github.com/JSQLParser/JSqlParser/commit/801cd84c8dbb33f) wumpz *2018-03-17 00:40:06* + +**JSQLPARSER-584: adds support for MySQL (a,b,...)OP(c,d,...) expression (#585)** + +* JSQLPARSER-584: adds support for MySQL (a,b,...)OP(c,d,...) expression +* JSQLPARSER-584: adds some tests and rename MySQLValueListExpression to ValueListExpression + +[2c272](https://github.com/JSQLParser/JSqlParser/commit/2c272f440995b2c) Adrien Lesur *2018-03-05 23:08:55* + +**checked #266** + + +[72059](https://github.com/JSQLParser/JSqlParser/commit/7205906f58be21c) wumpz *2018-02-14 08:43:51* + +**fixes #583** + + +[76ed9](https://github.com/JSQLParser/JSqlParser/commit/76ed995ebef6bd1) wumpz *2018-02-14 08:37:38* + +**fixes #583** + + +[3768b](https://github.com/JSQLParser/JSqlParser/commit/3768b8d10789c70) wumpz *2018-02-14 08:36:26* + +**tested issue 582** + + +[84459](https://github.com/JSQLParser/JSqlParser/commit/84459536a13fa4b) wumpz *2018-02-09 07:18:06* + +**Create ISSUE_TEMPLATE.md** + + +[d5ec2](https://github.com/JSQLParser/JSqlParser/commit/d5ec2fe18e8f63b) Tobias *2018-02-08 07:12:19* + +**removed unneeded dependencies** + + +[445b1](https://github.com/JSQLParser/JSqlParser/commit/445b1a517e651de) wumpz *2018-02-07 10:46:12* + +**** + + +[feaea](https://github.com/JSQLParser/JSqlParser/commit/feaeaeb2c63b88c) wumpz *2018-02-02 12:46:17* + +**** + + +[18d01](https://github.com/JSQLParser/JSqlParser/commit/18d01811c592581) wumpz *2018-02-02 12:45:51* + +**Fix issue #563: subjoin allows only one inner join, this should be a … (#564)** + +* Fix issue #563: subjoin allows only one inner join, this should be a list +* Fix failing Oracle tests because of confusion between subjoin and subselect. + +[8456a](https://github.com/JSQLParser/JSqlParser/commit/8456acf7f228a46) Frits Jalvingh *2018-02-02 10:40:01* + +**fixes #320 (#576)** + +* fixes #320 + +[e6451](https://github.com/JSQLParser/JSqlParser/commit/e645193140f4271) Taner Mansur *2018-02-01 14:55:37* + +**** + + +[21e8b](https://github.com/JSQLParser/JSqlParser/commit/21e8bc4c549ea75) wumpz *2018-02-01 14:54:12* + +**fixes #566,#438,#267** + + +[bf951](https://github.com/JSQLParser/JSqlParser/commit/bf9515418475372) wumpz *2018-01-30 14:10:17* + +**fixes #566,#438,#267** + + +[ccbe9](https://github.com/JSQLParser/JSqlParser/commit/ccbe9ad0be27d78) wumpz *2018-01-30 14:09:12* + +**tests #572** + + +[5d609](https://github.com/JSQLParser/JSqlParser/commit/5d609ef208c6803) wumpz *2018-01-29 15:43:04* + +**corrected generics type** + + +[ed1a2](https://github.com/JSQLParser/JSqlParser/commit/ed1a297094cd85c) wumpz *2018-01-22 07:34:55* + +**fixes #567** + + +[0d4ae](https://github.com/JSQLParser/JSqlParser/commit/0d4aed3aadce638) wumpz *2018-01-12 07:36:54* + +**removed "removed" project bewa** + + +[dec98](https://github.com/JSQLParser/JSqlParser/commit/dec98caa839b0d6) wumpz *2018-01-08 07:44:24* + +**fixes #338** + + +[0e571](https://github.com/JSQLParser/JSqlParser/commit/0e571d14aed151c) wumpz *2018-01-05 23:29:00* + +**fixes #545** + + +[ab7e2](https://github.com/JSQLParser/JSqlParser/commit/ab7e29bba316f0d) wumpz *2018-01-05 23:16:29* + +**fixes #462** + + +[83844](https://github.com/JSQLParser/JSqlParser/commit/838449cb5163f19) wumpz *2017-12-28 00:50:29* + +**fixes #462** + + +[bc005](https://github.com/JSQLParser/JSqlParser/commit/bc005f89fd7d091) wumpz *2017-12-28 00:47:37* + +**Update README.md** + + +[5871c](https://github.com/JSQLParser/JSqlParser/commit/5871c573f69696d) Tobias *2017-12-27 20:04:29* + +**Update README.md** + + +[dd6bb](https://github.com/JSQLParser/JSqlParser/commit/dd6bbef26420dd0) Tobias *2017-12-07 10:25:11* + +**fixes #554** + + +[4ce98](https://github.com/JSQLParser/JSqlParser/commit/4ce98e492ce9d17) wumpz *2017-12-07 08:55:52* + +**** + + +[ee723](https://github.com/JSQLParser/JSqlParser/commit/ee723d50b08a54d) wumpz *2017-12-04 08:36:46* + +**fixes #543** + + +[bdc20](https://github.com/JSQLParser/JSqlParser/commit/bdc20ea7688c8c4) wumpz *2017-12-04 08:35:07* + +**fixes #551** + + +[a25fb](https://github.com/JSQLParser/JSqlParser/commit/a25fb7cb3ba02c1) wumpz *2017-12-04 08:14:06* + +**made some modifications to rlike fix** + + +[f0ffe](https://github.com/JSQLParser/JSqlParser/commit/f0ffe4c53edbcaa) wumpz *2017-11-16 22:29:53* + +**Added support for RLIKE expressions (#544)** + +* RLIKE is a synonym of REGEXP, therefore should be treated the same. + +[8a950](https://github.com/JSQLParser/JSqlParser/commit/8a950b3e09dce06) sh-tomer *2017-11-16 22:10:51* + +**jdk 1.7** + + +[8d4f2](https://github.com/JSQLParser/JSqlParser/commit/8d4f25c49c3975d) wumpz *2017-11-07 09:43:35* + +**modern template included** + + +[9ea8e](https://github.com/JSQLParser/JSqlParser/commit/9ea8e4c3f4e3ab7) wumpz *2017-11-07 07:31:58* + +**fixes #540,#526** + + +[8bc23](https://github.com/JSQLParser/JSqlParser/commit/8bc236e25ddbe8d) wumpz *2017-11-03 07:21:40* + +**fixes #540,#526** + + +[ab868](https://github.com/JSQLParser/JSqlParser/commit/ab868a627a6b72f) wumpz *2017-11-03 07:18:39* + +**corrected a lookahead issue** + + +[a2f81](https://github.com/JSQLParser/JSqlParser/commit/a2f81f3a299145a) wumpz *2017-10-31 22:37:41* + +**Add ability to support "NOT LIKE ..." expressions (#539)** + +* The parser is able to parse expressions such as "a NOT LIKE '%pattern%'", but is not able to parse expressions where the not is before the entire expression. For example: "NOT a LIKE '%pattern%'. +* When parsing the latter, the error is: +* Caused by: net.sf.jsqlparser.parser.ParseException: Encountered " "LIKE" "LIKE "" at line 1, column 32. +* Was expecting one of: ... +* The reason this is important is both because these syntaxes are both valid, and also because the deparser uses the second method. +* Therefore, if you parse a query with the first type of expression, then deparse it and parse again, you'll get the same error. + +[daea3](https://github.com/JSQLParser/JSqlParser/commit/daea33e73aa05c6) sh-tomer *2017-10-31 20:27:50* + +**** + + +[452ba](https://github.com/JSQLParser/JSqlParser/commit/452baffb2af8c21) wumpz *2017-10-29 23:20:57* + +**** + + +[14523](https://github.com/JSQLParser/JSqlParser/commit/1452360f9cca7aa) wumpz *2017-10-29 23:08:39* + +**** + + +[7c90a](https://github.com/JSQLParser/JSqlParser/commit/7c90a24bdf72994) wumpz *2017-10-29 22:59:21* + +**Linking structures to their AST nodes to have access to their positions (#534)** + +* Linking several structures to their AST nodes to have access to their positions +* This far there were only 3 types of structures linked to their AST nodes. Now adding some more expressions and literals to their AST node to have access to their token's position in the query. +* Added missing parts in JSQqlParserCC.jjt for AST linking to work +* Added missing parts in JSQqlParserCC.jjt to make sure all relevant code is created to generate and link AST nodes to the relevant structures. + +[514f2](https://github.com/JSQLParser/JSqlParser/commit/514f2588af97345) sh-tomer *2017-10-29 12:39:56* + +**add debug note (#531)** + +* added a link to the visualize parsing section to have a visible debug mode (so users that create an issue can try to get us better output) + +[b1abc](https://github.com/JSQLParser/JSqlParser/commit/b1abc6ff39e9c2a) Jan Monterrubio *2017-10-25 06:21:26* + +**fixes #525 (#530)** + +* fixes #525 +* Simply unit test. + +[1a1a1](https://github.com/JSQLParser/JSqlParser/commit/1a1a1aa53866787) Linyu Chen *2017-10-24 05:30:39* + +**simplified tests for SQL_CALC_FOUND_ROWS** + + +[e23d4](https://github.com/JSQLParser/JSqlParser/commit/e23d4bc09e5f6e4) wumpz *2017-10-20 07:32:58* + +**Implements #509 (#504)** + +* Supporting MySql hit SQL_CALC_FOUND_ROWS for selecting row count. +* Supporting MySql hit SQL_CALC_FOUND_ROWS for selecting row count. - refactoring +* Supporting MySql hit SQL_CALC_FOUND_ROWS for selecting row count. - missing copyright.ˆ +* Supporting MySql hit SQL_CALC_FOUND_ROWS for selecting row count. - Modify field type to boolean for prevent memory consumption by creating object and try assertSqlCanBeParsedAndDeparsed on unit test. + +[3e163](https://github.com/JSQLParser/JSqlParser/commit/3e16345815e45b5) Yoon Kyong Sik *2017-10-20 07:27:48* + +**fixes #522** + + +[45ac8](https://github.com/JSQLParser/JSqlParser/commit/45ac8c8a2bcff54) wumpz *2017-10-12 21:27:57* + +**fixes #522** + + +[2c69c](https://github.com/JSQLParser/JSqlParser/commit/2c69cc65f8bfd32) wumpz *2017-10-12 21:22:26* + +**fixes #510** + + +[f64ad](https://github.com/JSQLParser/JSqlParser/commit/f64ad89eec4ea53) wumpz *2017-10-09 23:51:46* + +**** + + +[1a771](https://github.com/JSQLParser/JSqlParser/commit/1a77106df128893) wumpz *2017-10-06 08:58:01* + +**fixes #508 including precedence** + + +[8037a](https://github.com/JSQLParser/JSqlParser/commit/8037af621f32f0a) wumpz *2017-10-06 08:36:57* + +**fixes #519** + +* fixes #520 + +[27217](https://github.com/JSQLParser/JSqlParser/commit/272177a37b9ee81) wumpz *2017-10-06 08:24:04* + +**transformed primary expression and sign parsing** + + +[51fcd](https://github.com/JSQLParser/JSqlParser/commit/51fcdea9f92c1ce) wumpz *2017-10-06 07:11:58* + +**corrected token definition order** + + +[64ce9](https://github.com/JSQLParser/JSqlParser/commit/64ce9ff2986d492) wumpz *2017-10-06 07:01:35* + +**waiting for https://github.com/javacc/javacc/issues/28** + + +[704e6](https://github.com/JSQLParser/JSqlParser/commit/704e6c84fb66150) wumpz *2017-10-02 09:14:01* + +**Fix test case** + + +[b2bb2](https://github.com/JSQLParser/JSqlParser/commit/b2bb2431c4dfae0) Nathaniel Camomot *2017-09-27 08:10:08* + +**Fix for some cases where TablNamesFinder can't find tables** + + +[395c3](https://github.com/JSQLParser/JSqlParser/commit/395c3b0049cd09f) Nathaniel Camomot *2017-09-27 06:21:21* + +**removed oraclejdk7 travis build due to https://github.com/travis-ci/travis-ci/issues/7964** + + +[812f9](https://github.com/JSQLParser/JSqlParser/commit/812f98fff951c4e) wumpz *2017-09-24 09:55:31* + +**** + + +[96b5d](https://github.com/JSQLParser/JSqlParser/commit/96b5d9f26ec7310) wumpz *2017-09-24 09:48:35* + +**** + + +[b847e](https://github.com/JSQLParser/JSqlParser/commit/b847e85c0dba19f) wumpz *2017-09-23 22:40:30* + +**Create LICENSE_LGPLV21** + + +[d2c87](https://github.com/JSQLParser/JSqlParser/commit/d2c87dac67436af) Tobias *2017-09-23 22:29:45* + +**Create LICENSE_APACHEV2** + + +[f9c1a](https://github.com/JSQLParser/JSqlParser/commit/f9c1a9f7fb91703) Tobias *2017-09-23 22:29:09* + +**fixes #515** + + +[c4b36](https://github.com/JSQLParser/JSqlParser/commit/c4b360e14a06201) wumpz *2017-09-23 22:20:51* + +**fixes #515** + + +[1afe7](https://github.com/JSQLParser/JSqlParser/commit/1afe7e6a9931f7e) wumpz *2017-09-23 22:18:35* + +**fixes #515** + + +[8388f](https://github.com/JSQLParser/JSqlParser/commit/8388f1e48355b4f) wumpz *2017-09-23 22:17:04* + +**Update README.md** + + +[3f734](https://github.com/JSQLParser/JSqlParser/commit/3f734f130da0a66) Tobias *2017-09-23 21:38:51* + +**fixes #514** + + +[8a459](https://github.com/JSQLParser/JSqlParser/commit/8a459ce9894ec36) wumpz *2017-09-23 21:32:10* + +**fixes #514** + + +[3e846](https://github.com/JSQLParser/JSqlParser/commit/3e84605a7a87948) wumpz *2017-09-23 21:29:52* + +**merge of within_group and analytic** + + +[26fab](https://github.com/JSQLParser/JSqlParser/commit/26faba8040636e8) wumpz *2017-09-23 21:24:18* + +**** + + +[c5a47](https://github.com/JSQLParser/JSqlParser/commit/c5a471f926c1d85) wumpz *2017-09-22 12:29:44* + +**#fixes 480** + + +[10352](https://github.com/JSQLParser/JSqlParser/commit/10352328d3d52f3) wumpz *2017-09-12 21:59:08* + +**#fixes 480** + + +[e60fa](https://github.com/JSQLParser/JSqlParser/commit/e60fa8cd305d154) wumpz *2017-09-12 21:58:39* + +**fixes #512** + + +[07a14](https://github.com/JSQLParser/JSqlParser/commit/07a14dc892d6003) wumpz *2017-09-07 22:20:01* + +**fixes #505** + + +[ef55f](https://github.com/JSQLParser/JSqlParser/commit/ef55ffba8b596aa) wumpz *2017-08-28 08:13:14* + +**fixes #502** + + +[6a440](https://github.com/JSQLParser/JSqlParser/commit/6a440ba583955b1) wumpz *2017-08-26 14:18:07* + +**fixes #502** + + +[41ea8](https://github.com/JSQLParser/JSqlParser/commit/41ea83d2757adee) wumpz *2017-08-26 14:14:13* + +**fixes #484** + + +[1a6f9](https://github.com/JSQLParser/JSqlParser/commit/1a6f9143ef491dd) wumpz *2017-08-23 20:41:06* + +**fixes #484** + + +[8f9b6](https://github.com/JSQLParser/JSqlParser/commit/8f9b62705ae094e) wumpz *2017-08-23 20:40:26* + +**replace support multiple values** + + +[93598](https://github.com/JSQLParser/JSqlParser/commit/93598bbe86aaa92) wanghai *2017-08-21 09:15:27* + +**fixed #491** + + +[147ec](https://github.com/JSQLParser/JSqlParser/commit/147ec4887639700) wumpz *2017-08-16 15:47:01* + +**fixed #491** + + +[24f23](https://github.com/JSQLParser/JSqlParser/commit/24f232c08edb86c) wumpz *2017-08-16 15:45:55* + +**checked issue #482** + + +[71692](https://github.com/JSQLParser/JSqlParser/commit/71692c5c6f85f0f) wumpz *2017-08-07 13:33:12* + +**fixes #485** + + +[64bc5](https://github.com/JSQLParser/JSqlParser/commit/64bc5e05d8086b4) wumpz *2017-08-03 05:57:10* + +**fix issue #424 (INSERT with SET) (#481)** + +* update insert with set language +* update insert with set +* update insert with set +* update insert test +* add removed lines + +[ca653](https://github.com/JSQLParser/JSqlParser/commit/ca6538a04dd7969) messfish *2017-07-28 06:23:33* + +**fixes #456** + + +[9c2cc](https://github.com/JSQLParser/JSqlParser/commit/9c2cc2c823b3d1e) wumpz *2017-07-27 11:14:26* + +**introduced partial / nonpartial parse for CCJSqlParserUtil methods** + + +[6b452](https://github.com/JSQLParser/JSqlParser/commit/6b452183f084652) wumpz *2017-07-27 05:47:13* + +**fixes #473** + + +[0aa22](https://github.com/JSQLParser/JSqlParser/commit/0aa229d3df996f6) wumpz *2017-07-18 06:24:20* + +**Update README.md** + + +[58c42](https://github.com/JSQLParser/JSqlParser/commit/58c42bcfbf717ee) Tobias *2017-06-29 21:37:30* + +**Update README.md** + + +[d235c](https://github.com/JSQLParser/JSqlParser/commit/d235ca3971a9a6e) Tobias *2017-06-29 21:34:47* + + +## jsqlparser-1.1 (2017-06-29) + +### Other changes + +**fixes #468** + + +[6cb45](https://github.com/JSQLParser/JSqlParser/commit/6cb459d747901ea) wumpz *2017-06-28 08:50:50* + +**** + + +[fb64e](https://github.com/JSQLParser/JSqlParser/commit/fb64e3295e91bca) wumpz *2017-06-11 21:50:53* + +**Add Upsert Grammer (#460)** + +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add test for de parser +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload +* Add files via upload + +[aaeb8](https://github.com/JSQLParser/JSqlParser/commit/aaeb8dfeb0c2a4e) messfish *2017-06-11 18:48:53* + +**introduced linking between Function and ASTNode** + + +[3e75c](https://github.com/JSQLParser/JSqlParser/commit/3e75c68c4bf769e) wumpz *2017-06-09 22:34:23* + +**introduced linking between Function and ASTNode** + + +[e96f4](https://github.com/JSQLParser/JSqlParser/commit/e96f48534ca3103) wumpz *2017-06-09 22:32:16* + +**fixes #457** + + +[2ae5e](https://github.com/JSQLParser/JSqlParser/commit/2ae5e76d69b1cbf) wumpz *2017-05-26 21:34:35* + +**** + + +[e4ef6](https://github.com/JSQLParser/JSqlParser/commit/e4ef6e231282b62) wumpz *2017-05-23 07:32:52* + +**Fix issue #442 (#451)** + +* Fix issue #442 for delete statements +* Fix issue #442 for insert statements +* Mock only when necessary +* E.g., interfaces, behavior needs to be verified, etc. +* Prefer the first style of testing +* As discussed in issue #442 +* Fix issue #442 for replace statements +* Improve readability of issue #442 tests +* Inject SelectDeParser as well +* As discussed in issue #442. +* Fix issue #442 for select statements +* Fix issue #442 for update statements +* Fix issue #442 for execute statements +* Fix issue #442 for set statements +* Fix PR code review issue +* https://www.codacy.com/app/wumpz/JSqlParser/file/6682733346/issues/source?bid=4162857&fileBranchId=4580866#l48 +* Skip PMD check for asserts in tests using Mockito +* As agreed upon in the discussion in PR #451. +* Use correct PMD check name + +[9d680](https://github.com/JSQLParser/JSqlParser/commit/9d680a6ec4b9f07) chrycheng *2017-05-22 07:13:41* + +**fixes #430** + + +[585cb](https://github.com/JSQLParser/JSqlParser/commit/585cbbd1377632b) wumpz *2017-05-16 22:04:19* + +**Fix issue #446 (#447)** + +* Test current behavior of ExecuteDeParser +* Fix issue #446 + +[275fb](https://github.com/JSQLParser/JSqlParser/commit/275fbbe87fa0ada) chrycheng *2017-05-16 20:46:29* + +**fixes #449** + + +[fe6da](https://github.com/JSQLParser/JSqlParser/commit/fe6dafea19fa236) wumpz *2017-05-16 14:12:50* + +**introduced test for 437** + + +[3e740](https://github.com/JSQLParser/JSqlParser/commit/3e740100498aa22) wumpz *2017-05-12 19:43:14* + +**test issue 445** + + +[fce59](https://github.com/JSQLParser/JSqlParser/commit/fce593dcf85c43e) wumpz *2017-05-11 08:37:49* + +**** + + +[1fbf6](https://github.com/JSQLParser/JSqlParser/commit/1fbf6c5bde81b41) wumpz *2017-05-08 12:32:25* + +**updated readme** + + +[1dabc](https://github.com/JSQLParser/JSqlParser/commit/1dabcbc56f9b158) wumpz *2017-05-07 20:37:31* + +**some minor changes** + + +[050b8](https://github.com/JSQLParser/JSqlParser/commit/050b8ba6434630d) wumpz *2017-05-07 20:35:15* + +**conversion to CNF (#434)** + +* Add files via upload +* Create foo +* All the files needed for the CNF conversion +* Delete foo +* Create foo +* Test cases for the CNF conversion +* Delete foo +* Add files via upload +* Add files via upload +* change some public methods to private +* Delete CNFConverter.java +* Delete CloneHelper.java +* Delete MultiAndExpression.java +* Delete MultiOrExpression.java +* Delete MultipleExpression.java +* Create foo +* Add files via upload +* Delete CNFTest.java +* Delete StepLastHelper.java +* Create foo +* Add files via upload +* Delete foo +* Delete foo +* Add files via upload +* Add files via upload +* Delete CNFConverter.java +* Delete CloneHelper.java +* Delete MultiAndExpression.java +* Delete MultiOrExpression.java +* Delete MultipleExpression.java +* Create foo +* Add files via upload +* Delete foo +* Delete CNFTest.java +* Create foo +* Add files via upload +* Delete foo +* Add files via upload +* Add files via upload + +[afe10](https://github.com/JSQLParser/JSqlParser/commit/afe1011bdd64696) messfish *2017-05-07 20:21:00* + +**** + + +[56497](https://github.com/JSQLParser/JSqlParser/commit/56497af552c53a4) wumpz *2017-05-02 06:06:33* + +**corrected bug within RelObjectNameExt processing** + + +[7b2b0](https://github.com/JSQLParser/JSqlParser/commit/7b2b0f649b1702a) wumpz *2017-05-02 06:00:44* + +**Update README.md** + + +[2c0f2](https://github.com/JSQLParser/JSqlParser/commit/2c0f2ff0f6c7814) Tobias *2017-04-28 07:37:09* + +**Update README.md** + + +[80c98](https://github.com/JSQLParser/JSqlParser/commit/80c98055bc969a0) Tobias *2017-04-28 07:35:42* + +**** + + +[59310](https://github.com/JSQLParser/JSqlParser/commit/5931045d807559e) wumpz *2017-04-24 13:25:21* + +**Introduce support for mysql index hints (fixing issue #374) (#429)** + +* Introduce support for mysql index hints (fixing issue #374) +* Fix checkstyle errors +* -Converted indent tabs to spaces +* -Added missing {} on single-line if statement + +[6db15](https://github.com/JSQLParser/JSqlParser/commit/6db15d2c6218d06) Joey Mart *2017-04-18 06:22:25* + +**#425 ADD CONSTRAINT also support state such as DEFERRABLE, VALIDATE... (#426)** + + +[f1113](https://github.com/JSQLParser/JSqlParser/commit/f11133c0bdd7a6b) Christophe Moine *2017-04-17 23:40:45* + +**Addressing #427 (#428)** + +* updating readme with Maven requirements +* removing ticks + +[0fddc](https://github.com/JSQLParser/JSqlParser/commit/0fddc73e2eee1b2) AnEmortalKid *2017-04-17 23:39:05* + +**going back to checkstyle 6.x due to java7 incompatibilities** + + +[564ac](https://github.com/JSQLParser/JSqlParser/commit/564acc288fa0294) wumpz *2017-04-17 23:27:10* + +**Update README.md** + + +[30b09](https://github.com/JSQLParser/JSqlParser/commit/30b0924742068f0) Tobias *2017-04-17 23:09:06* + +**Update README.md** + + +[2b5c8](https://github.com/JSQLParser/JSqlParser/commit/2b5c84552963ec3) Tobias *2017-04-17 23:05:07* + +**checkstyle source check included. configuration done** + + +[12377](https://github.com/JSQLParser/JSqlParser/commit/12377c784a3fa53) wumpz *2017-04-17 23:01:42* + +**checkstyle source check included. configuration done** + + +[1bdf5](https://github.com/JSQLParser/JSqlParser/commit/1bdf5b9515b5af3) wumpz *2017-04-17 22:57:12* + +**improved StatementVistorAdaptor to process all statements.** + + +[27119](https://github.com/JSQLParser/JSqlParser/commit/2711900eb3ebf83) wumpz *2017-04-11 07:47:22* + +**removed linefeed check, due to multiple git checkout configurations regarding linefeeds** + + +[aab56](https://github.com/JSQLParser/JSqlParser/commit/aab569bf4c6376f) wumpz *2017-03-31 08:04:24* + +**** + + +[2f5a1](https://github.com/JSQLParser/JSqlParser/commit/2f5a1eacf3e9f5a) wumpz *2017-03-29 06:07:20* + +**corrected source files regarding checkstyle errors** + + +[0d6fa](https://github.com/JSQLParser/JSqlParser/commit/0d6faeb8b411e53) wumpz *2017-03-28 09:46:55* + +**introduced some more checkstyle rules** + + +[c7a86](https://github.com/JSQLParser/JSqlParser/commit/c7a8601b84695e4) wumpz *2017-03-28 09:30:00* + +**removed problematic profile "check.sources" activation, excluded generated-sources, included test-sources** + + +[e2cc2](https://github.com/JSQLParser/JSqlParser/commit/e2cc2210c364f6c) wumpz *2017-03-27 11:48:50* + +**removed problematic profile "check.sources" activation, excluded generated-sources, included test-sources** + + +[e941f](https://github.com/JSQLParser/JSqlParser/commit/e941fd96a2caade) wumpz *2017-03-27 11:45:39* + +**removed problematic profile "check.sources" activation, excluded generated-sources, included test-sources** + + +[dd23f](https://github.com/JSQLParser/JSqlParser/commit/dd23f27516db63b) wumpz *2017-03-27 11:14:44* + +**removed auto activation due to travis problems, included test sources** + + +[759e7](https://github.com/JSQLParser/JSqlParser/commit/759e751b85c5a16) wumpz *2017-03-27 10:53:46* + +**checkstyle** + + +[62505](https://github.com/JSQLParser/JSqlParser/commit/625054295a7700b) wumpz *2017-03-27 09:16:11* + +**Update README.md** + + +[da9ac](https://github.com/JSQLParser/JSqlParser/commit/da9acf59e308d2b) Tobias *2017-03-25 22:21:59* + + +## jsqlparser-1.0 (2017-03-25) + +### Other changes + +**** + + +[32e8f](https://github.com/JSQLParser/JSqlParser/commit/32e8fa02ecfadc4) wumpz *2017-03-25 22:00:13* + +**** + + +[a31b2](https://github.com/JSQLParser/JSqlParser/commit/a31b219baadb001) wumpz *2017-03-25 21:52:19* + +**** + + +[f731f](https://github.com/JSQLParser/JSqlParser/commit/f731fa4cf726036) wumpz *2017-03-25 21:47:42* + +**reformating hole sourcecode** + + +[4146f](https://github.com/JSQLParser/JSqlParser/commit/4146f869cb01151) wumpz *2017-03-22 07:36:17* + +**Fix #407 by enhancing grammar (#410)** + +* Fix #407 by enhancing grammar +* Change LF and tabs + +[5d901](https://github.com/JSQLParser/JSqlParser/commit/5d9018657df6b22) Christophe Moine *2017-03-22 07:36:14* + +**removed dependencies** + + +[dd1b3](https://github.com/JSQLParser/JSqlParser/commit/dd1b334e3bc4675) wumpz *2017-03-20 10:22:55* + +**fixes #406** + + +[06619](https://github.com/JSQLParser/JSqlParser/commit/066199cfeb97ea4) wumpz *2017-03-17 11:55:11* + +**update to JavaCC 7.0.2** + + +[c12f7](https://github.com/JSQLParser/JSqlParser/commit/c12f7ac457d92c3) wumpz *2017-03-15 10:28:17* + +**Update README.md** + + +[6312f](https://github.com/JSQLParser/JSqlParser/commit/6312f3aaf9aa46e) Tobias *2017-03-15 08:55:03* + +**update readme** + + +[03746](https://github.com/JSQLParser/JSqlParser/commit/03746a8ddf0c14e) wumpz *2017-03-15 08:45:24* + +**update readme** + + +[5bbfe](https://github.com/JSQLParser/JSqlParser/commit/5bbfeb76bf7deab) wumpz *2017-03-15 08:44:22* + +**** + + +[6e72b](https://github.com/JSQLParser/JSqlParser/commit/6e72b99ee4b0ba0) wumpz *2017-03-14 11:41:26* + +**corrected merge conflict** + + +[1211d](https://github.com/JSQLParser/JSqlParser/commit/1211dcf1209f3a4) wumpz *2017-03-14 11:39:30* + +**corrected case when expressions** + + +[12cc4](https://github.com/JSQLParser/JSqlParser/commit/12cc4059ddef291) wumpz *2017-03-14 11:12:53* + +**rewrote some lookaheads** + + +[2a440](https://github.com/JSQLParser/JSqlParser/commit/2a4405a6a0821cc) wumpz *2017-03-14 10:33:21* + +**replace some junit pre 4.x artifacts** + + +[7dd85](https://github.com/JSQLParser/JSqlParser/commit/7dd857e5000f09a) wumpz *2017-03-14 09:55:42* + +**first rewrite of SelectBody** + + +[49127](https://github.com/JSQLParser/JSqlParser/commit/49127be715d029a) wumpz *2017-03-14 09:43:25* + +**** + + +[5dcef](https://github.com/JSQLParser/JSqlParser/commit/5dcefcefd07755a) wumpz *2017-03-10 22:13:02* + +**Support FOR UPDATE WAIT (#405)** + +* Adding FOR UPDATE WAIT support +* removing final peppered everywhere +* updating formatting, fixing codacy test names +* updating asserts to use static import +* reverting changes +* reverting line feeds +* adding tests and deparser code back without formatting + +[45b39](https://github.com/JSQLParser/JSqlParser/commit/45b392f4b93714c) AnEmortalKid *2017-03-10 22:06:53* + +**add support for LIMIT with only one row count JDBC parameter (#404)** + +* small but powerfull change 👍 + +[42318](https://github.com/JSQLParser/JSqlParser/commit/42318531bb72279) zhushaoping *2017-03-03 07:06:08* + +**merged** + + +[c3eed](https://github.com/JSQLParser/JSqlParser/commit/c3eed13096c0019) wumpz *2017-03-03 07:03:08* + +**fixes #401** + + +[1315d](https://github.com/JSQLParser/JSqlParser/commit/1315d035dbc5008) wumpz *2017-03-01 08:20:55* + +**fixes #402** + + +[6fb15](https://github.com/JSQLParser/JSqlParser/commit/6fb15a104debe95) wumpz *2017-03-01 07:55:25* + +**release 0.9.7** + + +[46720](https://github.com/JSQLParser/JSqlParser/commit/46720ef029cf8aa) wumpz *2017-02-26 23:13:50* + + +## jsqlparser-0.9.7 (2017-02-26) + +### Other changes + +**updated readme** + + +[e2dc3](https://github.com/JSQLParser/JSqlParser/commit/e2dc36897178155) wumpz *2017-02-21 08:49:56* + +**commented an issue test** + + +[4fe4c](https://github.com/JSQLParser/JSqlParser/commit/4fe4ce206296ea1) wumpz *2017-02-21 08:46:38* + +**set statemet with optional equals** + + +[ec6ce](https://github.com/JSQLParser/JSqlParser/commit/ec6cef2e803d87a) wumpz *2017-02-11 23:57:32* + +**fixes #393** + + +[320f6](https://github.com/JSQLParser/JSqlParser/commit/320f64a9a4aa687) wumpz *2017-02-10 09:34:47* + +**** + + +[42f32](https://github.com/JSQLParser/JSqlParser/commit/42f3242cc13fac6) wumpz *2017-02-08 08:17:40* + +**removed unused imports** + + +[c66cc](https://github.com/JSQLParser/JSqlParser/commit/c66cc6973753c3a) wumpz *2017-02-08 08:15:51* + +**minor code improvements** + + +[e3fd2](https://github.com/JSQLParser/JSqlParser/commit/e3fd2c6df3444ae) wumpz *2017-02-08 08:13:58* + +**Update README.md** + + +[3d05e](https://github.com/JSQLParser/JSqlParser/commit/3d05e16c6c09a05) Tobias *2017-02-07 18:09:26* + +**fixes #390** + + +[546b7](https://github.com/JSQLParser/JSqlParser/commit/546b71d84eb8b45) wumpz *2017-02-01 15:27:48* + +**** + + +[d4396](https://github.com/JSQLParser/JSqlParser/commit/d439643bbf1cd02) wumpz *2017-01-27 20:53:20* + +**fixes #389** + + +[71c32](https://github.com/JSQLParser/JSqlParser/commit/71c32d905fbd4cb) wumpz *2017-01-27 20:39:25* + +**included LOOKAHEAD** + + +[6776e](https://github.com/JSQLParser/JSqlParser/commit/6776eb5fd0224e4) wumpz *2017-01-20 23:12:17* + +**updated readme** + + +[b5f6e](https://github.com/JSQLParser/JSqlParser/commit/b5f6e9efac23dca) wumpz *2017-01-20 22:10:59* + +**updated readme** + + +[1abd2](https://github.com/JSQLParser/JSqlParser/commit/1abd224a3e2ff0f) wumpz *2017-01-20 22:00:07* + +**Increase test coverage on AlterExpression.java** + +* getOperation +* getFkColumns +* getFkSourceTable +* getFkSourceColumns +* getConstraintName +* tried getPkColumns but it does not behave as I expected. +* placed TODO in AlterTest.testAlterTablePK for this +* getIndex().getColumnNames + +[5a799](https://github.com/JSQLParser/JSqlParser/commit/5a79964714b13f7) jthomas *2017-01-19 19:43:24* + +**Enhance AlterExpression grammar:** + +* 1. optional "COLUMN" keyword in ADD alter operation +* 2. new alter operation: MODIFY +* 3. add column specs to alter table column definitions + +[24177](https://github.com/JSQLParser/JSqlParser/commit/241779b26973b47) jthomas *2017-01-19 17:32:21* + +**support to add jdbc name parameter after LIMIT and TOP keywords** + + +[e25e2](https://github.com/JSQLParser/JSqlParser/commit/e25e247dd5e9131) zhushaoping *2017-01-13 02:55:52* + +**fixes #288** + + +[091c5](https://github.com/JSQLParser/JSqlParser/commit/091c5dd5ab5ce93) zhushaoping *2017-01-12 07:09:57* + +**tests for issue 379 included** + + +[f7c27](https://github.com/JSQLParser/JSqlParser/commit/f7c27ad6492a636) wumpz *2017-01-04 07:22:19* + +**tests for issue 379 included** + + +[14a9b](https://github.com/JSQLParser/JSqlParser/commit/14a9b3e372b664a) wumpz *2017-01-04 06:49:43* + +**updated readme** + + +[1899c](https://github.com/JSQLParser/JSqlParser/commit/1899cbffb915992) wumpz *2017-01-02 13:32:56* + +**fixes #375** + +* fixes #371 + +[957f3](https://github.com/JSQLParser/JSqlParser/commit/957f39c496a7fac) wumpz *2017-01-02 13:30:09* + +**fixed NPE in ExpressionVisitorAdapter when SubSelect doesn't has withItemsList** + + +[28979](https://github.com/JSQLParser/JSqlParser/commit/2897935037560db) Donghang Lin *2016-12-21 07:14:48* + +**** + + +[5bc1f](https://github.com/JSQLParser/JSqlParser/commit/5bc1fc3669d52f0) wumpz *2016-12-06 22:08:00* + +**fixed #363** + + +[66e44](https://github.com/JSQLParser/JSqlParser/commit/66e44c956be7481) wumpz *2016-12-01 06:52:45* + +**integrated some tests** + + +[5937b](https://github.com/JSQLParser/JSqlParser/commit/5937bace81bd20c) wumpz *2016-11-14 11:47:43* + +**corrected fix #311 and fix #332, introduced unaliased fqn of column** + + +[88804](https://github.com/JSQLParser/JSqlParser/commit/888041d1971257e) wumpz *2016-09-26 12:33:24* + +**fixes #341** + + +[b3faf](https://github.com/JSQLParser/JSqlParser/commit/b3faf8eb8680484) wumpz *2016-09-20 21:53:32* + +**Update README.md** + + +[98ded](https://github.com/JSQLParser/JSqlParser/commit/98ded4dfd487b7e) Tobias *2016-09-17 14:34:21* + +**corrected some lookaheads** + + +[7c157](https://github.com/JSQLParser/JSqlParser/commit/7c1572febc89ae1) wumpz *2016-09-16 11:52:08* + +**Updated header and removed unused methods.** + + +[2bfc9](https://github.com/JSQLParser/JSqlParser/commit/2bfc9ab124086b9) Peter Borissow *2016-09-15 15:28:59* + +**Added json parsing tests.** + + +[7c740](https://github.com/JSQLParser/JSqlParser/commit/7c740854852d725) Peter Borissow *2016-09-15 14:59:01* + +**Added support for PostgreSQL JSON Functions and Operators.** + + +[a5504](https://github.com/JSQLParser/JSqlParser/commit/a5504819c1d93f0) Peter Borissow *2016-09-14 02:28:01* + +**Add support for more Postgres Create Table options** + + +[04c56](https://github.com/JSQLParser/JSqlParser/commit/04c56f283d24b44) Rob Story *2016-09-09 21:02:57* + +**fixes #334** + + +[21a0d](https://github.com/JSQLParser/JSqlParser/commit/21a0df961b4dc70) wumpz *2016-09-01 07:45:04* + +**** + + +[8e229](https://github.com/JSQLParser/JSqlParser/commit/8e22953b3bdcf85) wumpz *2016-09-01 06:50:59* + +**** + + +[e6e7e](https://github.com/JSQLParser/JSqlParser/commit/e6e7ea7bd407e30) wumpz *2016-09-01 06:46:49* + +**Support additional Postgres column types for alter table statements** + + +[42181](https://github.com/JSQLParser/JSqlParser/commit/42181b00cace324) Rob Story *2016-08-30 14:22:55* + +**fixes #330** + + +[03a34](https://github.com/JSQLParser/JSqlParser/commit/03a344d221abc9b) wumpz *2016-08-29 07:13:00* + +**fixes #329** + + +[3df49](https://github.com/JSQLParser/JSqlParser/commit/3df492bb5cadaee) wumpz *2016-08-28 21:06:08* + +**updated readme** + + +[2acae](https://github.com/JSQLParser/JSqlParser/commit/2acaee03959f798) wumpz *2016-08-23 20:02:35* + + +## jsqlparser-0.9.6 (2016-08-23) + +### Other changes + +**#modify net.sf.jsqlparser.statement.insert.Insert Method:toString() if itemsList and useSelectBrackets together not null will error** + +* #modify PlainSelect.getStringList change sql append to StringBuilder + +[471b9](https://github.com/JSQLParser/JSqlParser/commit/471b94495623ee2) zheng.liu@baifendian.com *2016-08-15 06:22:23* + +**corrected some lookaheads parsing delete statements** + + +[57890](https://github.com/JSQLParser/JSqlParser/commit/578909f24136b04) wumpz *2016-08-14 12:59:27* + +**some cleanup** + + +[d34eb](https://github.com/JSQLParser/JSqlParser/commit/d34ebcab6ac939f) wumpz *2016-08-13 22:20:27* + +**Update Alter and add AlterExpression class for multiple ADD/DROP expressions in a single ALTER statement** + +* Update .jjt file to break out the AlterExpression into its own class and for Alter to compose multiple AlterExpressions +* Update AlterTest for new AlterExpressions and test for multiple ADD/DROP statements in a single ALTER + +[e8d1c](https://github.com/JSQLParser/JSqlParser/commit/e8d1cf2cb1db16c) Rob Story *2016-08-11 19:24:41* + +**Support for parse delete from table using join to another table like:** + +* DELETE posts +* FROM posts +* INNER JOIN projects ON projects.project_id = posts.project_id +* WHERE projects.client_id = :client_id +* This necessitated some changes to the DeleteTest class, +* specifically: +* JSqlParserCC.jjt - changes on grammar of Delete statements. +* Delete toString and DeleteDeParser. + +[b6eb5](https://github.com/JSQLParser/JSqlParser/commit/b6eb57b61f7b205) Lucas Oliveira *2016-08-06 16:28:11* + +**fix bug of TablesNamesFinder when SubSlect has withItemsList, add corresponding test case** + + +[276dd](https://github.com/JSQLParser/JSqlParser/commit/276ddc8a4dd8bf7) Xin Quan *2016-08-04 01:44:08* + +**fixes #309** + + +[37f06](https://github.com/JSQLParser/JSqlParser/commit/37f061014e21f01) wumpz *2016-08-03 22:02:45* + +**fixes #309** + + +[acd16](https://github.com/JSQLParser/JSqlParser/commit/acd16e59b8d8378) wumpz *2016-08-03 22:02:04* + +**fixes #303** + + +[043a5](https://github.com/JSQLParser/JSqlParser/commit/043a5cb59727cda) wumpz *2016-08-03 21:31:11* + +**fixes #303** + + +[76982](https://github.com/JSQLParser/JSqlParser/commit/76982f7b00b54f7) wumpz *2016-08-03 21:30:04* + +**intruced new test for oracle join syntax** + + +[cb8dd](https://github.com/JSQLParser/JSqlParser/commit/cb8ddd71254a640) wumpz *2016-08-03 21:05:38* + +**fixes #246** + + +[822bb](https://github.com/JSQLParser/JSqlParser/commit/822bbbe78cc8481) wumpz *2016-07-31 20:56:56* + +**fixes #247** + + +[42636](https://github.com/JSQLParser/JSqlParser/commit/4263651d43d4c60) wumpz *2016-07-28 20:13:41* + +**test for issue 265** + + +[59f7e](https://github.com/JSQLParser/JSqlParser/commit/59f7ec2a2a432de) wumpz *2016-07-24 22:28:08* + +**fixes #292** + + +[f0b35](https://github.com/JSQLParser/JSqlParser/commit/f0b350d13756b1f) wumpz *2016-07-24 22:13:37* + +**fixes #299** + + +[d2ad3](https://github.com/JSQLParser/JSqlParser/commit/d2ad3dfe936c8ce) wumpz *2016-07-24 22:05:14* + +**fixes #311** + + +[dfd2f](https://github.com/JSQLParser/JSqlParser/commit/dfd2fe55f0ad2bb) wumpz *2016-07-22 07:25:01* + +**** + + +[84bf0](https://github.com/JSQLParser/JSqlParser/commit/84bf0650e8f7d55) wumpz *2016-07-21 14:08:19* + +**first try of error recovery for statement and statements** + + +[a7247](https://github.com/JSQLParser/JSqlParser/commit/a7247eb48369472) wumpz *2016-07-21 07:33:49* + +**some refactoring** + + +[1e307](https://github.com/JSQLParser/JSqlParser/commit/1e30760dce107d9) wumpz *2016-07-18 16:50:28* + +**The previous pull request broke the build. Besides being a keyword, 'double' is also a function name. Add K_DOUBLE to the RelObjectNameExt() function to pick up this distinction.** + + +[8bfc1](https://github.com/JSQLParser/JSqlParser/commit/8bfc1583f12049c) Tom Moore *2016-07-11 19:14:06* + +**Add a double precision cast type** + + +[60ad1](https://github.com/JSQLParser/JSqlParser/commit/60ad18ed1a10328) Tom Moore *2016-07-11 17:59:53* + +**removed one lookahead and improved parenthesis parsing** + + +[84a88](https://github.com/JSQLParser/JSqlParser/commit/84a883614af908a) wumpz *2016-06-30 18:41:06* + +**removed one lookahead and improved parenthesis parsing** + + +[51b39](https://github.com/JSQLParser/JSqlParser/commit/51b39c55aaaa58c) wumpz *2016-06-30 18:37:23* + +**fixes #296** + +* refactored getTableList method of TableNamesFinder + +[3ccca](https://github.com/JSQLParser/JSqlParser/commit/3ccca01bbc85778) wumpz *2016-06-28 12:16:39* + +**fixes #295** + + +[b877d](https://github.com/JSQLParser/JSqlParser/commit/b877da0a425c01f) wumpz *2016-06-28 08:19:36* + +**fixes #293** + + +[c1d0b](https://github.com/JSQLParser/JSqlParser/commit/c1d0b2f5283d8bb) wumpz *2016-06-28 00:11:15* + +**introduced OSGi metadata** + + +[89daf](https://github.com/JSQLParser/JSqlParser/commit/89dafaedeb69d6a) wumpz *2016-06-23 21:58:22* + +**fixes #291** + + +[63fa2](https://github.com/JSQLParser/JSqlParser/commit/63fa2f66b537731) wumpz *2016-06-23 21:40:57* + +**fixes #291** + + +[da42b](https://github.com/JSQLParser/JSqlParser/commit/da42b1dce108dd9) wumpz *2016-06-23 21:37:51* + +**fixes #278** + + +[12341](https://github.com/JSQLParser/JSqlParser/commit/1234127a47199e6) wumpz *2016-06-21 23:02:11* + +**fixes #278** + + +[faf8c](https://github.com/JSQLParser/JSqlParser/commit/faf8c6adea9bb28) wumpz *2016-06-21 22:58:40* + +**fixes #287** + + +[b1bea](https://github.com/JSQLParser/JSqlParser/commit/b1bea0273c5557a) wumpz *2016-06-21 20:50:02* + +**fixes #270** + + +[37c83](https://github.com/JSQLParser/JSqlParser/commit/37c8313e46e45a7) wumpz *2016-06-21 20:12:55* + +**** + + +[d3d66](https://github.com/JSQLParser/JSqlParser/commit/d3d66f819662698) wumpz *2016-06-20 07:08:58* + +**** + + +[0d1d1](https://github.com/JSQLParser/JSqlParser/commit/0d1d1c066d77ded) wumpz *2016-06-19 21:15:55* + +**fixes #284** + + +[8e7ba](https://github.com/JSQLParser/JSqlParser/commit/8e7ba38a39c6f85) wumpz *2016-06-19 20:09:07* + +**Implemented table check constraint for named constraints.** + +* 1. Added named constraint to create table. +* 2. Added check constraint to alter table statement. +* 3. Added CheckConstraint type. +* Tests: +* 4. Added create table test. +* 5. Added alter table test. + +[401d2](https://github.com/JSQLParser/JSqlParser/commit/401d279ef7e6ef9) Megan Woods *2016-06-16 14:56:01* + +**** + + +[04fc3](https://github.com/JSQLParser/JSqlParser/commit/04fc3aa9b53c8a9) wumpz *2016-06-15 20:50:52* + +**** + + +[bddbe](https://github.com/JSQLParser/JSqlParser/commit/bddbe588a759dd0) wumpz *2016-06-15 20:45:51* + +**Implemented:** + +* 1. UPDATE .. RETURNING col, col as Alias +* 2. UPDATE .. RETURNING * +* Tested: +* 3. UPDATE .. ORDER BY .. LIMIT .. RETURNING +* 4. UPDATE .. RETURNING +* Item 4 represents the PostgreSQL UPDATE .. RETURNING Syntax without ORDER BY and LIMIT. +* See: https://www.postgresql.org/docs/9.5/static/sql-update.html + +[f4526](https://github.com/JSQLParser/JSqlParser/commit/f452638f0f04f99) Megan Woods *2016-06-15 09:12:14* + +**** + + +[40aba](https://github.com/JSQLParser/JSqlParser/commit/40aba736f79c495) wumpz *2016-06-12 11:12:57* + +**-- added scalar time functions of ANSI SQL** + + +[f51df](https://github.com/JSQLParser/JSqlParser/commit/f51df4b5f7d51e2) ChrissW-R1 *2016-06-08 12:57:26* + +**** + + +[24c87](https://github.com/JSQLParser/JSqlParser/commit/24c874afad3110f) wumpz *2016-06-06 21:50:44* + +**updated readme** + + +[3bc31](https://github.com/JSQLParser/JSqlParser/commit/3bc316df743ab09) wumpz *2016-05-24 09:45:34* + +**Add a test-case for Hive's LEFT SEMI JOIN** + + +[e56fb](https://github.com/JSQLParser/JSqlParser/commit/e56fbe984cfab98) Vu Nhan *2016-05-19 04:53:22* + +**Add support for Hive's LEFT SEMI JOIN** + + +[fd03a](https://github.com/JSQLParser/JSqlParser/commit/fd03ad4f6bdd06a) Vu Nhan *2016-05-19 04:05:43* + +**fixes #243** + + +[bb978](https://github.com/JSQLParser/JSqlParser/commit/bb978c45b4d744d) wumpz *2016-05-16 20:49:58* + +**fixes #243** + + +[780ba](https://github.com/JSQLParser/JSqlParser/commit/780ba125a5807b2) wumpz *2016-05-16 20:47:32* + +**fixes #261** + + +[10e68](https://github.com/JSQLParser/JSqlParser/commit/10e68b5c3c58296) wumpz *2016-05-16 20:03:07* + +**updated readme** + + +[77ba3](https://github.com/JSQLParser/JSqlParser/commit/77ba380cfb639c4) wumpz *2016-05-06 06:06:33* + +**** + + +[57145](https://github.com/JSQLParser/JSqlParser/commit/5714516d314f31d) wumpz *2016-04-28 22:15:18* + +**Added ability to have operators like '>=' or '<=' separated by a space.** + +* This includes: +* Modifying the JJT syntax to support the 'space in the middle' versions +* of operators (any quantity of whitespace is supported). +* Modifying the various operators to inherit from a new +* 'ComparisonOperator' class, which handles the (previously NotEqualsTo- +* only) logic for capturing the form of the operator. +* Giving each of the various operators a constructor that accepts the +* syntax used. +* Modifying TestUtils to strip comments out before comparing SQL text +* (necessary because condition07.sql is now passing, and has a comment). +* Updating SpecialOracleTest to indicate 130 tests passing now +* (condition7.sql now passes). +* Adding a new test specifically for operators into SpecialOracleTest. +* NOTE: Because the "! =" form of the 'not equals' operator means something +* different in PostgresSQL (factorial of previous argument + equals), we do +* NOT include that case. + +[9886b](https://github.com/JSQLParser/JSqlParser/commit/9886b02975d1749) Dave Lindquist *2016-04-28 13:28:58* + +**Corrected "MERGE INTO" parsing for more complicated statements.** + +* Specifically: +* Changed "Condition" to "Expression" for the "ON" clause -- this is +* needed to handle "ON" clauses that have "a = y AND b = z" or other +* more complicated expressions (basically the same as the "ON" clause +* in a SELECT query). +* Also changed the "WHERE" and "DELETE WHERE" clauses in the same +* fashion ('Condition' becomes 'Expression'), as they too support +* multiple conditions. +* Corrected the toString on the MergeUpdate clause, which was missing a +* comma between the fields. +* Added a new, more complicated MERGE INTO statement to the MergeTest +* class. + +[7efd5](https://github.com/JSQLParser/JSqlParser/commit/7efd58f7704a0ff) Dave Lindquist *2016-04-28 13:19:34* + +**added for update test** + + +[d54b8](https://github.com/JSQLParser/JSqlParser/commit/d54b82ba62f1133) wumpz *2016-04-27 14:23:55* + +**fixes #253** + + +[75be4](https://github.com/JSQLParser/JSqlParser/commit/75be42659dc3a76) wumpz *2016-04-26 06:11:13* + +**fixed #245** + + +[01287](https://github.com/JSQLParser/JSqlParser/commit/012874f905adabe) wumpz *2016-04-15 22:01:56* + +**fixes #244** + + +[2204a](https://github.com/JSQLParser/JSqlParser/commit/2204a5fc85fb99d) wumpz *2016-04-15 20:10:32* + +**Update README.md** + + +[ac4a5](https://github.com/JSQLParser/JSqlParser/commit/ac4a56151b46d0b) Tobias *2016-04-14 19:30:09* + +**fixes #240** + +* fixes #241 + +[7f8b5](https://github.com/JSQLParser/JSqlParser/commit/7f8b59b31e44521) wumpz *2016-04-05 06:25:57* + +**small modifications, reduces some semantic lookaheads** + + +[7f5b6](https://github.com/JSQLParser/JSqlParser/commit/7f5b61e60bf037b) wumpz *2016-03-29 11:34:17* + +**fixed #228** + + +[3dfae](https://github.com/JSQLParser/JSqlParser/commit/3dfae9c62615711) wumpz *2016-03-17 08:40:24* + +**fixed #228** + + +[8f9b2](https://github.com/JSQLParser/JSqlParser/commit/8f9b2b905c00c68) wumpz *2016-03-17 08:38:35* + +**fixed #232 without correction of order of update and insert** + + +[7e2e7](https://github.com/JSQLParser/JSqlParser/commit/7e2e7200ce48672) wumpz *2016-03-17 08:28:47* + +**fixed some whitespace differences between deparser and toString regarding NOT expression** + + +[f4b25](https://github.com/JSQLParser/JSqlParser/commit/f4b25599a8919d4) wumpz *2016-03-17 08:16:24* + +**Update README.md** + + +[12009](https://github.com/JSQLParser/JSqlParser/commit/120096068fa4b3d) Tobias *2016-03-17 07:51:11* + +**update release info** + + +[eccd6](https://github.com/JSQLParser/JSqlParser/commit/eccd66f01f924f8) wumpz *2016-03-14 00:27:18* + +**Fixing uncaught exception** + + +[4fad4](https://github.com/JSQLParser/JSqlParser/commit/4fad4af810aef8d) emopers *2016-01-12 19:30:52* + + +## jsqlparser-0.9.5 (2016-03-13) + +### Other changes + +**no message** + + +[ffcfe](https://github.com/JSQLParser/JSqlParser/commit/ffcfe41096bca29) wumpz *2016-03-13 23:55:09* + +**** + + +[3c863](https://github.com/JSQLParser/JSqlParser/commit/3c8635280dbd959) wumpz *2016-03-13 23:35:37* + +**introduced boolean values within conditions** + + +[36a62](https://github.com/JSQLParser/JSqlParser/commit/36a62e9de7ec65e) wumpz *2016-03-10 21:19:22* + +**introduced boolean values within conditions** + + +[a8333](https://github.com/JSQLParser/JSqlParser/commit/a8333bf9310355b) wumpz *2016-03-10 21:16:28* + +**introduced boolean values within conditions** + + +[68e5b](https://github.com/JSQLParser/JSqlParser/commit/68e5b53e834f02f) wumpz *2016-03-10 21:11:01* + +**fixes #230** + + +[19915](https://github.com/JSQLParser/JSqlParser/commit/1991507179224f0) wumpz *2016-03-07 23:17:40* + +**multiple code improvements: squid:S1905, squid:S00122, squid:S1155, squid:S00105** + + +[905b2](https://github.com/JSQLParser/JSqlParser/commit/905b28d34771d15) George Kankava *2016-03-03 11:40:31* + +**fixed #226** + + +[67b17](https://github.com/JSQLParser/JSqlParser/commit/67b178b533128ae) wumpz *2016-02-27 13:54:58* + +**fixes #223** + + +[04e5c](https://github.com/JSQLParser/JSqlParser/commit/04e5c8b354f149d) wumpz *2016-02-11 21:23:51* + +**reduces a bunch of dynamic lookaheads to fixed ones** + + +[4c764](https://github.com/JSQLParser/JSqlParser/commit/4c764f54da7d820) wumpz *2016-02-11 20:51:02* + +**integrated changes of #225** + + +[eb5d7](https://github.com/JSQLParser/JSqlParser/commit/eb5d7a29737c6c5) wumpz *2016-02-11 20:41:23* + +**Multiple code improvements fix 1: squid:S1199, squid:S1066, squid:S1854, squid:S1165** + + +[af5d3](https://github.com/JSQLParser/JSqlParser/commit/af5d3cddf3564cf) George Kankava *2016-02-10 16:11:10* + +**Update README.md** + + +[e455c](https://github.com/JSQLParser/JSqlParser/commit/e455ce024f53779) Tobias *2016-02-10 06:43:04* + +**improved parsing performance** + + +[c78aa](https://github.com/JSQLParser/JSqlParser/commit/c78aa03d1af2cfe) wumpz *2016-02-09 22:30:20* + +**fixes #221** + + +[579f0](https://github.com/JSQLParser/JSqlParser/commit/579f0bc159aa053) wumpz *2016-02-04 22:10:43* + +**fixes #221** + + +[4a12d](https://github.com/JSQLParser/JSqlParser/commit/4a12dc10014ec51) wumpz *2016-02-04 22:07:12* + +**cleaned up some lookaheads** + + +[0cc80](https://github.com/JSQLParser/JSqlParser/commit/0cc809ea7de5238) wumpz *2016-02-04 08:58:52* + +**** + + +[36a4a](https://github.com/JSQLParser/JSqlParser/commit/36a4a0f9918ef9e) wumpz *2016-02-02 06:45:45* + +**fixes #217** + + +[de61c](https://github.com/JSQLParser/JSqlParser/commit/de61c0b92a25e03) wumpz *2016-02-02 06:21:59* + +**Added reference options foreign keys support (ON UPDATE/DELETE NO ACTION/CASCADE) and Full text indexes (FULLTEXT idx(text1))** + + +[c2956](https://github.com/JSQLParser/JSqlParser/commit/c29565bcaed42b1) pabloa *2016-02-01 21:57:27* + +**multiple code improvements 1** + + +[e6bec](https://github.com/JSQLParser/JSqlParser/commit/e6becde1df91db5) George Kankava *2016-02-01 07:35:08* + +**Support of mysql create statements with timestamp column with ON UPDATE. Example: CREATE TABLE test (applied timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)** + + +[9dcaa](https://github.com/JSQLParser/JSqlParser/commit/9dcaaee63e4b2b3) pabloa98@gmail.com *2016-01-24 08:37:38* + +**fixes #151** + + +[f5b51](https://github.com/JSQLParser/JSqlParser/commit/f5b515be9351c77) wumpz *2016-01-06 09:12:54* + +**corrected lookahead for tablefunctions** + + +[8036e](https://github.com/JSQLParser/JSqlParser/commit/8036edd80628410) wumpz *2015-12-09 22:01:02* + +**TableFunction extends FunctionItem** + + +[17371](https://github.com/JSQLParser/JSqlParser/commit/17371ae38e0384e) tfedkiv *2015-12-08 08:39:07* + +**added TableFunction alias suppurt** + +* added TableFunction unit tests + +[88edd](https://github.com/JSQLParser/JSqlParser/commit/88eddaf50dada22) tfedkiv *2015-12-07 15:27:02* + +**fixed verion** + + +[a5a5f](https://github.com/JSQLParser/JSqlParser/commit/a5a5f9ee5b0d28d) ftaras *2015-12-07 14:25:07* + +**added support of SELECT FROM table function (h2)** + + +[0403f](https://github.com/JSQLParser/JSqlParser/commit/0403fdda2918311) tfedkiv *2015-12-07 14:23:39* + +**replaced size() with isEmpty()** + + +[1d634](https://github.com/JSQLParser/JSqlParser/commit/1d6348126dceec7) wumpz *2015-12-06 22:03:20* + +**jdk 8 build included into travis** + + +[830be](https://github.com/JSQLParser/JSqlParser/commit/830be49c4de1311) wumpz *2015-11-27 22:12:36* + +**increased version of maven-javadoc-plugin** + + +[1b842](https://github.com/JSQLParser/JSqlParser/commit/1b842f891e8b370) wumpz *2015-11-26 07:34:47* + +**** + + +[01d25](https://github.com/JSQLParser/JSqlParser/commit/01d25deaae72ba2) wumpz *2015-11-26 07:24:43* + +**Issue 198: add profile to ensure doclint is turned off with Java 8+. Without this, the project won't build on Java 8. (You can run mvn test successfully, but not mvn package.)** + + +[bb3ef](https://github.com/JSQLParser/JSqlParser/commit/bb3ef6188982b9b) James Heather *2015-11-25 13:43:57* + +**fixes #193** + + +[5d7bd](https://github.com/JSQLParser/JSqlParser/commit/5d7bdb9b254bc19) wumpz *2015-11-25 06:37:36* + +**fixes #195** + + +[ab1ad](https://github.com/JSQLParser/JSqlParser/commit/ab1ad25b6862e08) wumpz *2015-11-25 06:22:12* + +**Issue 195:** + +* Add support for ORDER BY and LIMIT in UPDATE and DELETE statements (as supported by MySQL). +* LimitDeparser and OrderByDeParser have been pulled out into separate classes to avoid code duplication from SelectDeParser. + +[a3133](https://github.com/JSQLParser/JSqlParser/commit/a31333a65141e27) James Heather *2015-11-24 14:57:04* + +**corrects parsing error** + + +[975cd](https://github.com/JSQLParser/JSqlParser/commit/975cddfb85bd0b3) wumpz *2015-11-20 22:44:01* + +**** + + +[f1d21](https://github.com/JSQLParser/JSqlParser/commit/f1d213636786e0a) wumpz *2015-11-20 14:27:19* + +**fixes #194** + + +[f1c98](https://github.com/JSQLParser/JSqlParser/commit/f1c9835bd34d3f1) wumpz *2015-11-18 21:17:49* + +**support INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] ...** + + +[00c18](https://github.com/JSQLParser/JSqlParser/commit/00c18698acb0316) wanghai *2015-11-18 09:10:31* + +**corrected lookahead** + + +[a97e9](https://github.com/JSQLParser/JSqlParser/commit/a97e9c94fef03c6) wumpz *2015-11-17 22:24:57* + +**fixes #192, fixes #191** + + +[2fddf](https://github.com/JSQLParser/JSqlParser/commit/2fddf8c8bf4072c) wumpz *2015-11-14 23:56:53* + +**replaceDeParser parser itemList** + + +[3c605](https://github.com/JSQLParser/JSqlParser/commit/3c6057b1f8d6311) wanghai *2015-11-13 08:45:21* + +**support insert ... on duplicate key update...** + + +[7d7fa](https://github.com/JSQLParser/JSqlParser/commit/7d7fae8a31abc3c) wanghai *2015-11-13 08:43:57* + +**fixes #181, added drop deparser** + + +[44091](https://github.com/JSQLParser/JSqlParser/commit/44091c622316769) wumpz *2015-11-09 22:33:56* + +**alter table support improved** + + +[ad0dd](https://github.com/JSQLParser/JSqlParser/commit/ad0dd23e8951e27) wumpz *2015-10-27 22:37:56* + +**fixes #180** + + +[0bb23](https://github.com/JSQLParser/JSqlParser/commit/0bb2358eaff8956) wumpz *2015-10-21 06:44:00* + +**#182** + + +[a3695](https://github.com/JSQLParser/JSqlParser/commit/a369537d0d3f51c) wumpz *2015-10-21 05:56:19* + +**Support for alter table drop column/constraint** + +* Fix for Issue #184 + +[58dd2](https://github.com/JSQLParser/JSqlParser/commit/58dd28aaf9b9273) schweighart *2015-10-20 21:34:51* + +**updated readme** + + +[e570a](https://github.com/JSQLParser/JSqlParser/commit/e570a919f24d385) wumpz *2015-10-19 13:16:54* + +**Improved required coverage** + + +[41cbd](https://github.com/JSQLParser/JSqlParser/commit/41cbd7f96ab9139) Rapševičius Valdas *2015-10-14 11:05:36* + +**Refactored Oracle Hint tests, added set selects** + + +[7b4fe](https://github.com/JSQLParser/JSqlParser/commit/7b4feb00cd4d312) Rapševičius Valdas *2015-10-13 22:37:29* + +**Added OracleHint class, grammar and model support, tests** + + +[f7f8d](https://github.com/JSQLParser/JSqlParser/commit/f7f8d03bfac9e09) Rapševičius Valdas *2015-10-13 22:06:16* + +**resolved choice conflict** + + +[b6f71](https://github.com/JSQLParser/JSqlParser/commit/b6f71e619c1a24d) wumpz *2015-10-08 11:11:42* + +**fixes #178, merged upstream** + + +[11dbd](https://github.com/JSQLParser/JSqlParser/commit/11dbda3b999d82b) Gabor Bota *2015-10-08 09:20:15* + +**added restrict and set null for alter statement** + + +[36379](https://github.com/JSQLParser/JSqlParser/commit/36379b2f646326c) wumpz *2015-10-07 21:38:53* + +**fixes #178** + + +[cb267](https://github.com/JSQLParser/JSqlParser/commit/cb2674e2b94ee95) Gabor Bota *2015-10-07 13:00:53* + +**fixes #174** + + +[da1e0](https://github.com/JSQLParser/JSqlParser/commit/da1e074b308d74a) wumpz *2015-10-06 21:18:27* + +**fixes #174** + + +[8d419](https://github.com/JSQLParser/JSqlParser/commit/8d419d31bb8be29) wumpz *2015-10-06 21:15:40* + +**simple merge implementation** + + +[bc4bc](https://github.com/JSQLParser/JSqlParser/commit/bc4bc9e52192b21) wumpz *2015-10-01 22:52:36* + +**simple merge implementation** + + +[af5a0](https://github.com/JSQLParser/JSqlParser/commit/af5a09078134f6c) wumpz *2015-10-01 22:44:50* + +**fixes #176** + + +[c6e93](https://github.com/JSQLParser/JSqlParser/commit/c6e9389599ed161) wumpz *2015-10-01 21:50:13* + +**fixes #176** + + +[fb4d4](https://github.com/JSQLParser/JSqlParser/commit/fb4d43b5a41d66b) wumpz *2015-10-01 21:45:44* + +**fixes #177** + + +[9999c](https://github.com/JSQLParser/JSqlParser/commit/9999c50ef3908a3) wumpz *2015-10-01 21:11:43* + +**** + + +[1fb42](https://github.com/JSQLParser/JSqlParser/commit/1fb426e08300adf) wumpz *2015-10-01 20:24:27* + +**merge impl started** + + +[8d8c0](https://github.com/JSQLParser/JSqlParser/commit/8d8c0e4ce70d944) wumpz *2015-09-24 22:23:11* + +**fixes #172** + + +[c690f](https://github.com/JSQLParser/JSqlParser/commit/c690f7f1efa5815) wumpz *2015-09-22 05:33:16* + +**** + + +[ae2c8](https://github.com/JSQLParser/JSqlParser/commit/ae2c87f5a19d9b0) wumpz *2015-09-16 18:55:58* + +**** + + +[03a4f](https://github.com/JSQLParser/JSqlParser/commit/03a4fc7d339cbb0) wumpz *2015-09-16 05:53:18* + +**fixes #167** + + +[57f30](https://github.com/JSQLParser/JSqlParser/commit/57f3099b869cc43) wumpz *2015-09-16 05:52:27* + +**fixes #167** + + +[71d9f](https://github.com/JSQLParser/JSqlParser/commit/71d9fd97fd92fbc) wumpz *2015-09-16 05:49:45* + +**fixes #77** + + +[0e51d](https://github.com/JSQLParser/JSqlParser/commit/0e51dacc2a0df3a) wumpz *2015-09-16 05:46:49* + +**fixes #170** + + +[cf9bf](https://github.com/JSQLParser/JSqlParser/commit/cf9bf8453791662) wumpz *2015-09-13 21:26:48* + + +## jsqlparser-0.9.4 (2015-09-13) + +### Other changes + +**** + + +[e9024](https://github.com/JSQLParser/JSqlParser/commit/e9024106aa5d994) wumpz *2015-09-07 19:26:26* + +**fixes #165** + + +[28101](https://github.com/JSQLParser/JSqlParser/commit/28101309a3502db) wumpz *2015-09-03 20:03:48* + +**fixes #165** + + +[bf06e](https://github.com/JSQLParser/JSqlParser/commit/bf06e6ccc269efa) wumpz *2015-09-03 20:02:25* + +**fixes #166** + + +[c244c](https://github.com/JSQLParser/JSqlParser/commit/c244ccb5cd00d0d) wumpz *2015-09-03 14:02:17* + +**fixed #162** + + +[46381](https://github.com/JSQLParser/JSqlParser/commit/463817b435ffdd5) wumpz *2015-08-07 20:48:55* + +**fixed #162** + + +[e3b73](https://github.com/JSQLParser/JSqlParser/commit/e3b73a35afbcb74) wumpz *2015-08-07 20:48:00* + +**fixed #160** + + +[432c0](https://github.com/JSQLParser/JSqlParser/commit/432c0ef9a7d462d) wumpz *2015-08-07 20:24:40* + +**no message** + + +[e91e0](https://github.com/JSQLParser/JSqlParser/commit/e91e074d8c773a6) wumpz *2015-08-05 20:44:25* + +**Add support for variable support to "SELECT SKIP FIRST ..." construct** + +* The grammar for the construct in informix [1] mentions the possibility, that <ROWCOUNT> can be either +* an integer or a host variable or local SPL variable storing the value of max. The case for plain integers and +* jdbc variables is covered by the first commit While this commit adds support for constructs using SPL +* variables. SPL variables must follow identifier rules [2][3]. +* [1] http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0156.htm +* [2] http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_1306.htm?lang=de +* [3] http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_1660.htm%23ids_sqs_1660?lang=de + +[9e77b](https://github.com/JSQLParser/JSqlParser/commit/9e77b6bd55ce242) Matthias Bläsing *2015-08-02 14:03:23* + +**simplified lookahead** + + +[a44ac](https://github.com/JSQLParser/JSqlParser/commit/a44acb7a785394b) wumpz *2015-08-01 21:42:46* + +**simplified lookahead** + + +[0fc8e](https://github.com/JSQLParser/JSqlParser/commit/0fc8e29a3a5df3d) wumpz *2015-08-01 21:33:31* + +**Update README.md** + + +[b3d76](https://github.com/JSQLParser/JSqlParser/commit/b3d76e7847c6f90) Tobias *2015-07-31 05:27:21* + +**** + + +[6f2a1](https://github.com/JSQLParser/JSqlParser/commit/6f2a1323d03ae00) wumpz *2015-07-30 21:35:13* + +**added another testcase for #154** + + +[e889c](https://github.com/JSQLParser/JSqlParser/commit/e889cf345a84b8d) wumpz *2015-07-29 10:50:10* + +**Implement support for "SELECT SKIP FIRST ..." construct** + + +[4a33d](https://github.com/JSQLParser/JSqlParser/commit/4a33d8c380260d2) Matthias Bläsing *2015-07-25 19:16:23* + +**test for #154 included** + + +[001d6](https://github.com/JSQLParser/JSqlParser/commit/001d665d32c6df5) wumpz *2015-07-23 09:49:24* + +**** + + +[157ee](https://github.com/JSQLParser/JSqlParser/commit/157eebf7a07e23c) wumpz *2015-07-15 20:55:25* + +**fixes #150** + + +[5b3ec](https://github.com/JSQLParser/JSqlParser/commit/5b3ec5ac9f502d4) wumpz *2015-07-15 20:42:54* + +**fixes #149** + + +[d2b07](https://github.com/JSQLParser/JSqlParser/commit/d2b0706e6f175db) wumpz *2015-07-15 20:20:14* + +**Fix inline usage of foreign keys in CREATE TABLE statements** + + +[23c19](https://github.com/JSQLParser/JSqlParser/commit/23c19a53fd72c26) Georg Semmler *2015-07-09 15:41:39* + +**fixes #146** + + +[978b6](https://github.com/JSQLParser/JSqlParser/commit/978b60ebd0ffbbd) wumpz *2015-07-03 13:19:54* + +**reincluded Apache 2.0 license** + + +[83899](https://github.com/JSQLParser/JSqlParser/commit/83899f824659012) wumpz *2015-07-02 20:54:03* + +**reincluded Apache 2.0 license** + + +[7e52d](https://github.com/JSQLParser/JSqlParser/commit/7e52dd7cb474bc3) wumpz *2015-07-02 20:52:04* + +**corrected deparser** + + +[cc4a5](https://github.com/JSQLParser/JSqlParser/commit/cc4a5fa149aeac4) wumpz *2015-07-01 20:51:03* + +**updated readme** + + +[44716](https://github.com/JSQLParser/JSqlParser/commit/4471653646f286e) wumpz *2015-07-01 20:04:46* + +**fixes #138 and AnyComparisionExpression** + + +[ab2b2](https://github.com/JSQLParser/JSqlParser/commit/ab2b2c07759af48) wumpz *2015-07-01 19:55:02* + +**null toString used** + + +[e425d](https://github.com/JSQLParser/JSqlParser/commit/e425dc2528cc4d3) wumpz *2015-06-24 21:20:29* + +**completed any and all comparisions** + + +[fc076](https://github.com/JSQLParser/JSqlParser/commit/fc076e89580ca78) wumpz *2015-06-24 20:59:45* + +**Exceptions skiped during coverage tests** + + +[1849c](https://github.com/JSQLParser/JSqlParser/commit/1849c5b3f5ca03f) wumpz *2015-06-10 05:50:43* + +**Update README.md** + + +[d561d](https://github.com/JSQLParser/JSqlParser/commit/d561d8ad60b84fc) Tobias *2015-06-09 21:39:04* + +**** + + +[a17d6](https://github.com/JSQLParser/JSqlParser/commit/a17d6280b1ecdf6) wumpz *2015-06-09 21:29:55* + +**coveralls** + + +[5858a](https://github.com/JSQLParser/JSqlParser/commit/5858aa7a2215300) wumpz *2015-06-09 21:03:49* + +**** + + +[1d71c](https://github.com/JSQLParser/JSqlParser/commit/1d71c51a934dd1e) wumpz *2015-06-08 20:14:29* + +**completed ExpressionVisitorAdapter** + + +[8ec0b](https://github.com/JSQLParser/JSqlParser/commit/8ec0b195ba8da00) wumpz *2015-06-07 22:37:50* + +**completed ExpressionVisitorAdapter** + + +[cf703](https://github.com/JSQLParser/JSqlParser/commit/cf703d8225908d9) wumpz *2015-06-05 22:32:50* + +**completed ExpressionVisitorAdapter** + + +[348fd](https://github.com/JSQLParser/JSqlParser/commit/348fd7ffce92125) wumpz *2015-06-05 22:29:30* + +**updated some plugin versions** + + +[94c63](https://github.com/JSQLParser/JSqlParser/commit/94c63556b9d92a1) wumpz *2015-06-05 21:08:48* + +**fixes #143** + +* some refactorings done + +[4d2a0](https://github.com/JSQLParser/JSqlParser/commit/4d2a0a1151faff1) wumpz *2015-06-05 20:50:28* + +**fixes #143** + +* some refactorings done + +[f71c3](https://github.com/JSQLParser/JSqlParser/commit/f71c307f15c4cde) wumpz *2015-06-05 20:48:45* + +**fixes #142** + + +[3d340](https://github.com/JSQLParser/JSqlParser/commit/3d340377b37ddd9) wumpz *2015-06-05 20:28:28* + +**fixes #141** + + +[b78ed](https://github.com/JSQLParser/JSqlParser/commit/b78ed4b46472902) wumpz *2015-06-05 20:09:32* + +**** + + +[5123f](https://github.com/JSQLParser/JSqlParser/commit/5123fe295a4142b) wumpz *2015-06-05 20:07:12* + +**root nodes established but not linked** + + +[71305](https://github.com/JSQLParser/JSqlParser/commit/71305d9cbdc0e5b) wumpz *2015-05-31 20:39:43* + +**root nodes established but not linked** + + +[edd0c](https://github.com/JSQLParser/JSqlParser/commit/edd0c765ea34898) wumpz *2015-05-31 19:54:52* + +**astnodes for columns and tables** + + +[d66a9](https://github.com/JSQLParser/JSqlParser/commit/d66a93a4066ccff) wumpz *2015-05-29 22:49:13* + +**simple jjtree start** + + +[e594e](https://github.com/JSQLParser/JSqlParser/commit/e594e591e79f555) wumpz *2015-05-27 22:34:35* + +**simple jjtree start** + + +[d9f5f](https://github.com/JSQLParser/JSqlParser/commit/d9f5fef5f9d43e1) wumpz *2015-05-24 21:08:32* + +**fixes #134 - preserve order of query** + + +[59470](https://github.com/JSQLParser/JSqlParser/commit/594705ae61fd1b5) wumpz *2015-05-24 20:28:51* + +**fixes #136** + + +[5adeb](https://github.com/JSQLParser/JSqlParser/commit/5adebeee953bd2a) tejksat *2015-05-24 10:00:31* + +**fixes #134** + + +[d99e6](https://github.com/JSQLParser/JSqlParser/commit/d99e603e0e968f8) wumpz *2015-05-21 21:10:44* + +**fixes #72** + + +[8b540](https://github.com/JSQLParser/JSqlParser/commit/8b540614d7dbe9e) wumpz *2015-05-21 20:28:50* + +**fixes #72** + + +[3aaf1](https://github.com/JSQLParser/JSqlParser/commit/3aaf11d348e0b16) wumpz *2015-05-21 20:26:15* + +**group_concat started** + + +[adca3](https://github.com/JSQLParser/JSqlParser/commit/adca3efe84aaeb3) wumpz *2015-05-20 21:48:36* + +**** + + +[3563c](https://github.com/JSQLParser/JSqlParser/commit/3563c2188f4ffde) wumpz *2015-05-12 22:32:17* + + +## jsqlparser-0.9.3 (2015-05-12) + +### Other changes + +**fixes #69** + + +[16034](https://github.com/JSQLParser/JSqlParser/commit/16034878352a0fe) wumpz *2015-05-10 22:11:41* + +**fixes #69** + + +[35164](https://github.com/JSQLParser/JSqlParser/commit/35164e58c437fdc) wumpz *2015-05-10 22:02:24* + +**fixes #90** + + +[536ba](https://github.com/JSQLParser/JSqlParser/commit/536ba9d091fbe75) wumpz *2015-05-07 22:53:42* + +**fixes #90** + + +[db4a2](https://github.com/JSQLParser/JSqlParser/commit/db4a27e284ace55) wumpz *2015-05-07 22:50:35* + +**** + + +[55b8e](https://github.com/JSQLParser/JSqlParser/commit/55b8e7a4c9c947b) wumpz *2015-05-07 18:41:22* + +**fixes #129** + + +[45132](https://github.com/JSQLParser/JSqlParser/commit/45132a7e3d57b15) wumpz *2015-04-30 19:07:21* + +**fixes #128** + + +[aa291](https://github.com/JSQLParser/JSqlParser/commit/aa2913da90a4a05) wumpz *2015-04-27 21:59:00* + +**Update README.md** + + +[c4f24](https://github.com/JSQLParser/JSqlParser/commit/c4f24e6a30b0b9d) Tobias *2015-04-23 08:56:37* + +**fixes #126 - allows brackets around select** + + +[64b22](https://github.com/JSQLParser/JSqlParser/commit/64b22e45987284e) wumpz *2015-04-22 22:03:21* + +**fixes #125 - added values as a column name** + + +[ac785](https://github.com/JSQLParser/JSqlParser/commit/ac785a405697df4) wumpz *2015-04-16 21:01:18* + +**fixes #110 - first implementation** + + +[94195](https://github.com/JSQLParser/JSqlParser/commit/941952f58f5b5be) wumpz *2015-04-11 17:32:48* + +**updated readme** + + +[f2d48](https://github.com/JSQLParser/JSqlParser/commit/f2d48cf28f452d4) wumpz *2015-04-09 21:52:40* + +**solved some oracle test sql parsings** + + +[b76ba](https://github.com/JSQLParser/JSqlParser/commit/b76baa31439f841) wumpz *2015-04-09 21:45:16* + +**fixes #122** + + +[46f51](https://github.com/JSQLParser/JSqlParser/commit/46f51972cf47885) wumpz *2015-04-09 21:02:10* + +**fixes #123** + + +[68f47](https://github.com/JSQLParser/JSqlParser/commit/68f47dc7c49c1b2) wumpz *2015-04-09 20:23:50* + +**refactoring** + + +[26e1c](https://github.com/JSQLParser/JSqlParser/commit/26e1c0ac1c9221f) wumpz *2015-04-08 21:20:40* + +**refactoring** + + +[a9768](https://github.com/JSQLParser/JSqlParser/commit/a97686797e77480) wumpz *2015-04-08 21:17:30* + +**fixes #120** + + +[c3995](https://github.com/JSQLParser/JSqlParser/commit/c39954916a0ab71) wumpz *2015-04-08 06:11:06* + +**first try to fix #114** + + +[a0d87](https://github.com/JSQLParser/JSqlParser/commit/a0d8733b6c57055) wumpz *2015-04-07 00:48:55* + +**** + + +[73822](https://github.com/JSQLParser/JSqlParser/commit/738226709622311) wumpz *2015-04-06 20:53:58* + +**Update README.md** + + +[ad91b](https://github.com/JSQLParser/JSqlParser/commit/ad91b733c8b495c) Tobias *2015-04-06 20:34:30* + +**travis** + + +[ade82](https://github.com/JSQLParser/JSqlParser/commit/ade827e1eda7248) wumpz *2015-04-06 20:04:47* + +**** + + +[673e0](https://github.com/JSQLParser/JSqlParser/commit/673e00b1996eaac) wumpz *2015-04-06 19:08:34* + +**fixes #109** + + +[a3285](https://github.com/JSQLParser/JSqlParser/commit/a32854822885741) wumpz *2015-04-02 23:08:59* + +**fixes #119** + + +[c9b58](https://github.com/JSQLParser/JSqlParser/commit/c9b58b2b2dfba67) wumpz *2015-04-01 20:31:03* + +**fixes #117** + + +[a3fc1](https://github.com/JSQLParser/JSqlParser/commit/a3fc1f23701d6d6) wumpz *2015-03-28 20:02:28* + +**fixes #117** + + +[b3d91](https://github.com/JSQLParser/JSqlParser/commit/b3d91de4d54153f) wumpz *2015-03-28 19:50:20* + +**** + + +[f194b](https://github.com/JSQLParser/JSqlParser/commit/f194b7cb7cc810d) wumpz *2015-03-04 23:26:13* + +**corrected lookup** + + +[8598d](https://github.com/JSQLParser/JSqlParser/commit/8598da5760028d6) wumpz *2015-03-04 22:33:16* + +**updated readme** + + +[5472e](https://github.com/JSQLParser/JSqlParser/commit/5472e2d60e95590) wumpz *2015-03-04 22:28:45* + +**fixes #115** + + +[a3e02](https://github.com/JSQLParser/JSqlParser/commit/a3e024a0b002ad0) wumpz *2015-03-04 22:18:59* + +**fixes #116** + + +[c916f](https://github.com/JSQLParser/JSqlParser/commit/c916f14c1e5f82c) wumpz *2015-03-04 21:55:29* + +**Update README.md** + + +[18089](https://github.com/JSQLParser/JSqlParser/commit/18089564f2b9efb) Tobias *2015-02-12 22:54:15* + + +## jsqlparser-0.9.2 (2015-02-12) + +### Other changes + +**updated readme** + + +[13d29](https://github.com/JSQLParser/JSqlParser/commit/13d29e0d545bbaa) wumpz *2015-02-12 21:43:13* + +**introduced user variables: fixes #107** + + +[0c288](https://github.com/JSQLParser/JSqlParser/commit/0c2889ca34c88fd) wumpz *2015-02-11 21:21:24* + +**maybe not correct alter statement** + + +[ab001](https://github.com/JSQLParser/JSqlParser/commit/ab00181f492820a) wumpz *2015-02-04 22:53:06* + +**fixes #102** + + +[d603e](https://github.com/JSQLParser/JSqlParser/commit/d603e41768a49fd) wumpz *2015-02-04 21:16:18* + +**Update README.md** + + +[66517](https://github.com/JSQLParser/JSqlParser/commit/6651771afb0754f) Tobias *2015-02-01 20:03:21* + +**fixes #91** + + +[495a7](https://github.com/JSQLParser/JSqlParser/commit/495a7f2590703db) wumpz *2015-02-01 00:07:07* + +**Update README.md** + + +[d0ce4](https://github.com/JSQLParser/JSqlParser/commit/d0ce413581ace0d) Tobias *2015-01-30 21:30:28* + +**fixes #89** + + +[4ac85](https://github.com/JSQLParser/JSqlParser/commit/4ac85f0b27c21ba) wumpz *2015-01-21 20:15:55* + +**pivot function test** + + +[3cc5a](https://github.com/JSQLParser/JSqlParser/commit/3cc5acd2ee83f76) wumpz *2015-01-16 23:33:19* + +**Update README.md** + + +[3bec5](https://github.com/JSQLParser/JSqlParser/commit/3bec524f829975b) Tobias *2015-01-11 10:37:55* + +**fixes #99** + + +[d4bc7](https://github.com/JSQLParser/JSqlParser/commit/d4bc726944700c1) wumpz *2015-01-10 23:10:04* + +**fixes #99** + + +[5ac27](https://github.com/JSQLParser/JSqlParser/commit/5ac27a7ceb6166d) wumpz *2015-01-10 23:08:28* + +**small grammar cleanup** + + +[e4756](https://github.com/JSQLParser/JSqlParser/commit/e47566636b7fd83) wumpz *2014-12-18 21:24:23* + +**fixes #93** + + +[02be9](https://github.com/JSQLParser/JSqlParser/commit/02be9cdbca314f6) wumpz *2014-12-10 23:33:19* + +**fixes #92** + + +[e902a](https://github.com/JSQLParser/JSqlParser/commit/e902a41c71e1b44) wumpz *2014-12-10 23:17:40* + +**updated readme** + + +[32bf3](https://github.com/JSQLParser/JSqlParser/commit/32bf3a2f1798270) wumpz *2014-12-10 21:56:12* + +**add group ba additions to SelectUtils** + + +[dd77b](https://github.com/JSQLParser/JSqlParser/commit/dd77b6c4f2a1f24) wumpz *2014-12-08 22:51:59* + +**** + + +[adcaf](https://github.com/JSQLParser/JSqlParser/commit/adcaf0fe83dad8c) wumpz *2014-12-07 21:54:35* + +**fixes #88** + + +[0d5cc](https://github.com/JSQLParser/JSqlParser/commit/0d5cc58237dbaae) wumpz *2014-12-03 23:45:07* + +**oracle colls started** + + +[e8a18](https://github.com/JSQLParser/JSqlParser/commit/e8a18cc8b76c6bd) wumpz *2014-11-30 20:41:53* + +**options** + + +[2e85a](https://github.com/JSQLParser/JSqlParser/commit/2e85a16ebf7bfe3) wumpz *2014-11-25 00:11:17* + +**updated readme** + + +[72340](https://github.com/JSQLParser/JSqlParser/commit/72340e55d94f68e) wumpz *2014-11-24 20:17:52* + +**added create table parameters to deparser** + + +[05967](https://github.com/JSQLParser/JSqlParser/commit/05967cce8c528db) wumpz *2014-11-24 20:10:48* + +**added create parameters to include into deparser** + + +[6f89e](https://github.com/JSQLParser/JSqlParser/commit/6f89e35e4544112) wumpz *2014-11-23 23:36:35* + +**added commit keyword** + + +[f276b](https://github.com/JSQLParser/JSqlParser/commit/f276b33528821ad) wumpz *2014-11-23 23:26:40* + +**fixes #87** + + +[2056c](https://github.com/JSQLParser/JSqlParser/commit/2056cb064dffb3f) wumpz *2014-11-22 00:27:01* + +**simple cleanup** + + +[6a98d](https://github.com/JSQLParser/JSqlParser/commit/6a98d2bd8dd504b) wumpz *2014-11-20 20:42:39* + +**withitem - deparsing merged and modified** + + +[20e0f](https://github.com/JSQLParser/JSqlParser/commit/20e0f48c1a56da4) wumpz *2014-11-03 22:54:58* + +**use accept() instead of toString() on StatementDeParser** + + +[67497](https://github.com/JSQLParser/JSqlParser/commit/674974ac08f822d) reed1 *2014-11-02 06:53:07* + +**fixes #84** + + +[a5031](https://github.com/JSQLParser/JSqlParser/commit/a5031b403af80e4) wumpz *2014-10-31 22:57:23* + +**for update selects implemented** + + +[92efe](https://github.com/JSQLParser/JSqlParser/commit/92efe5b962ede77) wumpz *2014-10-30 23:59:42* + +**allow 'key' as object name** + + +[32b0a](https://github.com/JSQLParser/JSqlParser/commit/32b0a67999cf9ca) wumpz *2014-10-30 23:19:30* + +**update readme** + + +[d9951](https://github.com/JSQLParser/JSqlParser/commit/d9951d7bc5129da) wumpz *2014-10-22 22:03:20* + +**little housekeeping** + + +[5fb21](https://github.com/JSQLParser/JSqlParser/commit/5fb21dc2f605f81) wumpz *2014-10-22 21:51:37* + +**Manage OFFSET and FETCH clauses in dedicated classes and rules in** + +* jsqlparsercc.jj +* Manage also jdbc parameter in these clauses. + +[26524](https://github.com/JSQLParser/JSqlParser/commit/26524ac850461cb) LionelNirva *2014-10-10 14:38:20* + +**added test for wrong top distinct order.** + + +[ccefb](https://github.com/JSQLParser/JSqlParser/commit/ccefbeb29ac6693) wumpz *2014-10-09 19:23:52* + +**Add support for new SQL Server 2012 and Oracle 12c versions of LIMIT** + +* (equivalent to MySql and PostgreSQL LIMIT ... OFFSET ... clauses) for +* parsing and deparsing. + +[dc215](https://github.com/JSQLParser/JSqlParser/commit/dc215bb6b8cf70b) LionelNirva *2014-10-08 12:38:04* + +**Unit test for the fix Bug when Deparsing SQL Server request having TOP** + +* and DISTINCT clauses. + +[c2ad9](https://github.com/JSQLParser/JSqlParser/commit/c2ad9d2b2c2ee9f) LionelNirva *2014-10-07 14:31:43* + +**little housekeeping** + + +[fd25a](https://github.com/JSQLParser/JSqlParser/commit/fd25ab4b9279003) wumpz *2014-10-05 21:44:57* + +**little housekeeping** + + +[c3ec6](https://github.com/JSQLParser/JSqlParser/commit/c3ec64d426102cc) wumpz *2014-10-05 21:38:24* + +**compile error corrected** + + +[8ae4b](https://github.com/JSQLParser/JSqlParser/commit/8ae4bead1868ac7) wumpz *2014-10-05 21:15:34* + +**Fix Bug when Deparsing SQL Server request having TOP and DISTINCT** + +* clauses. SQL Server requires the DISTINCT clause to be the first. + +[7ac70](https://github.com/JSQLParser/JSqlParser/commit/7ac7002d1276f01) LionelNirva *2014-10-03 16:34:49* + +**Update UpdateTest.java** + +* Add an SQL test for Update with Select + +[aec82](https://github.com/JSQLParser/JSqlParser/commit/aec82516c9d0db6) CeeKayGit *2014-10-01 21:34:51* + +**Update UpdateDeParser.java** + + +[f2fec](https://github.com/JSQLParser/JSqlParser/commit/f2fecb7b62f5882) CeeKayGit *2014-10-01 21:18:33* + +**Update UpdateDeParser.java** + + +[e31ac](https://github.com/JSQLParser/JSqlParser/commit/e31ac1ad7090fc2) CeeKayGit *2014-10-01 20:51:26* + +**Update Update.java** + +* Add necessary Select import for Update with Select + +[8321a](https://github.com/JSQLParser/JSqlParser/commit/8321aae44a6adce) CeeKayGit *2014-10-01 20:37:42* + +**Update UpdateDeParser.java** + +* Extend the deparser to support DB2 Updates with Select clause + +[3a7bf](https://github.com/JSQLParser/JSqlParser/commit/3a7bf9d520ead88) CeeKayGit *2014-10-01 20:12:14* + +**Update JSqlParserCC.jj** + +* For DB2 "$" is also a standard letter, so handle "$" as #LETTER. + +[a6383](https://github.com/JSQLParser/JSqlParser/commit/a6383a52ccee448) CeeKayGit *2014-09-30 20:56:13* + +**Update Update.java** + +* Add support for DB2 Updates with Select clause + +[1bdb6](https://github.com/JSQLParser/JSqlParser/commit/1bdb69b8891ee26) CeeKayGit *2014-09-30 20:52:21* + +**Update JSqlParserCC.jj** + +* Add support for DB2 Updates with Select clause + +[17e3d](https://github.com/JSQLParser/JSqlParser/commit/17e3d539a4ce6bd) CeeKayGit *2014-09-30 20:47:54* + +**Update README.md** + + +[23279](https://github.com/JSQLParser/JSqlParser/commit/232795fc575cdf1) Tobias *2014-09-23 20:32:34* + + +## jsqlparser-0.9.1 (2014-09-23) + +### Other changes + +**Update README.md** + + +[267b4](https://github.com/JSQLParser/JSqlParser/commit/267b443e23b95a2) Tobias *2014-09-22 07:25:49* + +**corrected typo** + + +[90c93](https://github.com/JSQLParser/JSqlParser/commit/90c932332a6b8ed) wumpz *2014-09-07 20:28:38* + +**refactored join processor to be more restrictive** + + +[f1544](https://github.com/JSQLParser/JSqlParser/commit/f154446364fd5db) wumpz *2014-09-06 20:24:16* + +**simple execute clause support** + + +[531d6](https://github.com/JSQLParser/JSqlParser/commit/531d6177dfc03d1) wumpz *2014-08-14 21:46:11* + +**simple start for execute** + + +[d6f01](https://github.com/JSQLParser/JSqlParser/commit/d6f0101b9a3d2e4) wumpz *2014-08-13 23:17:08* + +**simple start for execute** + + +[406a1](https://github.com/JSQLParser/JSqlParser/commit/406a138cf3af9f7) wumpz *2014-08-13 23:08:35* + +**updated readme** + + +[1532d](https://github.com/JSQLParser/JSqlParser/commit/1532d15c3dad9ff) wumpz *2014-08-12 14:33:26* + +**correced select into parsing and deparsing** + + +[0b7f3](https://github.com/JSQLParser/JSqlParser/commit/0b7f3007dac51cb) wumpz *2014-08-12 14:29:46* + +**refactored grammar a bit** + + +[096e8](https://github.com/JSQLParser/JSqlParser/commit/096e8742b6fff86) wumpz *2014-08-05 20:58:15* + +**improved insert clause** + + +[a4de6](https://github.com/JSQLParser/JSqlParser/commit/a4de602442a73da) wumpz *2014-08-04 22:09:19* + +**corrected a failing test** + + +[24dc0](https://github.com/JSQLParser/JSqlParser/commit/24dc08db8b9f536) wumpz *2014-07-30 20:47:49* + +**updated readme** + + +[fc0ba](https://github.com/JSQLParser/JSqlParser/commit/fc0ba6a535c3f30) wumpz *2014-07-30 20:43:23* + +**limit 0 and limit null included** + + +[50d3e](https://github.com/JSQLParser/JSqlParser/commit/50d3e8b4224bbaf) wumpz *2014-07-30 20:41:40* + +**Add support for LIMIT 0 and LIMIT NULL statements** + + +[6db00](https://github.com/JSQLParser/JSqlParser/commit/6db009418e925ca) Michaël Cervera *2014-07-29 21:58:29* + +**unlogged inlucded in deparser** + + +[e9939](https://github.com/JSQLParser/JSqlParser/commit/e9939fdfdfca726) wumpz *2014-07-27 21:42:18* + +**Add support for 'UNLOGGED' tables** + +* Support the PostgreSQL 9.1+ ‘UNLOGGED’ table feature + +[eb05c](https://github.com/JSQLParser/JSqlParser/commit/eb05ce30cb90b93) Michaël Cervera *2014-07-27 20:49:00* + +**create table implemented version 2** + + +[98903](https://github.com/JSQLParser/JSqlParser/commit/989033d24e9b3a9) wumpz *2014-07-26 19:56:53* + +**recent changes made more oracle tests succeed** + + +[bbf36](https://github.com/JSQLParser/JSqlParser/commit/bbf360e5620b073) wumpz *2014-07-24 20:04:01* + +**updated readme** + + +[262d4](https://github.com/JSQLParser/JSqlParser/commit/262d48922d66d0f) wumpz *2014-07-24 19:59:25* + +**replaced column list in expression list for partition by of analytic expressions** + + +[2ebaa](https://github.com/JSQLParser/JSqlParser/commit/2ebaaf03602a13b) wumpz *2014-07-24 19:53:17* + +**updated readme** + + +[55e68](https://github.com/JSQLParser/JSqlParser/commit/55e68bfb4f84fa5) wumpz *2014-07-22 20:49:45* + +**implemented create table .. as select ..** + + +[23b93](https://github.com/JSQLParser/JSqlParser/commit/23b938c096eaf67) wumpz *2014-07-22 20:48:00* + +**simple improvements** + + +[5b3ea](https://github.com/JSQLParser/JSqlParser/commit/5b3ea032ff50712) wumpz *2014-07-16 20:27:54* + +**added lookahead for regexp binary** + + +[75aed](https://github.com/JSQLParser/JSqlParser/commit/75aeded181a6f88) Sarah Komla-Ebri *2014-07-16 15:05:30* + +**Added support for MySQL REGEXP BINARY (for case insensitivity)** + + +[ec0dc](https://github.com/JSQLParser/JSqlParser/commit/ec0dc88bc9b4280) Sarah Komla-Ebri *2014-07-16 13:50:37* + +**Added support for MySQL REGEXP insensitivity case** + + +[4d9e4](https://github.com/JSQLParser/JSqlParser/commit/4d9e46198e0a679) Sarah Komla-Ebri *2014-07-16 13:27:25* + +**simple first json syntax** + + +[cb674](https://github.com/JSQLParser/JSqlParser/commit/cb674bfa5937757) wumpz *2014-06-24 21:20:58* + +**simple first json syntax** + + +[45ce9](https://github.com/JSQLParser/JSqlParser/commit/45ce94eb9c0c62a) wumpz *2014-06-24 21:19:04* + +**returning implemented, column as identifier allowed** + + +[0020c](https://github.com/JSQLParser/JSqlParser/commit/0020c798f32c586) wumpz *2014-06-20 23:04:02* + +**returning implemented, column as identifier allowed** + + +[733ff](https://github.com/JSQLParser/JSqlParser/commit/733ff6da5d59ac1) wumpz *2014-06-20 22:58:28* + +**Update README.md** + + +[e12b8](https://github.com/JSQLParser/JSqlParser/commit/e12b8644326d3d2) Tobias *2014-06-04 20:50:35* + +**Update README.md** + + +[e8927](https://github.com/JSQLParser/JSqlParser/commit/e8927d40ab55bdd) Tobias *2014-06-04 20:47:38* + +**Update README.md** + + +[fb8ad](https://github.com/JSQLParser/JSqlParser/commit/fb8add01cb28b85) Tobias *2014-06-04 20:46:03* + +**Update README.md** + + +[08c6a](https://github.com/JSQLParser/JSqlParser/commit/08c6a48b3180db4) Tobias *2014-06-04 20:45:22* + +**fixes #56 : multitable updates** + + +[dfda1](https://github.com/JSQLParser/JSqlParser/commit/dfda1395c4275f6) wumpz *2014-05-25 20:16:31* + +**fixes #56 : multitable updates** + + +[9c183](https://github.com/JSQLParser/JSqlParser/commit/9c183ed34760126) wumpz *2014-05-25 20:06:04* + +**fixes #57: brackets were not handled properly** + + +[00367](https://github.com/JSQLParser/JSqlParser/commit/003674787cfa982) wumpz *2014-05-25 19:10:28* + +**readme updated** + + +[55634](https://github.com/JSQLParser/JSqlParser/commit/5563419fd15e430) wumpz *2014-05-22 22:08:32* + +**junit annotations** + + +[57154](https://github.com/JSQLParser/JSqlParser/commit/57154b37c22abfb) wumpz *2014-05-22 21:05:22* + +**Unit test** + + +[8cc03](https://github.com/JSQLParser/JSqlParser/commit/8cc036b4a99117a) shuyangzhou *2014-05-20 21:52:29* + +**TablesNamesFinder.getTableList(Delete) throws NPE when the sql does not have a where clause** + + +[6d828](https://github.com/JSQLParser/JSqlParser/commit/6d8287fcf9dd1ee) shuyangzhou *2014-05-20 21:52:24* + +**upgrade to JavaCC 6.1.2** + + +[c3404](https://github.com/JSQLParser/JSqlParser/commit/c3404e01e59b8d5) wumpz *2014-05-16 06:49:21* + +**Update README.md** + + +[67af4](https://github.com/JSQLParser/JSqlParser/commit/67af4cd64bf0af0) Tobias *2014-05-08 19:35:00* + + +## jsqlparser-0.9 (2014-05-08) + +### Other changes + +**support for some keywords as objectnames** + + +[60f2b](https://github.com/JSQLParser/JSqlParser/commit/60f2bc4345ad0c8) wumpz *2014-05-07 21:19:09* + +**support for some keywords as objectnames** + + +[c126e](https://github.com/JSQLParser/JSqlParser/commit/c126e1e511d2deb) wumpz *2014-05-07 20:57:32* + +**support for named pks included** + + +[3aabf](https://github.com/JSQLParser/JSqlParser/commit/3aabff2d744315e) wumpz *2014-04-20 23:56:06* + +**support for named pks included** + + +[9e683](https://github.com/JSQLParser/JSqlParser/commit/9e683d3662350ce) wumpz *2014-04-20 23:51:10* + +**util for conditional expression parsing included** + + +[ffeb7](https://github.com/JSQLParser/JSqlParser/commit/ffeb7b7013afaf4) wumpz *2014-04-07 21:29:42* + +**util for conditional expression parsing included** + + +[bc5a6](https://github.com/JSQLParser/JSqlParser/commit/bc5a6a459533b4e) wumpz *2014-04-07 21:21:58* + +**updated readme** + + +[01a82](https://github.com/JSQLParser/JSqlParser/commit/01a82c2e2da9ffb) wumpz *2014-03-23 21:21:41* + +**updated readme** + + +[84979](https://github.com/JSQLParser/JSqlParser/commit/849796360b04aa1) wumpz *2014-03-22 22:43:53* + +**changed configuration** + + +[96be5](https://github.com/JSQLParser/JSqlParser/commit/96be5d779bbf0bb) wumpz *2014-03-22 21:42:11* + +**readme updated** + + +[986c8](https://github.com/JSQLParser/JSqlParser/commit/986c87e1c61f332) wumpz *2014-03-18 21:35:28* + +**removed stachtrace printing for problematic sql scripts** + + +[7ff12](https://github.com/JSQLParser/JSqlParser/commit/7ff12fb4fded358) wumpz *2014-03-18 20:52:15* + +**corrected some sql test scripts to be deparseable** + +* corrected pivot handling in SelectDeParser + +[8ac25](https://github.com/JSQLParser/JSqlParser/commit/8ac250d9f90144d) wumpz *2014-03-12 23:24:47* + +**site descriptor** + + +[a6265](https://github.com/JSQLParser/JSqlParser/commit/a626532c854c35b) wumpz *2014-03-12 19:56:37* + +**pivot test sqls a little tweaked so parseing deparsing will work** + + +[dcd97](https://github.com/JSQLParser/JSqlParser/commit/dcd97c16a007c31) wumpz *2014-03-08 00:00:29* + +**pivot for subquery corrected** + + +[eb480](https://github.com/JSQLParser/JSqlParser/commit/eb480d73dc02c5c) wumpz *2014-03-07 23:48:52* + +**!= usage corrected** + +* deparser for oracle hierarchical expressions corrected +* order by asc/desc corrected + +[d4f74](https://github.com/JSQLParser/JSqlParser/commit/d4f744c761fffe9) wumpz *2014-03-06 22:27:11* + +**ALL processing corrected** + + +[68938](https://github.com/JSQLParser/JSqlParser/commit/68938c79b0394e0) wumpz *2014-03-06 20:46:49* + +**lax tests improved** + + +[ab578](https://github.com/JSQLParser/JSqlParser/commit/ab578af86ca2c26) wumpz *2014-03-05 23:17:40* + +**toString for windowing elements corrected** + +* lax equality test implemented +* included oracle test sqls +* included @ and # for identifiers + +[884dc](https://github.com/JSQLParser/JSqlParser/commit/884dcafa73ecfd2) wumpz *2014-03-05 23:01:03* + +**First version of all *Visitor adapters + simple test** + + +[cdc42](https://github.com/JSQLParser/JSqlParser/commit/cdc42110478506b) aalmiray *2014-03-05 20:45:57* + +**character set implemented** + + +[90048](https://github.com/JSQLParser/JSqlParser/commit/90048e535baa2f0) wumpz *2014-03-01 00:11:04* + +**character set implemented** + + +[e7114](https://github.com/JSQLParser/JSqlParser/commit/e7114e3c53230c6) wumpz *2014-03-01 00:05:59* + +**Update README.md** + + +[2c22b](https://github.com/JSQLParser/JSqlParser/commit/2c22b60433c9a51) Tobias *2014-02-20 22:51:32* + + +## jsqlparser-0.8.9 (2014-02-20) + +### Other changes + +**Update README.md** + + +[d6edd](https://github.com/JSQLParser/JSqlParser/commit/d6eddfd7e5d8a6b) Tobias *2014-02-15 22:11:51* + +**readme** + + +[f82d8](https://github.com/JSQLParser/JSqlParser/commit/f82d8316f00c581) wumpz *2014-02-14 22:01:31* + +**first statements version** + + +[4be27](https://github.com/JSQLParser/JSqlParser/commit/4be2700c2b5e0cd) wumpz *2014-02-14 21:56:27* + +**update readme** + + +[ff94a](https://github.com/JSQLParser/JSqlParser/commit/ff94a3ded2c295c) wumpz *2014-02-11 00:13:16* + +**** + + +[c91d1](https://github.com/JSQLParser/JSqlParser/commit/c91d153020b588c) wumpz *2014-02-11 00:08:31* + +**update readme** + + +[3b219](https://github.com/JSQLParser/JSqlParser/commit/3b21988a4857273) wumpz *2014-02-11 00:01:11* + +**corrected some styling issues** + + +[a3a7f](https://github.com/JSQLParser/JSqlParser/commit/a3a7ff934980b41) wumpz *2014-02-10 23:44:22* + +**backported analytic expressions from fork** + + +[43d97](https://github.com/JSQLParser/JSqlParser/commit/43d97ea79f1e48a) wumpz *2014-02-10 23:36:24* + +**order by clause improved nulls first last** + + +[ce45f](https://github.com/JSQLParser/JSqlParser/commit/ce45fbcf7f2d3e3) wumpz *2014-02-09 23:59:29* + +**added versions to pom** + + +[06bbd](https://github.com/JSQLParser/JSqlParser/commit/06bbda82b813e7b) wumpz *2014-02-08 11:01:56* + +**** + + +[9b2c2](https://github.com/JSQLParser/JSqlParser/commit/9b2c295a8552cf6) wumpz *2014-02-07 22:25:13* + +**Updated most of the Maven dependencies;** + + +[e6aaf](https://github.com/JSQLParser/JSqlParser/commit/e6aaf8b260fadd7) Pap Lőrinc *2014-02-07 07:59:11* + +**Added PERCENT support for the TOP statement;** + + +[5e127](https://github.com/JSQLParser/JSqlParser/commit/5e127196a96ced3) Pap Lőrinc *2014-02-07 07:58:51* + +**Update README.md** + + +[53aab](https://github.com/JSQLParser/JSqlParser/commit/53aab5737c61d1e) Tobias *2014-02-06 21:18:20* + +**readme updated** + + +[96654](https://github.com/JSQLParser/JSqlParser/commit/966541e5b90dbb8) wumpz *2014-02-06 21:14:04* + +**added testcase, little refactoring** + + +[4f766](https://github.com/JSQLParser/JSqlParser/commit/4f76615cf3bbd9b) wumpz *2014-02-06 21:08:18* + +**Modified the TOP expression to accept parentheses also;** + + +[b5849](https://github.com/JSQLParser/JSqlParser/commit/b5849b63d24bef3) Pap Lőrinc *2014-02-06 09:39:31* + +**updated readme** + + +[e143a](https://github.com/JSQLParser/JSqlParser/commit/e143abbd6c6374f) wumpz *2014-02-04 22:57:24* + +**removed Exception logging for false multipart name test** + + +[7a94f](https://github.com/JSQLParser/JSqlParser/commit/7a94fa7b57a085b) wumpz *2014-02-04 22:48:24* + +**** + + +[e1f06](https://github.com/JSQLParser/JSqlParser/commit/e1f06bb0204fe43) wumpz *2014-02-04 22:14:12* + +**included maven site generation** + + +[fc016](https://github.com/JSQLParser/JSqlParser/commit/fc016126850b1ac) wumpz *2014-02-02 23:47:06* + +**extended multipart identifier tests** + + +[a3e0f](https://github.com/JSQLParser/JSqlParser/commit/a3e0f9de56c4441) wumpz *2014-02-02 00:04:28* + +**** + + +[13f3c](https://github.com/JSQLParser/JSqlParser/commit/13f3c0c64f785fb) wumpz *2014-02-01 23:23:43* + +**removed possibility of empty tablename** + + +[9a819](https://github.com/JSQLParser/JSqlParser/commit/9a819eb5ceae1f9) wumpz *2014-02-01 23:17:35* + +**removed some changes** + + +[7fa4f](https://github.com/JSQLParser/JSqlParser/commit/7fa4f8501cc4453) wumpz *2014-02-01 22:55:57* + +**signed expressions tests improved** + + +[a78ab](https://github.com/JSQLParser/JSqlParser/commit/a78ab94cd60353f) wumpz *2014-02-01 22:18:32* + +**Replaced a leftover StringBuffer with StringBuilder;** + + +[9b8d7](https://github.com/JSQLParser/JSqlParser/commit/9b8d72739d464cc) Pap Lőrinc *2014-01-28 17:26:00* + +**Corrected Sql Server multi-part table and column names (database.schema.table.column) in the select statement to accept 4 levels with empty inner parts;** + + +[ba6c5](https://github.com/JSQLParser/JSqlParser/commit/ba6c54de7da2efa) Pap Lőrinc *2014-01-28 17:23:37* + +**Renamed getWholeColumnName and getWholeTableName to getFullyQualifiedName;** + + +[b4d54](https://github.com/JSQLParser/JSqlParser/commit/b4d547eeb04cb9a) Pap Lőrinc *2014-01-28 17:14:09* + +**Corrected the signed expression behaviors and renamed InverseExpression to SignedExpression;** + + +[d1e71](https://github.com/JSQLParser/JSqlParser/commit/d1e7185633bf840) Pap Lőrinc *2014-01-28 08:36:06* + +**Removed the leading and trailing whitespaces in the JavaCC parser file;** + +* Organized the declared imports in order to ease further changes in the file and to remove unused ones; +* Renamed the S_INTEGER token to S_LONG to be in sync with the S_DOUBLE token; + +[5d151](https://github.com/JSQLParser/JSqlParser/commit/5d151c7bdbe08fd) Pap Lőrinc *2014-01-28 08:24:04* + +**fixes #34** + + +[144ca](https://github.com/JSQLParser/JSqlParser/commit/144ca3a140d1024) wumpz *2014-01-23 22:14:58* + +**Update README.md** + + +[7024b](https://github.com/JSQLParser/JSqlParser/commit/7024bc7c1d1f553) Tobias *2014-01-22 23:23:54* + + +## jsqlparser-0.8.8 (2014-01-22) + +### Other changes + +**problem with git v1.8.5 adressed** + + +[9b12d](https://github.com/JSQLParser/JSqlParser/commit/9b12d17a4cb9744) wumpz *2014-01-22 23:05:23* + +**version 0.8.8-SNAPSHOT** + + +[810ca](https://github.com/JSQLParser/JSqlParser/commit/810cabdafe2012a) wumpz *2014-01-22 22:41:41* + +**version 0.8.8-SNAPSHOT** + + +[fdd3a](https://github.com/JSQLParser/JSqlParser/commit/fdd3a71426e473a) wumpz *2014-01-22 22:29:11* + +**Update README.md** + + +[d4083](https://github.com/JSQLParser/JSqlParser/commit/d40837361354a27) Tobias *2014-01-21 23:37:41* + +**addJoin introduced** + + +[c19f8](https://github.com/JSQLParser/JSqlParser/commit/c19f83f768a5e4a) wumpz *2014-01-21 23:35:34* + +**readme updated** + + +[d3675](https://github.com/JSQLParser/JSqlParser/commit/d367559442a98ab) wumpz *2014-01-14 22:29:07* + +**started simple utility function for select statement modification** + + +[bf454](https://github.com/JSQLParser/JSqlParser/commit/bf454e9a261cd4d) wumpz *2014-01-14 22:18:43* + +**started simple utility function for select statement modification** + + +[6b5e2](https://github.com/JSQLParser/JSqlParser/commit/6b5e29af117e04e) wumpz *2014-01-14 22:11:13* + +**update readme** + + +[311d6](https://github.com/JSQLParser/JSqlParser/commit/311d63639bda4a4) wumpz *2014-01-14 21:07:21* + +**little housekeeping** + + +[1c927](https://github.com/JSQLParser/JSqlParser/commit/1c927884749b032) wumpz *2014-01-14 21:01:05* + +**Alias class implemented and integrated** + + +[ce339](https://github.com/JSQLParser/JSqlParser/commit/ce3390677746faf) wumpz *2014-01-14 20:58:03* + +**Added one simple insert SQL to test** + + +[2db02](https://github.com/JSQLParser/JSqlParser/commit/2db02ada400cd99) wumpz *2014-01-11 15:05:50* + +**** + + +[f58ca](https://github.com/JSQLParser/JSqlParser/commit/f58ca061b25ba5b) wumpz *2013-12-08 20:13:04* + +**update readme** + + +[068b1](https://github.com/JSQLParser/JSqlParser/commit/068b19d17d9dba4) wumpz *2013-12-07 23:59:34* + +**start alter statement** + + +[75575](https://github.com/JSQLParser/JSqlParser/commit/7557524708d0ce0) wumpz *2013-12-07 23:57:27* + +**PostgresSQL regular expression match operators** + + +[e5e48](https://github.com/JSQLParser/JSqlParser/commit/e5e488d60c316f3) wumpz *2013-11-12 21:37:43* + +**Update README.md** + + +[259dd](https://github.com/JSQLParser/JSqlParser/commit/259dd566a55a9b6) Tobias *2013-11-08 23:38:09* + +**PostgresSQL regular expression case sensitive match** + + +[db923](https://github.com/JSQLParser/JSqlParser/commit/db923d53c5ceee7) wumpz *2013-11-08 23:33:46* + +**PostgresSQL regular expression case sensitive match** + + +[88b5a](https://github.com/JSQLParser/JSqlParser/commit/88b5aa81b405d45) wumpz *2013-11-08 23:27:30* + +**simple modifier cleanup** + + +[0528e](https://github.com/JSQLParser/JSqlParser/commit/0528ecca9768cf7) wumpz *2013-11-06 21:11:27* + +**Update README.md** + + +[2a4bb](https://github.com/JSQLParser/JSqlParser/commit/2a4bbe5391e4dfd) Tobias *2013-10-30 22:37:09* + +**update readme** + + +[e3b0e](https://github.com/JSQLParser/JSqlParser/commit/e3b0e6c4b5b7e48) wumpz *2013-10-30 22:31:03* + + +## jsqlparser-0.8.6 (2013-10-30) + +### Other changes + +**a little cleanup** + + +[bdc81](https://github.com/JSQLParser/JSqlParser/commit/bdc81933ab76b01) wumpz *2013-10-24 21:46:52* + +**version not needed anymore** + + +[7a737](https://github.com/JSQLParser/JSqlParser/commit/7a737e70a76616d) wumpz *2013-10-24 21:34:14* + +**Update README.md** + + +[f14e3](https://github.com/JSQLParser/JSqlParser/commit/f14e3c98917bc24) Tobias *2013-10-08 22:42:11* + +**Update README.md** + + +[22c3e](https://github.com/JSQLParser/JSqlParser/commit/22c3ee9379b4f7c) Tobias *2013-10-08 22:37:23* + +**update readme.md** + + +[d2dcf](https://github.com/JSQLParser/JSqlParser/commit/d2dcfaece51ceda) wumpz *2013-10-08 22:35:21* + +**merge oracle hierarchical syntax into main** + + +[a0b21](https://github.com/JSQLParser/JSqlParser/commit/a0b21c36e5d2008) wumpz *2013-10-08 22:23:30* + +**merge oracle hierarchical syntax into main** + + +[6c300](https://github.com/JSQLParser/JSqlParser/commit/6c30062bd7e9a59) wumpz *2013-10-08 22:22:19* + +**OracleHierarchicalExpression implemented** + + +[b48f2](https://github.com/JSQLParser/JSqlParser/commit/b48f26e48a00f03) wumpz *2013-10-08 22:07:03* + +**OracleHierarchicalExpression implemented** + + +[afa6e](https://github.com/JSQLParser/JSqlParser/commit/afa6e2d73d237f0) wumpz *2013-10-08 00:15:32* + +**Update README.md** + + +[3901b](https://github.com/JSQLParser/JSqlParser/commit/3901bc6bf380099) Tobias *2013-10-07 12:09:23* + +**Update README.md** + + +[9eb5f](https://github.com/JSQLParser/JSqlParser/commit/9eb5fa11dad1733) Tobias *2013-10-06 14:12:55* + +**parser updated oracle recursives** + + +[aff53](https://github.com/JSQLParser/JSqlParser/commit/aff53603149d42c) wumpz *2013-10-01 19:07:16* + +**begin implementation of oracle recursive queries** + + +[a7566](https://github.com/JSQLParser/JSqlParser/commit/a7566a7371bdca0) wumpz *2013-09-19 20:33:18* + + +## jsqlparser-0.8.5 (2013-10-06) + +### Other changes + +**preparing release of 0.8.5** + + +[7abce](https://github.com/JSQLParser/JSqlParser/commit/7abce433ce56bab) wumpz *2013-10-06 13:23:53* + +**preparing release of 0.8.5** + + +[0e13b](https://github.com/JSQLParser/JSqlParser/commit/0e13b77a827dfb5) wumpz *2013-10-06 12:55:48* + +**readme updated** + + +[3e68f](https://github.com/JSQLParser/JSqlParser/commit/3e68fa4928d5115) wumpz *2013-09-19 21:08:23* + +**problems solved with postgresqls data type "character varying"** + + +[c84e5](https://github.com/JSQLParser/JSqlParser/commit/c84e59eadd380e0) wumpz *2013-09-19 21:05:18* + +**problems solved with postgresqls data type "character varying"** + + +[f5af3](https://github.com/JSQLParser/JSqlParser/commit/f5af3053102af19) wumpz *2013-09-19 21:00:19* + +**corrected version infos** + + +[9da72](https://github.com/JSQLParser/JSqlParser/commit/9da728241feb44b) wumpz *2013-09-17 21:49:19* + +**Update README.md** + + +[da809](https://github.com/JSQLParser/JSqlParser/commit/da809493f5d6dbb) Tobias *2013-09-17 21:36:47* + +**first snapshot deployed to sonatype** + + +[62970](https://github.com/JSQLParser/JSqlParser/commit/629705cc0a3d758) wumpz *2013-09-17 21:27:05* + +**pom modification to publish to public repository** + + +[e60bc](https://github.com/JSQLParser/JSqlParser/commit/e60bc0e9fac79ee) wumpz *2013-09-17 12:14:43* + +**pom modification to publish to public repository** + + +[085d4](https://github.com/JSQLParser/JSqlParser/commit/085d4970d2a56c8) wumpz *2013-09-17 09:11:36* + +**CastExpression favours cast keyword instead of ::** + + +[68d12](https://github.com/JSQLParser/JSqlParser/commit/68d12944d835777) wumpz *2013-09-17 07:17:39* + +**CastExpression favours cast keyword instead of ::** + + +[8cf8b](https://github.com/JSQLParser/JSqlParser/commit/8cf8b4b7733dbd4) wumpz *2013-09-17 07:16:27* + +**removed unused modifiers** + + +[b3ee7](https://github.com/JSQLParser/JSqlParser/commit/b3ee75103cba4ec) wumpz *2013-08-29 20:22:48* + +**improved function test** + + +[35608](https://github.com/JSQLParser/JSqlParser/commit/35608babd2caae1) wumpz *2013-08-29 19:32:20* + +**workaround for mySql truncate function** + + +[c3b40](https://github.com/JSQLParser/JSqlParser/commit/c3b4046f8833357) wumpz *2013-08-29 19:22:57* + + +## jsqlparser-0.8.4 (2013-08-27) + +### Other changes + +**JJDoc output included in site configuration** + + +[b2688](https://github.com/JSQLParser/JSqlParser/commit/b2688799ada5918) wumpz *2013-08-25 19:30:45* + +**Update README.md** + + +[891dd](https://github.com/JSQLParser/JSqlParser/commit/891dd0a8e7e3086) Tobias *2013-08-22 20:29:48* + +**update readme** + + +[d375a](https://github.com/JSQLParser/JSqlParser/commit/d375ac9a51bc51e) wumpz *2013-08-22 20:20:29* + +**update readme** + + +[e25d0](https://github.com/JSQLParser/JSqlParser/commit/e25d0be44a8223a) wumpz *2013-08-22 20:13:19* + +**some minor additions to named parameters** + + +[8bff2](https://github.com/JSQLParser/JSqlParser/commit/8bff2c911467e84) wumpz *2013-08-22 20:11:19* + +**added ability to parse named parameters** + + +[284ec](https://github.com/JSQLParser/JSqlParser/commit/284ec72cd00a574) audrium *2013-08-22 13:47:39* + +**added changes to readme** + + +[6ab75](https://github.com/JSQLParser/JSqlParser/commit/6ab75599642eb23) wumpz *2013-08-14 21:34:21* + +**added some test cases** + + +[00f76](https://github.com/JSQLParser/JSqlParser/commit/00f76fe1a853843) wumpz *2013-08-14 21:25:47* + +**removed PivotForColumn** + + +[18904](https://github.com/JSQLParser/JSqlParser/commit/18904dd44c915d2) wumpz *2013-08-11 23:43:07* + +**regexp_like transfered into a general boolean function** + + +[410a2](https://github.com/JSQLParser/JSqlParser/commit/410a2d125db963e) wumpz *2013-08-11 21:26:33* + +**Add support old oracle join syntax to more expressions (simple comparisons and IN)** + + +[55f42](https://github.com/JSQLParser/JSqlParser/commit/55f42ea3712cf4d) Jonathan Burnhams *2013-08-02 07:52:05* + +**Add support for lag and lead with offset and default value parameters** + + +[99b46](https://github.com/JSQLParser/JSqlParser/commit/99b46bf1e7b18ec) Jonathan Burnhams *2013-08-01 14:00:15* + +**Added regexp_like support** + + +[33f4f](https://github.com/JSQLParser/JSqlParser/commit/33f4f66dbdd693d) Jonathan Burnhams *2013-08-01 13:26:05* + +**Finished adding pivot support** + + +[43fe8](https://github.com/JSQLParser/JSqlParser/commit/43fe8ca9c71afff) Jonathan Burnhams *2013-08-01 08:56:50* + +**Started to add pivot support** + + +[a9716](https://github.com/JSQLParser/JSqlParser/commit/a97160a801585fa) Jonathan Burnhams *2013-07-31 15:15:42* + +**Ignore intellij** + + +[51783](https://github.com/JSQLParser/JSqlParser/commit/517839aa4734e24) Jonathan Burnhams *2013-07-31 13:25:20* + +**Update README.md** + + +[3a8ea](https://github.com/JSQLParser/JSqlParser/commit/3a8eacabad85274) Tobias *2013-07-18 13:06:09* + +**removed release plugin dryrun** + + +[6e45a](https://github.com/JSQLParser/JSqlParser/commit/6e45a4fb22fe72a) wumpz *2013-07-05 20:55:50* + +**Update README.md** + + +[b53e7](https://github.com/JSQLParser/JSqlParser/commit/b53e74d3b50c5d5) Tobias *2013-07-05 05:58:12* + +**maven release plugin for local git repository** + + +[bd05e](https://github.com/JSQLParser/JSqlParser/commit/bd05eab93f7303b) wumpz *2013-07-04 19:54:39* + +**more sonar issues corrected** + + +[7fea9](https://github.com/JSQLParser/JSqlParser/commit/7fea946f0ea664e) wumpz *2013-07-04 19:23:29* + +**Update README.md** + + +[79f32](https://github.com/JSQLParser/JSqlParser/commit/79f322aca2246bc) Tobias *2013-07-04 19:04:02* + +**create table can now have foreign key definitions** + +* fixes #14 + +[0c41f](https://github.com/JSQLParser/JSqlParser/commit/0c41f27165a2f41) wumpz *2013-06-24 23:28:29* + +**removed some unused imports** + + +[8c37c](https://github.com/JSQLParser/JSqlParser/commit/8c37ca2628188ac) wumpz *2013-06-20 21:59:24* + +**more sonar identified stuff cleaned** + + +[51791](https://github.com/JSQLParser/JSqlParser/commit/5179164dc6d54b5) wumpz *2013-06-20 21:12:48* + +**cleanup violations found by sonar** + + +[51d0b](https://github.com/JSQLParser/JSqlParser/commit/51d0ba3b1eec349) Ivan Vasyliev *2013-06-14 14:44:01* + +**more sonar identified stuff cleaned** + + +[c84ed](https://github.com/JSQLParser/JSqlParser/commit/c84ed36f9555aa0) wumpz *2013-06-13 20:53:57* + +**corrected Method names mentioned by Sonar** + + +[16e2d](https://github.com/JSQLParser/JSqlParser/commit/16e2d8dd4a3e7ac) wumpz *2013-06-13 20:46:02* + +**cleaned up more critical points (sonar)** + + +[ad96c](https://github.com/JSQLParser/JSqlParser/commit/ad96cbb9c65e39f) wumpz *2013-06-13 20:42:40* + +**solved critical "Performance - Method concatenates strings using + in a loop"** + + +[9b86e](https://github.com/JSQLParser/JSqlParser/commit/9b86e368e4b3b67) wumpz *2013-06-09 23:40:10* + +**Update README.md** + + +[5c36d](https://github.com/JSQLParser/JSqlParser/commit/5c36da78eb4cc3d) Tobias *2013-06-08 22:14:15* + +**Update README.md** + + +[cdbec](https://github.com/JSQLParser/JSqlParser/commit/cdbec9bc2194147) Tobias *2013-06-08 21:55:29* + +**fixes #30** + + +[22f83](https://github.com/JSQLParser/JSqlParser/commit/22f839045489e20) wumpz *2013-05-30 20:11:44* + +**** + + +[4ebb5](https://github.com/JSQLParser/JSqlParser/commit/4ebb568f83de703) wumpz *2013-05-26 22:47:27* + +**added readme entry** + + +[afc0e](https://github.com/JSQLParser/JSqlParser/commit/afc0e2957c5c52c) wumpz *2013-05-26 22:21:36* + +**multi value IN expression introduced (a,b,c) in ...** + +* fixes #30 + +[3c443](https://github.com/JSQLParser/JSqlParser/commit/3c44391bf5f168f) wumpz *2013-05-26 22:19:03* + +**introduces Interval expression** + + +[fc5e6](https://github.com/JSQLParser/JSqlParser/commit/fc5e6050533e34d) wumpz *2013-05-26 20:44:44* + +**new version** + + +[f97c5](https://github.com/JSQLParser/JSqlParser/commit/f97c5a27faecc7b) wumpz *2013-05-23 22:03:06* + +**new version** + + +[a470a](https://github.com/JSQLParser/JSqlParser/commit/a470ae965d06ab4) wumpz *2013-05-22 19:57:51* + +**release** + + +[1366c](https://github.com/JSQLParser/JSqlParser/commit/1366caba4b4d087) wumpz *2013-05-22 19:57:21* + +**readme** + + +[4a620](https://github.com/JSQLParser/JSqlParser/commit/4a620031bcbef1e) wumpz *2013-05-22 19:49:11* + +**introduced generic list** + + +[8af04](https://github.com/JSQLParser/JSqlParser/commit/8af04647982fc78) wumpz *2013-05-22 19:38:36* + +**refactored some test utility methods out into a new class** + + +[c6bc4](https://github.com/JSQLParser/JSqlParser/commit/c6bc4c3ae5fad83) wumpz *2013-05-22 19:33:05* + +**improved test** + + +[5e106](https://github.com/JSQLParser/JSqlParser/commit/5e1069523441f0f) wumpz *2013-05-22 19:16:18* + +**- corrected S_DOUBLE parsing** + + +[6e3dc](https://github.com/JSQLParser/JSqlParser/commit/6e3dce2af7f2edd) wumpz *2013-05-16 22:22:01* + +**- solved critical grammar bug regarding concat expressions and parenthesis parsing** + +* - introduced some tests to cover the above +* - corrected ExpressionDeparser to deliver same result as toString for substractions + +[51365](https://github.com/JSQLParser/JSqlParser/commit/51365239ead790b) wumpz *2013-05-16 21:53:04* + +**added simple delete sql check** + + +[45fad](https://github.com/JSQLParser/JSqlParser/commit/45fad04b620704c) wumpz *2013-05-03 20:36:31* + +**add simple materialized view parsing without additional parameters** + + +[6b339](https://github.com/JSQLParser/JSqlParser/commit/6b339fc1e6478cc) wumpz *2013-04-24 20:48:16* + +**add simple materialized view parsing without additional parameters** + + +[fa5da](https://github.com/JSQLParser/JSqlParser/commit/fa5daaa3cd8430b) wumpz *2013-04-24 20:45:22* + +**Update README.md** + + +[1d923](https://github.com/JSQLParser/JSqlParser/commit/1d92374962fc745) Tobias *2013-04-24 06:03:14* + +**** + + +[a6615](https://github.com/JSQLParser/JSqlParser/commit/a661593121f07ac) wumpz *2013-04-23 21:14:24* + +**- corrected TableNamesFinder to work properly on update statements** + + +[eab74](https://github.com/JSQLParser/JSqlParser/commit/eab747b7891cbd8) wumpz *2013-04-23 21:07:32* + +**- Create View corrected in using set operations** + + +[97c03](https://github.com/JSQLParser/JSqlParser/commit/97c03337c1a2deb) wumpz *2013-04-23 20:42:51* + +**- from clause can now be used in update statements** + + +[b24c1](https://github.com/JSQLParser/JSqlParser/commit/b24c1c727cd1f81) wumpz *2013-04-21 21:34:26* + +**- from clause can now be used in update statements** + + +[b5c4c](https://github.com/JSQLParser/JSqlParser/commit/b5c4ce66d751579) wumpz *2013-04-21 21:31:30* + +**- insertet toString in Update** + +* - modified Update deparser to deliver better results + +[e2e4d](https://github.com/JSQLParser/JSqlParser/commit/e2e4d80675d525d) wumpz *2013-04-21 21:18:48* + +**added cross join syntax support** + + +[777a0](https://github.com/JSQLParser/JSqlParser/commit/777a08b2afeb495) wumpz *2013-04-18 22:28:32* + +**allow more complex expressions in extract clause** + + +[e551a](https://github.com/JSQLParser/JSqlParser/commit/e551a1603b1e2e6) wumpz *2013-04-18 21:49:45* + +**allow more complex expressions in extract clause** + + +[ab2ab](https://github.com/JSQLParser/JSqlParser/commit/ab2ab73f08d4fc8) wumpz *2013-04-18 21:46:29* + +**allow complete type in cast expression** + + +[8562d](https://github.com/JSQLParser/JSqlParser/commit/8562d7870a1c8c7) wumpz *2013-04-18 20:47:12* + +**allow complete type in cast expression** + + +[905a6](https://github.com/JSQLParser/JSqlParser/commit/905a62377b3bedd) wumpz *2013-04-18 20:40:49* + +**create view .. as (select ..) implemented** + + +[1b3c5](https://github.com/JSQLParser/JSqlParser/commit/1b3c507c922dd3a) wumpz *2013-04-18 20:23:19* + +**corrected comma list to partition by** + + +[d82c7](https://github.com/JSQLParser/JSqlParser/commit/d82c7a189f1b579) wumpz *2013-04-18 20:01:55* + +**corrected comma list to partition by** + + +[eafea](https://github.com/JSQLParser/JSqlParser/commit/eafea98e54e9b2e) wumpz *2013-04-18 19:59:20* + +**corrected comma list to partition by** + + +[5d40d](https://github.com/JSQLParser/JSqlParser/commit/5d40d7f384935ee) wumpz *2013-04-18 19:55:03* + +**added column names list to create view statement** + + +[b3a63](https://github.com/JSQLParser/JSqlParser/commit/b3a6354b5248884) wumpz *2013-04-17 22:15:38* + +**added column names list to create view statement** + + +[b7e73](https://github.com/JSQLParser/JSqlParser/commit/b7e738a071c28d8) wumpz *2013-04-17 22:11:15* + +**added more testcases** + + +[eae84](https://github.com/JSQLParser/JSqlParser/commit/eae84f640ba9619) wumpz *2013-04-07 21:08:13* + +**Update README.md** + + +[f2765](https://github.com/JSQLParser/JSqlParser/commit/f27659d74fad122) Tobias *2013-04-05 19:34:33* + +**support listing tables from other operations** + + +[1d09b](https://github.com/JSQLParser/JSqlParser/commit/1d09b0cd2a68fc5) Raymond Auge *2013-04-05 15:39:59* + +**support for create index** + + +[dca7d](https://github.com/JSQLParser/JSqlParser/commit/dca7d9be7a6d63f) Raymond Auge *2013-04-05 13:54:56* + +**added more tool functions to new tool class CCJSqlParserUtil** + + +[83a1e](https://github.com/JSQLParser/JSqlParser/commit/83a1e9590471581) wumpz *2013-03-23 22:31:09* + +**added more tool functions to new tool class CCJSqlParserUtil** + + +[90341](https://github.com/JSQLParser/JSqlParser/commit/90341f89642659e) wumpz *2013-03-23 22:28:35* + +**added more tool functions to new tool class CCJSqlParserUtil** + + +[56fe6](https://github.com/JSQLParser/JSqlParser/commit/56fe6558e978d8f) wumpz *2013-03-23 22:27:32* + +**added more tool functions** + + +[71daa](https://github.com/JSQLParser/JSqlParser/commit/71daa4ceee100c0) wumpz *2013-03-23 22:20:20* + +**switch to unicode parsing** + + +[886b7](https://github.com/JSQLParser/JSqlParser/commit/886b72c16d95a5a) wumpz *2013-03-21 22:58:37* + +**ignoring jedit backup files** + + +[da1e3](https://github.com/JSQLParser/JSqlParser/commit/da1e319210c431b) Tobias Warneke *2013-03-20 20:33:35* + +**Added automatic license header generation. The link to the original project was moved to the poms description.** + +* Format of all sources done. + +[01f7a](https://github.com/JSQLParser/JSqlParser/commit/01f7a4c92670794) wumpz *2013-03-19 21:30:50* + +**automatically create license header** + + +[8206d](https://github.com/JSQLParser/JSqlParser/commit/8206dea9caf33f9) wumpz *2013-03-19 21:05:27* + +**** + + +[26e3a](https://github.com/JSQLParser/JSqlParser/commit/26e3a8334563108) wumpz *2013-03-19 20:50:59* + +**** + + +[f37b7](https://github.com/JSQLParser/JSqlParser/commit/f37b7285295ec0a) wumpz *2013-03-19 20:38:04* + +**wildcard extension for analytic expression** + + +[d36fd](https://github.com/JSQLParser/JSqlParser/commit/d36fd2bd7f17dba) wumpz *2013-03-19 20:18:46* + +**readme updated** + + +[27be9](https://github.com/JSQLParser/JSqlParser/commit/27be9c57d64a2d3) wumpz *2013-03-19 00:16:05* + +**analytic expressions updated** + + +[9d62c](https://github.com/JSQLParser/JSqlParser/commit/9d62c21b2553b9c) wumpz *2013-03-19 00:12:06* + +**- additional test case for values** + +* - additional test cases for analytical expressions + +[15fc8](https://github.com/JSQLParser/JSqlParser/commit/15fc834bf78ae91) wumpz *2013-03-18 23:59:07* + +**Update README.md** + + +[d7f9f](https://github.com/JSQLParser/JSqlParser/commit/d7f9f39ab2b5e3c) Tobias *2013-03-17 00:32:02* + +**additional test case** + + +[e7dc8](https://github.com/JSQLParser/JSqlParser/commit/e7dc8d0cb5bb192) wumpz *2013-03-17 00:26:21* + +**multi value expression for select included** + + +[6b51f](https://github.com/JSQLParser/JSqlParser/commit/6b51f26b6025532) wumpz *2013-03-17 00:21:17* + +**Update README.md** + + +[15a8d](https://github.com/JSQLParser/JSqlParser/commit/15a8d0dd8053881) Tobias *2013-03-14 21:43:12* + +**multi value expression for insert included** + + +[898f3](https://github.com/JSQLParser/JSqlParser/commit/898f36937a9ad05) wumpz *2013-03-14 21:40:42* + +**multi value expression for insert included** + + +[8f21c](https://github.com/JSQLParser/JSqlParser/commit/8f21c6608eacd56) wumpz *2013-03-14 21:36:44* + +**corrected InsertDeParser to deliver same results like toString** + + +[95527](https://github.com/JSQLParser/JSqlParser/commit/955274b969983f6) wumpz *2013-03-12 22:15:07* + +**test for lateral and TableNamesFinder** + + +[a3ec5](https://github.com/JSQLParser/JSqlParser/commit/a3ec55aa297eade) wumpz *2013-03-03 00:46:19* + +**corrected readme** + + +[966d8](https://github.com/JSQLParser/JSqlParser/commit/966d8a7747becd1) wumpz *2013-02-27 23:27:02* + +**corrected readme** + + +[20275](https://github.com/JSQLParser/JSqlParser/commit/202756d18453b25) wumpz *2013-02-27 23:13:22* + +**** + + +[3d72a](https://github.com/JSQLParser/JSqlParser/commit/3d72a4f45f7cdad) wumpz *2013-02-27 23:08:50* + +**implemented lateral keyword** + + +[5bc39](https://github.com/JSQLParser/JSqlParser/commit/5bc39d3aaa74c24) wumpz *2013-02-27 23:05:01* + +**add WithItem to visitor interface** + + +[10e8f](https://github.com/JSQLParser/JSqlParser/commit/10e8f7ffd9a3b07) wumpz *2013-02-20 23:06:07* + +**some clean up** + + +[00799](https://github.com/JSQLParser/JSqlParser/commit/00799709a45f68c) wumpz *2013-02-20 22:47:14* + +**** + + +[35a17](https://github.com/JSQLParser/JSqlParser/commit/35a17b5a0190992) wumpz *2013-02-16 14:01:45* + +**0.8.2-SNAPSHOT** + + +[e8ed7](https://github.com/JSQLParser/JSqlParser/commit/e8ed7c70fac2cd3) wumpz *2013-02-15 22:42:47* + +**Release 0.8.1 to include in my maven repo** + + +[e41b3](https://github.com/JSQLParser/JSqlParser/commit/e41b333a4635c61) wumpz *2013-02-15 22:41:44* + +**- problem with TablesNamesFinder: finds with - alias instead of tablenames** + + +[08236](https://github.com/JSQLParser/JSqlParser/commit/082362b174d3faf) wumpz *2013-02-15 22:41:07* + +**- problem with TablesNamesFinder: finds with - alias instead of tablenames** + + +[43699](https://github.com/JSQLParser/JSqlParser/commit/436992983926da2) wumpz *2013-02-15 22:14:13* + +**Update README.md** + + +[c438f](https://github.com/JSQLParser/JSqlParser/commit/c438fdd520ede8e) Tobias *2013-02-14 07:45:00* + +**Update README.md** + + +[7beeb](https://github.com/JSQLParser/JSqlParser/commit/7beebabfe7eba67) Tobias *2013-02-14 00:11:32* + +**deployment to github maven repository** + + +[d9fe3](https://github.com/JSQLParser/JSqlParser/commit/d9fe37ad578a0e2) wumpz *2013-02-14 00:04:46* + +**Update README.md** + + +[5f306](https://github.com/JSQLParser/JSqlParser/commit/5f306a889b11754) Tobias *2013-01-04 09:39:02* + +**CreateView merged in** + + +[0ba65](https://github.com/JSQLParser/JSqlParser/commit/0ba65276f0a67e0) wumpz *2013-01-04 09:32:08* + +**CreateView merged in** + + +[b2eff](https://github.com/JSQLParser/JSqlParser/commit/b2eff8b0e0e7976) wumpz *2013-01-04 09:31:12* + +**Add CREATE VIEW support** + + +[101ef](https://github.com/JSQLParser/JSqlParser/commit/101ef1d9e10e7d2) Jeffrey Gerard *2012-12-26 17:52:30* + +**some housekeeping: replace string concats** + + +[db49b](https://github.com/JSQLParser/JSqlParser/commit/db49b43c2d7bace) wumpz *2012-11-15 22:38:04* + +**some housekeeping: adding missing braces** + + +[5dabd](https://github.com/JSQLParser/JSqlParser/commit/5dabda1deca055a) wumpz *2012-11-15 22:33:05* + +**some housekeeping: adding override annotations** + + +[5302b](https://github.com/JSQLParser/JSqlParser/commit/5302b4562af8bd0) wumpz *2012-11-15 22:21:05* + +**changed source encoding to utf8 from win-1252** + + +[af7fc](https://github.com/JSQLParser/JSqlParser/commit/af7fc5c63a08f96) wumpz *2012-10-31 23:38:33* + +**additional letters token rule included, to expand range of acceptable identifiers** + + +[86423](https://github.com/JSQLParser/JSqlParser/commit/86423b0ea8e9875) wumpz *2012-10-31 22:40:42* + +**additional letters token rule included, to expand range of acceptable identifiers** + + +[aa8e1](https://github.com/JSQLParser/JSqlParser/commit/aa8e15a1923c0a1) wumpz *2012-10-31 19:16:02* + +**Update README.md** + + +[50a56](https://github.com/JSQLParser/JSqlParser/commit/50a56b02c70dac2) Tobias *2012-10-27 22:42:10* + +**initial import** + + +[be85e](https://github.com/JSQLParser/JSqlParser/commit/be85e2dd312821a) wumpz *2012-10-27 22:23:51* + +**initial import** + + +[3331f](https://github.com/JSQLParser/JSqlParser/commit/3331fc415a20832) wumpz *2012-10-27 22:21:08* + +**initial import** + + +[52ffc](https://github.com/JSQLParser/JSqlParser/commit/52ffcf6d42d673c) wumpz *2012-10-27 22:17:53* + +**- introduced more generics in parser definition** + + +[4a89f](https://github.com/JSQLParser/JSqlParser/commit/4a89f9b93e3d4ff) wumpz *2012-10-26 22:23:16* + +**- introduced more generics in parser definition** + + +[b0e4a](https://github.com/JSQLParser/JSqlParser/commit/b0e4a4712432492) wumpz *2012-10-26 22:16:59* + +**- introduced more generics in parser definition** + + +[07317](https://github.com/JSQLParser/JSqlParser/commit/07317edca9c8f89) wumpz *2012-10-26 22:13:12* + +**- introduced more generics in parser definition** + + +[fde24](https://github.com/JSQLParser/JSqlParser/commit/fde24683e0c9930) wumpz *2012-10-12 20:55:17* + +**- clean up merge conflicts** + + +[e838d](https://github.com/JSQLParser/JSqlParser/commit/e838d9778060478) wumpz *2012-10-12 20:13:43* + +**- clean up merge conflicts** + + +[bf5d1](https://github.com/JSQLParser/JSqlParser/commit/bf5d17f1594c7ca) wumpz *2012-10-12 20:11:30* + +**Added SELECT parsing and JUnit test** + + +[e9766](https://github.com/JSQLParser/JSqlParser/commit/e9766966ccd7809) Christian Bockermann *2012-10-01 09:21:38* + +**- corrected changelog** + + +[1047b](https://github.com/JSQLParser/JSqlParser/commit/1047bb1877cc1ac) wumpz *2012-09-16 21:14:25* + +**- difference problem between deparser and tostring for function without parameters resolved** + + +[aee0f](https://github.com/JSQLParser/JSqlParser/commit/aee0fa79d5eb085) wumpz *2012-09-16 21:13:08* + +**- difference problem between deparser and tostring for function without parameters resolved** + + +[90f48](https://github.com/JSQLParser/JSqlParser/commit/90f48ff7b87767a) wumpz *2012-09-16 21:11:10* + +**- ExtractExpression integrated** + +* - Tests ExtractExpression started +* - Function problem found + +[7ea63](https://github.com/JSQLParser/JSqlParser/commit/7ea63d17c1ef299) wumpz *2012-09-16 21:01:53* + +**- extract syntax integrated into jj file** + + +[7a50b](https://github.com/JSQLParser/JSqlParser/commit/7a50b960e974183) wumpz *2012-09-15 21:26:39* + +**- expansion warnings removed by introducing lookaheads** + + +[db904](https://github.com/JSQLParser/JSqlParser/commit/db90438f3daab6f) wumpz *2012-09-15 21:04:18* + +**** + + +[3da19](https://github.com/JSQLParser/JSqlParser/commit/3da190b0b31a30d) wumpz *2012-09-11 19:33:24* + +**** + + +[ab60c](https://github.com/JSQLParser/JSqlParser/commit/ab60cfe02940fb8) wumpz *2012-09-08 20:58:20* + +**- moved tables names finder to utils package of source package. it is a too useful tool to live only in the test packages** + + +[57025](https://github.com/JSQLParser/JSqlParser/commit/5702587ce4abae9) wumpz *2012-09-08 19:59:35* + +**- moved tables names finder to utils package of source package. it is a too useful tool to live only in the test packages** + + +[4d33d](https://github.com/JSQLParser/JSqlParser/commit/4d33ded5322ca3b) wumpz *2012-09-08 19:57:25* + +**- Tool expression connector included** + + +[bb726](https://github.com/JSQLParser/JSqlParser/commit/bb726681905a11b) wumpz *2012-09-08 19:46:28* + +**- Tool alias adder implemented** + + +[2ee7a](https://github.com/JSQLParser/JSqlParser/commit/2ee7aa9688f8775) wumpz *2012-09-03 23:32:15* + +**imports corrected** + + +[147e8](https://github.com/JSQLParser/JSqlParser/commit/147e8b70ef75e81) wumpz *2012-09-01 22:05:02* + +**Fix some obvious compiler warnings** + + +[ea7a1](https://github.com/JSQLParser/JSqlParser/commit/ea7a174bf86f0bf) Ian Bacher *2012-06-13 20:35:48* + +**** + + +[99b92](https://github.com/JSQLParser/JSqlParser/commit/99b92b3e4e57860) wumpz *2012-06-12 21:49:05* + +**quoted columns in create table statement included** + +* CreateTableDeParser corrected (NPE with no indexes, toString delivers now same) +* CreateTableTest expanded + +[69287](https://github.com/JSQLParser/JSqlParser/commit/69287d7b2e8b278) wumpz *2012-05-26 19:58:14* + +**complex with tests included** + +* exists formatting included from fork + +[7e39e](https://github.com/JSQLParser/JSqlParser/commit/7e39e9ec4f48448) wumpz *2012-05-23 19:57:10* + +**changed version number due to visitor incombatibilities** + + +[87315](https://github.com/JSQLParser/JSqlParser/commit/87315094501ffbc) wumpz *2012-05-23 19:08:39* + +**** + + +[877ea](https://github.com/JSQLParser/JSqlParser/commit/877ea2c6783bf79) wumpz *2012-05-19 23:04:42* + +**- removed deprecated union class (replaced by SetOperationList)** + + +[bce12](https://github.com/JSQLParser/JSqlParser/commit/bce1290bea487cf) wumpz *2012-05-19 22:09:03* + +**set operation handling done** + + +[673eb](https://github.com/JSQLParser/JSqlParser/commit/673eb25f97c04d8) wumpz *2012-05-19 21:42:21* + +**start implementing union intersection etc. set operation handling** + + +[e980b](https://github.com/JSQLParser/JSqlParser/commit/e980bf3ac12a6b3) wumpz *2012-05-18 21:17:50* + +**** + + +[37ecf](https://github.com/JSQLParser/JSqlParser/commit/37ecf0a5a7e26ab) wumpz *2012-05-18 20:11:59* + +**- Added Oracle (+) join Syntax (instead of taba left join tabn on a=b oracle allows taba,tabn where a=b(+) )** + + +[31e94](https://github.com/JSQLParser/JSqlParser/commit/31e9435776bebaa) wumpz *2012-05-18 20:10:14* + +**- Analytic functions added: corrected PARTITION BY** + + +[4f2cb](https://github.com/JSQLParser/JSqlParser/commit/4f2cbb3eff61683) wumpz *2012-05-17 13:44:50* + +**- Analytic functions added: row_number() over (order by a,c)** + + +[b8543](https://github.com/JSQLParser/JSqlParser/commit/b8543ac725fe773) wumpz *2012-05-17 12:46:52* + +**Added support for modulo expression (5 % 4)** + + +[ae513](https://github.com/JSQLParser/JSqlParser/commit/ae51331f7c82d04) wumpz *2012-05-17 12:19:50* + +**Added support for modulo expression (5 % 4)** + + +[4ef84](https://github.com/JSQLParser/JSqlParser/commit/4ef842925b27438) wumpz *2012-05-16 21:30:14* + +**Include bracket quotation of columns and aliases. For example MSAccess supports this.** + + +[e6d5a](https://github.com/JSQLParser/JSqlParser/commit/e6d5accd0db8e1f) wumpz *2012-05-16 20:33:44* + +**** + + +[d6a22](https://github.com/JSQLParser/JSqlParser/commit/d6a22d1076b95f0) wumpz *2012-05-15 21:50:56* + +**- allowed simple expressions in case else** + + +[54d2c](https://github.com/JSQLParser/JSqlParser/commit/54d2c54658d1644) wumpz *2012-05-15 21:36:59* + +**- make "select function" pass assertSqlCanBeParsedAndDeparsed** + + +[21296](https://github.com/JSQLParser/JSqlParser/commit/21296032a0ef7db) wumpz *2012-05-15 21:00:51* + +**- make "select function" pass assertSqlCanBeParsedAndDeparsed** + + +[f769e](https://github.com/JSQLParser/JSqlParser/commit/f769ef2e562f485) wumpz *2012-05-15 20:57:07* + +**- make "select function" pass assertSqlCanBeParsedAndDeparsed** + + +[e5853](https://github.com/JSQLParser/JSqlParser/commit/e5853695b96ac0f) wumpz *2012-05-15 20:55:23* + +**- make "select function" pass assertSqlCanBeParsedAndDeparsed** + + +[7a8bb](https://github.com/JSQLParser/JSqlParser/commit/7a8bbbe8abf9681) toben *2012-05-13 22:21:38* + +**- CAST - statement included** + + +[e22f5](https://github.com/JSQLParser/JSqlParser/commit/e22f5a3b6fe70aa) toben *2012-05-13 22:09:34* + +**removed main and junit 3 only artifacts from source code** + + +[3f854](https://github.com/JSQLParser/JSqlParser/commit/3f854eb7cbe63d9) toben *2012-05-13 12:39:52* + +**junit upgrade to 4.10** + + +[44b0d](https://github.com/JSQLParser/JSqlParser/commit/44b0d01d19571d0) toben *2012-05-13 12:35:33* + +**Refactoring of SelectTest** + + +[e1c80](https://github.com/JSQLParser/JSqlParser/commit/e1c80a0434df739) Florent Bécart *2011-12-02 07:20:18* + +**Removal of tests that are not able to pass** + +* - Functions do not accept conditions as arguments + +[aa5f0](https://github.com/JSQLParser/JSqlParser/commit/aa5f044c5bebc78) Florent Bécart *2011-12-02 07:20:18* + +**Code reformat** + + +[272bf](https://github.com/JSQLParser/JSqlParser/commit/272bf237eddcdc2) Florent Bécart *2011-12-02 07:20:18* + +**Modify DeParsers to output the same result as statement.toString();** + + +[2a35e](https://github.com/JSQLParser/JSqlParser/commit/2a35efd003ca5b5) Alice Rapunzel *2011-11-21 08:53:24* + +**Changed DeParsers to generic list types.** + + +[666ca](https://github.com/JSQLParser/JSqlParser/commit/666cac2edecc8d7) Christian Bockermann *2011-09-17 07:58:43* + +**Changed all lists to their appropriate generics type.** + + +[0dd60](https://github.com/JSQLParser/JSqlParser/commit/0dd60b143eae3f1) Christian Bockermann *2011-09-17 07:53:14* + +**.gitignore update** + + +[dd2a7](https://github.com/JSQLParser/JSqlParser/commit/dd2a75bd7fde3fb) Florent Bécart *2011-09-16 22:41:36* + +**Add the sources generated by javacc-maven-plugin to eclipse classpath** + + +[66556](https://github.com/JSQLParser/JSqlParser/commit/6655673c1531cac) Florent Bécart *2011-09-16 22:41:36* + +**Set the version of javacc-maven-plugin in pom.xml as recommended by maven** + + +[3f9c4](https://github.com/JSQLParser/JSqlParser/commit/3f9c4cc36c1a628) Florent Bécart *2011-09-16 22:41:36* + +**Project cleanup** + + +[0cb63](https://github.com/JSQLParser/JSqlParser/commit/0cb637199c9cd95) Florent Bécart *2011-09-16 22:41:36* + +**README update** + + +[00b8c](https://github.com/JSQLParser/JSqlParser/commit/00b8ca8dbb2ca6b) Florent Bécart *2011-09-16 22:41:36* + +**Added README** + + +[2005d](https://github.com/JSQLParser/JSqlParser/commit/2005d6db8594102) Christian Bockermann *2011-09-16 20:22:29* + +**Removed javcc-5.0 directory (no covered by Maven plugin)** + + +[61fb4](https://github.com/JSQLParser/JSqlParser/commit/61fb4a16876f9e4) Christian Bockermann *2011-09-16 20:13:28* + +**Added support for select without from-list ( SELECT 1 + 2 )** + +* Modified test cases for test resources in src/test/resources + +[0e5d7](https://github.com/JSQLParser/JSqlParser/commit/0e5d732e65bf622) Christian Bockermann *2011-09-16 20:06:07* + +**Moved classes to match Maven directory layout.** + + +[a8d70](https://github.com/JSQLParser/JSqlParser/commit/a8d70350729d085) Christian Bockermann *2011-09-16 19:48:54* + +**Use of StringBuilders instead of StringBuffers** + + +[ef03d](https://github.com/JSQLParser/JSqlParser/commit/ef03d68f8a365fc) Florent Bécart *2011-06-23 00:50:08* + +**Files generated by JavaCC should be ignored by Git** + + +[b5aff](https://github.com/JSQLParser/JSqlParser/commit/b5affcc84aaf6d7) Florent Bécart *2011-06-23 00:49:59* + +**Removal of files generated by JavaCC** + + +[767e3](https://github.com/JSQLParser/JSqlParser/commit/767e3c4e257512e) Florent Bécart *2011-06-23 00:05:33* + +**Bug Fix: the column deparser should use the table alias if any** + + +[bc8dc](https://github.com/JSQLParser/JSqlParser/commit/bc8dcbbe1fdae50) Florent Bécart *2011-06-23 00:01:57* + +**Use of generics** + +* - List of expressions in ItemsList +* - List of columns in Statement +* - List of joins in PlainSelect +* - List of withItems in Select +* - List of plainSelects in Union +* - List of orderByElements in Union +* - List of columns in Update +* - List of expressions in Update + +[8b0b8](https://github.com/JSQLParser/JSqlParser/commit/8b0b865780ee962) Florent Bécart *2011-06-22 20:00:44* + +**Insert statements accept both keywords "value" and "values"** + + +[1db31](https://github.com/JSQLParser/JSqlParser/commit/1db31a4491b01f1) Florent Bécart *2011-06-20 23:14:11* + +**Organize imports** + + +[db5e2](https://github.com/JSQLParser/JSqlParser/commit/db5e2501d8eefd5) Florent Bécart *2011-06-20 22:49:36* + +**Code reformat** + + +[fed74](https://github.com/JSQLParser/JSqlParser/commit/fed74aec2acf3db) Florent Bécart *2011-06-20 22:48:00* + +**Fixes a compilation error by removing an unused import** + + +[b9ce3](https://github.com/JSQLParser/JSqlParser/commit/b9ce35c945ffdab) Florent Bécart *2011-06-20 22:35:16* + +**Eclipse configuration files** + +* Makes development environment installation easier + +[b93af](https://github.com/JSQLParser/JSqlParser/commit/b93af3e4f333cdc) Florent Bécart *2011-06-20 22:33:30* + +**Add .gitignore file** + +* Auto-generated files that won't be pushed to the repo are: +* - classes: compiled main code +* - docs: project javadoc +* - *.jar: distribution jar (sources and documentation) +* - lib: library jar (.class files) +* - testclasses: compiled unit tests + +[55197](https://github.com/JSQLParser/JSqlParser/commit/5519799ce41c45b) Florent Bécart *2011-06-20 22:08:46* + +**Remove auto-generated folders docs and lib** + + +[d2f54](https://github.com/JSQLParser/JSqlParser/commit/d2f5416986e5c9b) Florent Bécart *2011-06-20 22:06:36* + +**Add junit library (required for ant build)** + + +[e0ad5](https://github.com/JSQLParser/JSqlParser/commit/e0ad59290667fc2) Florent Bécart *2011-06-20 21:50:19* + +**Add javacc-5.0 folder (required for ant build)** + + +[36ddc](https://github.com/JSQLParser/JSqlParser/commit/36ddcb236313093) Florent Bécart *2011-06-20 21:48:21* + +**Initial commit (base version: 0.7.0)** + +* Source: http://sourceforge.net/projects/jsqlparser/files/jsqlparser/jsqlparser-0.7.0.jar/download + +[67c91](https://github.com/JSQLParser/JSqlParser/commit/67c9150f5d93ced) Florent Bécart *2011-06-20 21:44:37* + + diff --git a/src/site/sphinx/contribution.rst b/src/site/sphinx/contribution.rst index 65fd49e4d..bfb3b3571 100644 --- a/src/site/sphinx/contribution.rst +++ b/src/site/sphinx/contribution.rst @@ -62,6 +62,7 @@ The JSQLParser is generated by ``JavaCC`` based on the provided Grammar. The Gra 5) Add the description of the new feature to the ``README.md`` file, section `Extensions`. 6) Build the package with ``Gradle`` and ensure, all checks do pass (PMD and CheckStyle and Code Formatting). + .. tab:: Gradle .. code-block:: shell From 7acf9d548edc854ddca5a9de0de151f5080ef590 Mon Sep 17 00:00:00 2001 From: lucarota Date: Fri, 15 Nov 2024 00:33:59 +0100 Subject: [PATCH 59/88] fix: Issue #2109 true and false value parsed as column instead of BooleanValue (#2110) Co-authored-by: Luca Rota --- .../jsqlparser/expression/BooleanValue.java | 74 +++++++++++++++++++ .../expression/ExpressionVisitor.java | 6 ++ .../expression/ExpressionVisitorAdapter.java | 5 ++ .../parser/ParserKeywordsUtils.java | 2 + .../sf/jsqlparser/util/TablesNamesFinder.java | 7 ++ .../util/deparser/ExpressionDeParser.java | 12 +++ .../validator/ExpressionValidator.java | 11 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 8 +- src/site/sphinx/keywords.rst | 4 + .../expression/BooleanValueTest.java | 49 ++++++++++++ .../statement/update/UpdateTest.java | 16 ++++ 11 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/sf/jsqlparser/expression/BooleanValue.java create mode 100644 src/test/java/net/sf/jsqlparser/expression/BooleanValueTest.java diff --git a/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java b/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java new file mode 100644 index 000000000..258a89e16 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/BooleanValue.java @@ -0,0 +1,74 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 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; + +import java.util.Objects; + +/** + * A boolean value true/false + */ +public final class BooleanValue extends ASTNodeAccessImpl implements Expression { + + private boolean value = false; + + public BooleanValue() { + // empty constructor + } + + public BooleanValue(String value) { + this(Boolean.parseBoolean(value)); + } + + public BooleanValue(boolean bool) { + value = bool; + } + + public boolean getValue() { + return value; + } + + public void setValue(boolean bool) { + value = bool; + } + + @Override + public T accept(ExpressionVisitor expressionVisitor, S context) { + return expressionVisitor.visit(this, context); + } + + @Override + public String toString() { + return Boolean.toString(value); + } + + public BooleanValue withValue(boolean bool) { + this.setValue(bool); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + BooleanValue that = (BooleanValue) o; + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index a6a0992b0..19067bf47 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -147,6 +147,12 @@ default void visit(StringValue stringValue) { this.visit(stringValue, null); } + T visit(BooleanValue booleanValue, S context); + + default void visit(BooleanValue booleanValue) { + this.visit(booleanValue, null); + } + T visit(Addition addition, S context); default void visit(Addition addition) { diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 6a54e3851..89bacff48 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -156,6 +156,11 @@ public T visit(StringValue stringValue, S context) { return visitExpression(stringValue, context); } + @Override + public T visit(BooleanValue booleanValue, S context) { + return visitExpression(booleanValue, context); + } + @Override public T visit(Addition addition, S context) { return visitBinaryExpression(addition, context); diff --git a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java index 80bc71779..2ac33fbd3 100644 --- a/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java +++ b/src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java @@ -68,6 +68,7 @@ public class ParserKeywordsUtils { {"EXCEPT", RESTRICTED_SQL2016}, {"EXCLUDES", RESTRICTED_JSQLPARSER}, {"EXISTS", RESTRICTED_SQL2016}, + {"FALSE", RESTRICTED_SQL2016}, {"FETCH", RESTRICTED_SQL2016}, {"FINAL", RESTRICTED_JSQLPARSER}, {"FOR", RESTRICTED_SQL2016}, @@ -131,6 +132,7 @@ public class ParserKeywordsUtils { {"TABLES", RESTRICTED_ALIAS}, {"TOP", RESTRICTED_SQL2016}, {"TRAILING", RESTRICTED_SQL2016}, + {"TRUE", RESTRICTED_SQL2016}, {"UNBOUNDED", RESTRICTED_JSQLPARSER}, {"UNION", RESTRICTED_SQL2016}, {"UNIQUE", RESTRICTED_SQL2016}, diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index ee4601e75..122d5cf2e 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -16,6 +16,7 @@ import net.sf.jsqlparser.expression.ArrayConstructor; import net.sf.jsqlparser.expression.ArrayExpression; import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.BooleanValue; import net.sf.jsqlparser.expression.CaseExpression; import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; @@ -626,6 +627,12 @@ public Void visit(StringValue stringValue, S context) { return null; } + @Override + public Void visit(BooleanValue booleanValue, S context) { + + return null; + } + @Override public Void visit(Subtraction subtraction, S context) { visitBinaryExpression(subtraction); 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 3b0e7281e..dc0c2b21f 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -16,6 +16,7 @@ import net.sf.jsqlparser.expression.ArrayConstructor; import net.sf.jsqlparser.expression.ArrayExpression; import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.BooleanValue; import net.sf.jsqlparser.expression.CaseExpression; import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; @@ -621,6 +622,13 @@ public StringBuilder visit(StringValue stringValue, S context) { return buffer; } + @Override + public StringBuilder visit(BooleanValue booleanValue, S context) { + buffer.append(booleanValue.getValue()); + + return buffer; + } + @Override public StringBuilder visit(Subtraction subtraction, S context) { deparse(subtraction, " - ", null); @@ -749,6 +757,10 @@ public void visit(StringValue stringValue) { visit(stringValue, null); } + public void visit(BooleanValue booleanValue) { + visit(booleanValue, null); + } + public void visit(Subtraction subtraction) { visit(subtraction, null); } 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 8c3a36066..c4fc26a94 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 @@ -15,6 +15,7 @@ import net.sf.jsqlparser.expression.ArrayConstructor; import net.sf.jsqlparser.expression.ArrayExpression; import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.BooleanValue; import net.sf.jsqlparser.expression.CaseExpression; import net.sf.jsqlparser.expression.CastExpression; import net.sf.jsqlparser.expression.CollateExpression; @@ -486,6 +487,12 @@ public Void visit(StringValue stringValue, S context) { return null; } + @Override + public Void visit(BooleanValue booleanValue, S context) { + // nothing to validate + return null; + } + @Override public Void visit(Subtraction subtraction, S context) { visitBinaryExpression(subtraction, " - "); @@ -620,6 +627,10 @@ public void visit(StringValue stringValue) { visit(stringValue, null); } + public void visit(BooleanValue booleanValue) { + visit(booleanValue, null); + } + public void visit(Subtraction subtraction) { visit(subtraction, null); } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 51b111cfb..a612e7f9f 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2022,7 +2022,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FALSE" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUE" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -4786,7 +4786,7 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2, {!interrupted}) retval=DateTimeLiteralExpression() - | LOOKAHEAD( 3 , {!interrupted}) retval=StructType() + | LOOKAHEAD(3 , {!interrupted}) retval=StructType() | LOOKAHEAD(3, {!interrupted}) retval=ArrayConstructor(true) @@ -4800,6 +4800,8 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2, {!interrupted}) retval=Column() + | LOOKAHEAD(2, {!interrupted}) (token= | token=) { retval = new BooleanValue(token.image); } + | token= { retval = new StringValue(token.image); linkAST(retval,jjtThis); } | "{d" token= "}" { retval = new DateValue(token.image); } @@ -6750,7 +6752,7 @@ String AList(): "(" ( - ( (tk= | tk= | tk=) { retval.append(tk.image); } + ( (tk= | tk= | tk= | tk= | tk=) { retval.append(tk.image); } | (name=RelObjectNameWithoutValue()) { retval.append(name); }) [("," {retval.append(",");} | "=" {retval.append("=");})] )* diff --git a/src/site/sphinx/keywords.rst b/src/site/sphinx/keywords.rst index 159c2fb85..8e890215e 100644 --- a/src/site/sphinx/keywords.rst +++ b/src/site/sphinx/keywords.rst @@ -53,6 +53,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | EXISTS | Yes | Yes | +----------------------+-------------+-----------+ +| FALSE | Yes | Yes | ++----------------------+-------------+-----------+ | FETCH | Yes | Yes | +----------------------+-------------+-----------+ | FINAL | Yes | Yes | @@ -179,6 +181,8 @@ The following Keywords are **restricted** in JSQLParser-|JSQLPARSER_VERSION| and +----------------------+-------------+-----------+ | TRAILING | Yes | Yes | +----------------------+-------------+-----------+ +| TRUE | Yes | Yes | ++----------------------+-------------+-----------+ | UNBOUNDED | Yes | Yes | +----------------------+-------------+-----------+ | UNION | Yes | Yes | diff --git a/src/test/java/net/sf/jsqlparser/expression/BooleanValueTest.java b/src/test/java/net/sf/jsqlparser/expression/BooleanValueTest.java new file mode 100644 index 000000000..93c936188 --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/expression/BooleanValueTest.java @@ -0,0 +1,49 @@ +/*- + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2024 JSQLParser + * %% + * Dual licensed under GNU LGPL 2.1 or Apache License 2.0 + * #L% + */ +package net.sf.jsqlparser.expression; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * + * @author tw + */ +public class BooleanValueTest { + + @Test + public void testTrueValue() { + BooleanValue value = new BooleanValue("true"); + + assertTrue(value.getValue()); + } + + @Test + public void testFalseValue() { + BooleanValue value = new BooleanValue("false"); + + assertFalse(value.getValue()); + } + + @Test + public void testWrongValueAsFalseLargeNumber() { + BooleanValue value = new BooleanValue("test"); + + assertFalse(value.getValue()); + } + + @Test + public void testNullStringValue() { + BooleanValue value = new BooleanValue(null); + + assertFalse(value.getValue()); + } +} diff --git a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java index 75ff452b0..127b4cfb7 100644 --- a/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.update; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.BooleanValue; import net.sf.jsqlparser.expression.DoubleValue; import net.sf.jsqlparser.expression.JdbcParameter; import net.sf.jsqlparser.expression.LongValue; @@ -36,6 +37,7 @@ import static net.sf.jsqlparser.test.TestUtils.assertUpdateMysqlHintExists; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -550,4 +552,18 @@ public void testPreferringClause(String sqlStr) throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlStr); } + @Test + public void testUpdateWithBoolean() throws JSQLParserException { + String statement = "UPDATE mytable set col1='as', col2=true Where o >= 3"; + Update update = (Update) PARSER_MANAGER.parse(new StringReader(statement)); + assertEquals("mytable", update.getTable().toString()); + assertEquals(2, update.getUpdateSets().size()); + assertEquals("col1", update.getUpdateSets().get(0).getColumns().get(0).getColumnName()); + assertEquals("col2", update.getUpdateSets().get(1).getColumns().get(0).getColumnName()); + assertEquals("as", + ((StringValue) update.getUpdateSets().get(0).getValues().get(0)).getValue()); + assertInstanceOf(BooleanValue.class, update.getUpdateSets().get(1).getValues().get(0)); + assertTrue(((BooleanValue) update.getUpdateSets().get(1).getValues().get(0)).getValue()); + assertInstanceOf(GreaterThanEquals.class, update.getWhere()); + } } From f80800ca5294e89b618998c527d67992da88aa8a Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sat, 16 Nov 2024 10:50:23 +0700 Subject: [PATCH 60/88] feat: proper `:` JSon operator - `:` is allowed as delimiter in table names (for INFORMIX) - otherwise `:` will return a JSON expression and can't be used as column delimiter - see #1134 and #2001 Signed-off-by: Andreas Reichel --- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 20 +++++++++++++++++-- .../expression/JsonExpressionTest.java | 12 ++++++++++- .../select/ExpressionDelimiterTest.java | 10 +++++++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index a612e7f9f..3356c2066 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -1969,6 +1969,7 @@ MergeOperation MergeWhenNotMatched() : { { return mi; } } +// table names seem to allow ":" delimiters, e.g. for Informix see #1134 ObjectNames RelObjectNames() : { String token = null; Token delimiter = null; @@ -1984,8 +1985,23 @@ ObjectNames RelObjectNames() : { { return new ObjectNames(data, delimiters); } } -// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx +// column names do not allow ":" delimeters as those represent JSON `GET` operators +ObjectNames ColumnIdentifier() : { + String token = null; + Token delimiter = null; + List data = new ArrayList(); + List delimiters = new ArrayList(); +} { + token = RelObjectNameExt() { data.add(token); } + ( + LOOKAHEAD (2) ( delimiter = "." ) { delimiters.add(delimiter.image); } (( delimiter = "." ) { data.add(null); delimiters.add(delimiter.image); })* + token = RelObjectNameExt2() { data.add(token); } + ) * + { return new ObjectNames(data, delimiters); } +} + +// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx Column Column() #Column : { ObjectNames data = null; @@ -1993,7 +2009,7 @@ Column Column() #Column : Token tk = null; } { - data = RelObjectNames() + data = ColumnIdentifier() [ LOOKAHEAD(2) tk= ] // @todo: we better should return a SEQUENCE instead of a COLUMN [ LOOKAHEAD(2) "." { data.getNames().add("nextval"); } ] diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java index 1a02dbcc2..cb4e92ac6 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JsonExpressionTest.java @@ -10,6 +10,8 @@ package net.sf.jsqlparser.expression; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.statement.select.PlainSelect; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -40,7 +42,15 @@ void testIssue1792() throws JSQLParserException { @Test void testSnowflakeGetOperator() throws JSQLParserException { String sqlStr = "SELECT v:'attr[0].name' FROM vartab;"; - assertSqlCanBeParsedAndDeparsed(sqlStr, true); + PlainSelect st = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + Assertions.assertInstanceOf(JsonExpression.class, st.getSelectItem(0).getExpression()); + } + + @Test + void testDataBricksExtractPathOperator() throws JSQLParserException { + String sqlStr = "SELECT C1:PRICE J FROM VALUES('{\"price\":5}')AS T(C1)"; + PlainSelect st = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true); + Assertions.assertInstanceOf(JsonExpression.class, st.getSelectItem(0).getExpression()); } @Test diff --git a/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java b/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java index cb4a63c97..6c14a331f 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/ExpressionDelimiterTest.java @@ -10,7 +10,10 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.JsonExpression; import net.sf.jsqlparser.schema.Column; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.List; @@ -24,12 +27,13 @@ public class ExpressionDelimiterTest { public void testColumnWithDifferentDelimiters() throws JSQLParserException { String statement = "SELECT mytable.mycolumn:parent:child FROM mytable"; PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement); - Column column = parsed.getSelectItem(0).getExpression(Column.class); - assertEquals(":", column.getTableDelimiter()); - assertEquals(List.of(":", "."), column.getTable().getNamePartDelimiters()); + Assertions.assertInstanceOf(JsonExpression.class, parsed.getSelectItem(0).getExpression()); } + // I don't know what kind of Operator ".:." shall present + // please rework @Test + @Disabled public void testColumnWithEmptyNameParts() throws JSQLParserException { String statement = "SELECT mytable.:.child FROM mytable"; PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement); From fee2f90c0283b3ecea7e3b5818d4b576e58cad0c Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Sun, 24 Nov 2024 09:46:00 +0900 Subject: [PATCH 61/88] Fix issue 2106: Add parsing functionality for MySQL ALTER Table option statements (#2115) * add alter table option * fix CreateParameter by adding auto_increment for passing test * fix by updatekeywords * test add assertSqlCanBeParsedAndDeparsed --------- Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 11 +++ .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 39 ++++++++++- .../jsqlparser/statement/alter/AlterTest.java | 67 +++++++++++++++++++ 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 38bed4b7a..1f26a70c7 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -57,6 +57,7 @@ public class AlterExpression implements Serializable { private String collation; private String lockOption; private String commentText; + private String tableOption; private boolean hasColumn = false; private boolean hasColumns = false; @@ -114,6 +115,14 @@ public void setCommentText(String commentText) { this.commentText = commentText; } + public String getTableOption() { + return tableOption; + } + + public void setTableOption(String tableOption) { + this.tableOption = tableOption; + } + public AlterOperation getOperation() { return operation; } @@ -454,6 +463,8 @@ public String toString() { if (operation == AlterOperation.UNSPECIFIC) { b.append(optionalSpecifier); + } else if (operation == AlterOperation.SET_TABLE_OPTION) { + b.append(tableOption); } else if (getOldIndex() != null) { b.append("RENAME"); switch (operation) { diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index f7cd0a4a3..fceeb9cae 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, TRUNCATE_PARTITION, LOCK; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, TRUNCATE_PARTITION, SET_TABLE_OPTION, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 3356c2066..f124a2ea9 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -173,6 +173,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -244,6 +245,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -2038,7 +2040,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="AUTO_INCREMENT" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="ENCRYPTION" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -6706,7 +6708,7 @@ List CreateParameter(): { param.add("TABLESPACE " + retval); } | ( - tk= | tk= | tk= | tk= | tk= + tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= @@ -7439,6 +7441,39 @@ AlterExpression AlterExpression(): tk= { alterExp.setCommentText(tk.image); } ) | + ( {alterExp.setOperation(AlterOperation.SET_TABLE_OPTION);} + ["=" { alterExp.setUseEqual(true);} ] + tk= { + if (alterExp.getUseEqual()) { + alterExp.setTableOption("ENCRYPTION = " + tk.image); + } else { + alterExp.setTableOption("ENCRYPTION " + tk.image); + } + } + ) + | + ( {alterExp.setOperation(AlterOperation.SET_TABLE_OPTION);} + ["=" { alterExp.setUseEqual(true);} ] + tk= { + if (alterExp.getUseEqual()) { + alterExp.setTableOption("AUTO_INCREMENT = " + tk.image); + } else { + alterExp.setTableOption("AUTO_INCREMENT " + tk.image); + } + } + ) + | + ( {alterExp.setOperation(AlterOperation.SET_TABLE_OPTION);} + ["=" { alterExp.setUseEqual(true);} ] + tk= { + if (alterExp.getUseEqual()) { + alterExp.setTableOption("ENGINE = " + tk.image); + } else { + alterExp.setTableOption("ENGINE " + tk.image); + } + } + ) + | LOOKAHEAD(2) ( (( {alterExp.setOperation(AlterOperation.RENAME_INDEX);} | {alterExp.setOperation(AlterOperation.RENAME_KEY);}) diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 79a11def2..005961a3d 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -30,6 +30,7 @@ import java.util.List; import static net.sf.jsqlparser.test.TestUtils.*; +import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.*; public class AlterTest { @@ -1275,4 +1276,70 @@ public void testIssue2106AlterTableTruncatePartition() throws JSQLParserExceptio assertEquals("p201801", partitionNames.get(2)); assertEquals("p201807", partitionNames.get(3)); } + + + @Test + public void testIssue2114AlterTableEncryption() throws JSQLParserException { + String sql = "ALTER TABLE confidential_data ENCRYPTION = 'Y'"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression encryptionExp = alterExpressions.get(0); + assertEquals(AlterOperation.SET_TABLE_OPTION, encryptionExp.getOperation()); + assertEquals(encryptionExp.getTableOption(), "ENCRYPTION = 'Y'"); + + assertSqlCanBeParsedAndDeparsed(sql); + } + + @Test + public void testIssue2114AlterTableEncryptionWithoutEqual() throws JSQLParserException { + String sql = "ALTER TABLE confidential_data ENCRYPTION 'N'"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression encryptionExp = alterExpressions.get(0); + assertEquals(AlterOperation.SET_TABLE_OPTION, encryptionExp.getOperation()); + assertEquals(encryptionExp.getTableOption(), "ENCRYPTION 'N'"); + assertSqlCanBeParsedAndDeparsed(sql); + } + + @Test + public void testIssue2114AlterTableAutoIncrement() throws JSQLParserException { + String sql = "ALTER TABLE tt AUTO_INCREMENT = 101"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression autoIncrementExp = alterExpressions.get(0); + assertEquals(AlterOperation.SET_TABLE_OPTION, autoIncrementExp.getOperation()); + assertEquals(autoIncrementExp.getTableOption(), "AUTO_INCREMENT = 101"); + assertSqlCanBeParsedAndDeparsed(sql); + } + + @Test + public void testIssue2114AlterTableEngine() throws JSQLParserException { + String sql = "ALTER TABLE city2 ENGINE = InnoDB"; + Statement stmt = CCJSqlParserUtil.parse(sql); + assertTrue(stmt instanceof Alter); + Alter alter = (Alter) stmt; + List alterExpressions = alter.getAlterExpressions(); + assertNotNull(alterExpressions); + assertEquals(1, alterExpressions.size()); + + AlterExpression engineExp = alterExpressions.get(0); + assertEquals(AlterOperation.SET_TABLE_OPTION, engineExp.getOperation()); + assertEquals(engineExp.getTableOption(), "ENGINE = InnoDB"); + assertSqlCanBeParsedAndDeparsed(sql); + } } From 8b4149b3b7e9a35d881da710d5c34c2f6ac0df36 Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Tue, 26 Nov 2024 14:55:37 +0900 Subject: [PATCH 62/88] Fix issue 2089: Enhance MySQL CONVERT Statement Parsing (#2117) * fix convert toString * fix mysql convert --------- Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 51 ++++++++++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 26 ++++++- .../jsqlparser/statement/alter/AlterTest.java | 68 ++++++++++++------- 3 files changed, 116 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 1f26a70c7..4fd1f4209 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -53,6 +53,11 @@ public class AlterExpression implements Serializable { private List partitionDefinitions; private List constraints; private List parameters; + + private ConvertType convertType; + private boolean hasEqualForCharacterSet; + private boolean hasEqualForCollate; + private String characterSet; private String collation; private String lockOption; @@ -401,6 +406,14 @@ public List getParameters() { return parameters; } + public ConvertType getConvertType() { + return convertType; + } + + public void setConvertType(ConvertType convertType) { + this.convertType = convertType; + } + public String getCharacterSet() { return characterSet; } @@ -485,6 +498,32 @@ public String toString() { } else if (operation == AlterOperation.DROP_PRIMARY_KEY) { b.append("DROP PRIMARY KEY "); + } else if (operation == AlterOperation.CONVERT) { + if (convertType == ConvertType.CONVERT_TO) { + b.append("CONVERT TO CHARACTER SET "); + } else if (convertType == ConvertType.DEFAULT_CHARACTER_SET) { + b.append("DEFAULT CHARACTER SET "); + if (hasEqualForCharacterSet) { + b.append("= "); + } + } else if (convertType == ConvertType.CHARACTER_SET) { + b.append("CHARACTER SET "); + if (hasEqualForCharacterSet) { + b.append("= "); + } + } + + if (getCharacterSet() != null) { + b.append(getCharacterSet()); + } + + if (getCollation() != null) { + b.append(" COLLATE "); + if (hasEqualForCollate) { + b.append("= "); + } + b.append(getCollation()); + } } else if (operation == AlterOperation.DROP_UNIQUE) { b.append("DROP UNIQUE (").append(PlainSelect.getStringList(pkColumns)).append(')'); @@ -797,6 +836,14 @@ public void setPartitionDefinitions(List partitionDefinitio this.partitionDefinitions = partitionDefinition; } + public void setHasEqualForCharacterSet(boolean hasEqualForCharacterSet) { + this.hasEqualForCharacterSet = hasEqualForCharacterSet; + } + + public void setHasEqualForCollate(boolean hasEqualForCollate) { + this.hasEqualForCollate = hasEqualForCollate; + } + public static final class ColumnDataType extends ColumnDefinition { private final boolean withType; @@ -890,4 +937,8 @@ public String toString() { return columnName + " DROP DEFAULT"; } } + + public enum ConvertType { + CONVERT_TO, DEFAULT_CHARACTER_SET, CHARACTER_SET + } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index f124a2ea9..4d26413b5 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -7430,11 +7430,31 @@ AlterExpression AlterExpression(): {alterExp.setOperation(AlterOperation.RENAME_TABLE);} (tk2= | tk2=) { alterExp.setNewTableName(tk2.image);} ) - | - ( { alterExp.setOperation(AlterOperation.CONVERT); } + | ( { + alterExp.setOperation(AlterOperation.CONVERT); + alterExp.setConvertType(AlterExpression.ConvertType.CONVERT_TO); + } tk= { alterExp.setCharacterSet(tk.image); } [ tk2= { alterExp.setCollation(tk2.image); }] - ) + ) + | ( { + alterExp.setOperation(AlterOperation.CONVERT); + alterExp.setConvertType(AlterExpression.ConvertType.DEFAULT_CHARACTER_SET); + } + [ "=" { alterExp.setHasEqualForCharacterSet(true); } ] + tk= { alterExp.setCharacterSet(tk.image); } + [ [ "=" { alterExp.setHasEqualForCollate(true); } ] + tk2= { alterExp.setCollation(tk2.image); }] + ) + | ( [ "=" { alterExp.setHasEqualForCharacterSet(true); } ] + tk= { + alterExp.setOperation(AlterOperation.CONVERT); + alterExp.setConvertType(AlterExpression.ConvertType.CHARACTER_SET); + alterExp.setCharacterSet(tk.image); + } + [ [ "=" { alterExp.setHasEqualForCollate(true); } ] + tk2= { alterExp.setCollation(tk2.image); }] + ) | ( {alterExp.setOperation(AlterOperation.COMMENT);} ["=" {alterExp.setOperation(AlterOperation.COMMENT_WITH_EQUAL_SIGN);} ] diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 005961a3d..03ec3e85e 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -24,13 +24,16 @@ import net.sf.jsqlparser.statement.create.table.*; import net.sf.jsqlparser.statement.create.table.Index.ColumnParams; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Stream; import static net.sf.jsqlparser.test.TestUtils.*; -import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.*; public class AlterTest { @@ -1093,41 +1096,54 @@ public void testIssue2090LockExclusive() throws JSQLParserException { assertEquals("EXCLUSIVE", lockExp.getLockOption()); } - @Test - public void testIssue2089() throws JSQLParserException { - String sql = "ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4"; + @ParameterizedTest + @MethodSource("provideMySQLConvertTestCases") + public void testIssue2089(String sql, String expectedCharacterSet, String expectedCollation) + throws JSQLParserException { Statement stmt = CCJSqlParserUtil.parse(sql); - assertTrue(stmt instanceof Alter); + assertTrue(stmt instanceof Alter, + "Expected instance of Alter but got: " + stmt.getClass().getSimpleName()); + Alter alter = (Alter) stmt; assertEquals("test_table", alter.getTable().getFullyQualifiedName()); List alterExpressions = alter.getAlterExpressions(); - assertNotNull(alterExpressions); - assertEquals(1, alterExpressions.size()); + assertNotNull(alterExpressions, "Alter expressions should not be null for SQL: " + sql); + assertEquals(1, alterExpressions.size(), "Expected 1 alter expression for SQL: " + sql); AlterExpression convertExp = alterExpressions.get(0); assertEquals(AlterOperation.CONVERT, convertExp.getOperation()); - assertEquals("utf8mb4", convertExp.getCharacterSet()); - assertNull(convertExp.getCollation()); - } - - @Test - public void testIssue2089WithCollation() throws JSQLParserException { - String sql = - "ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"; - Statement stmt = CCJSqlParserUtil.parse(sql); - assertTrue(stmt instanceof Alter); - Alter alter = (Alter) stmt; - assertEquals("test_table", alter.getTable().getFullyQualifiedName()); - List alterExpressions = alter.getAlterExpressions(); - assertNotNull(alterExpressions); - assertEquals(1, alterExpressions.size()); + assertEquals(expectedCharacterSet, convertExp.getCharacterSet(), + "CHARACTER SET mismatch for SQL: " + sql); + assertEquals(expectedCollation, convertExp.getCollation(), + "COLLATE mismatch for SQL: " + sql); + assertSqlCanBeParsedAndDeparsed(sql); + } - AlterExpression convertExp = alterExpressions.get(0); - assertEquals(AlterOperation.CONVERT, convertExp.getOperation()); - assertEquals("utf8mb4", convertExp.getCharacterSet()); - assertEquals("utf8mb4_general_ci", convertExp.getCollation()); + private static Stream provideMySQLConvertTestCases() { + return Stream.of( + Arguments.of("ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4", "utf8mb4", + null), + Arguments.of( + "ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", + "utf8mb4", "utf8mb4_general_ci"), + Arguments.of( + "ALTER TABLE test_table DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", + "utf8mb4", "utf8mb4_general_ci"), + Arguments.of( + "ALTER TABLE test_table DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci", + "utf8mb4", "utf8mb4_general_ci"), + Arguments.of( + "ALTER TABLE test_table CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", + "utf8mb4", "utf8mb4_general_ci"), + Arguments.of( + "ALTER TABLE test_table CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci", + "utf8mb4", "utf8mb4_general_ci"), + Arguments.of("ALTER TABLE test_table DEFAULT CHARACTER SET utf8mb4", "utf8mb4", + null), + Arguments.of("ALTER TABLE test_table DEFAULT CHARACTER SET = utf8mb4", "utf8mb4", + null)); } @Test From d5af1f1cf93d0ca97f71080f5d35c392fb7c6960 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Tue, 26 Nov 2024 13:06:42 +0700 Subject: [PATCH 63/88] update Gradle wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 ++++- gradlew.bat | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 zcmY+pRa6|n(lttO3GVLh?(Xh3xVuAe26uONcL=V5;I6?T_zdn2`Oi5I_gl9gx~lft zRjVKRp?B~8Wyrx5$mS3|py!Njy{0Wt4i%@s8v88pK z6fPNA45)|*9+*w5kcg$o)}2g}%JfXe6l9ig4T8ia3Hlw#3f^fAKW63%<~GZJd-0YA z9YjleCs~#Y?V+`#nr+49hhsr$K$k!lg}AZDw@>2j=f7t~5IW6#K|lAX7|^N}lJ)I!km`nrwx> z))1Es16__aXGVzQM0EC8xH+O!nqTFBg9Ci{NwRK*CP<6s`Gq(~#lqb(zOlh6ZDBK* zr$|NDj^s6VanrKa+QC;5>twePaexqRI%RO~OY075y?NN90I|f^(P# zF=b>fZ73b5JzD`#GC3lTQ_B3lMeBWgQUGYnFw*HQC}^z{$6G4j(n4y-pRxPT(d2Wgb%vCH(?+t&Pj z)QM`zc`U`+<~D+9E{4Uj2kc#*6eZMU$4Oj6QMfA^K!rbl`iBix=2sPrs7j@aqIrE zTaZJ2M09>rp$mgyUZ!r2$UK{+DGqgl`n;*qFF~M(r#eh`T{MO?2&j?xgr8FU$u3-` zhRDc_I23LL4)K&xg$^&l-W=!Jp-P(_Ie07q>Je;QLxi8LaEc%;WIacJD_T69egF?7 z;I_Sg_!+qrur8$Hq4grigaiVF>U7uWJ@Hkd&%kmFnQN-P^fq0gB1|uRt!U#X;DnlV zo?yHWTw7g5B;#xxY`adhi4yZn@f(7-Xa(J6S=#d@&rlFw!qfvholE>MEb|VWn^g}G zMSrK&zQ^vDId&ojL!{%{o7?s{7;{+u%L{|tar(gp?Uxq3p?xAysB>0E$eG#$tvkk9 z2Q2gEP17{U6@UD*v({5MP-CTZfvWMItVjb4c;i~WLq&{?Q1(koX&vt7+$z}10{^Id z{KDjGi0JpD7@;~odF__0m|p;5rIrHidOP9^mwKe#-&JX-X@acc)06G{LO1Wu)#gvZ za~y9(fhA%UwkDOVU1LBJ`0ROE z4&)dJKK%mG@+CIm?+wt9f~@xIMr8}UH*K1j| z0pppo{7gv3v{URwxVMeg>Ps!L5IKxm zjac2egjgb0vH5i75$s|sY_RYec#>faqJk|AGgV;v=^%BM(^p{p;(^SVt-88G9f!q; z>p}9E4^f0=01S2pQBE4}9YqE%TV)*hlU^8k9{&=K76+*Ax^r=AkBb%OCP^P2nm0Ri z;D-|Zk?gGeU<12ti2CnPVNA(Pb)02+r|&yTWW-OJO7 zNLb0pps6aN?A~NJp5kj{{IOlf!5KWMleV@-hYLift)D>-7K+tgs=7Ake}oBnIy-y1 z(Hn@Hjw=_(x>dO5ysQsrnE%A*bk0K<-j{1Yqz@#n#jOL^AzCr#wR|WYzqk6i7v)Lf zkXdKxzuu20aP{Tbg$(+9&oh7cd(Uoqqf<#ujb$q4sZ~gxFbQfS zS)kNklyL*{2AELgjZ(LBu*>S(oH5AaJ;YiB@;l@=O%F6B?oanzoYRM^fQ9-<~^=3$H0g^JPMLQo@SZ@QuNvy)tyJ)LSj`+()#fy?{aV4Yg^7dlQ7AQM^3GLCR2dAFR zJjtfKiVqF`l-H_fz0HD|9g>)pOxn}k!vdZ=DO!7Sikm{Z%P6BrRkBS6W?ZB5W&7rT z@uYpf@M@a!z7H&o@-yrcCL^Ff3e7p3T`R9p?@o-acXmbTSa0>ZANzCSgovsd%;i$| zVus`not!oL#(W`L-!9w0jdaECaG4hk{V7IOs676ZquZH~0TX5hDq|)x z6T497l|E?f4)LA>j=S8}b$0LS=I4h|hUFJYJODT8Li@#6kF$k0)@*l{RnM1HQ%?VT ze-Pqlc!~t(oumVC*?5fwR;P6u{tHaZ~*LlD;B)4f? z?lpWfa2P@)g57flVl83Ej%P`2)gGyaPjhvD(%i~{`2b>#3!+y&` z!2nuwHMFA-zUY}f1^0B8<`N)Gr=A4TS@b1qykmd0Pq{?r)+1^^+D(=xasb^Tf!oK9 zBLL+*p6M_#ufgLzgq1zcSwZsZnQWFLC3`Yxdg-2=*tT`J9nrfYt)RF)YryBf8_gW{ zvKbB+oZLehfT)S#<|y1)E0hW^?+AnqPXq9Hu;v3dsMGdr{SVyF63;K<8VcgI#~}1i zLYSBL0K;RTT(;>2x=*!1Di9w0mwr;`CN}kM65|Ay{~z}_^JKOsRaN<~#9O^iiW<5P zYN7r~HV!#Nz~IZU`P>1Xe%4f~K}KcF#X&5kO*G}-)74S*tQ8CietdPcA1Yl;S=Mr# z`#MYY!{s^uo=jn7;k6O%(}fN+*0cWMpt~#n9DR<3NyU?+3D^AgI}S)Cu-Tljg`VY} zX1=fq$?8$DtOeGxE6f8lbS_6Q3C4+LDTO$}_IpM$Xv<|QSC%+Oll^q$y`7o@jD{dp zNDl|&X)r7wETa-#h*d`KXntxI(Y{vLha{$0i7@G8xx^m=c<{lJ9?p-i!^W{%j7-oo z0W^SzZ^(Wkyz*We{lEn%Yhu-ycUOHtrRiVJL4~&S91*D0MrLu}Q>v-Mc?GcWfpyz% zX|UvcN@krFO#@v|CtYM}g|=L3%aMo$E5<@CM%c*;?u>LOTz00@+dt1{yg1y=$h+{|D17U}$*^fE^H&8b431EUE z<9tv0V_#%#&1N#j7AKCj!tTK@J%oFW*ESW<(#Gl#Xs%v<@AitI?s92nLzm<)w3Wkkom1f$gcdUi%g_*jofy&}N#luL<$GVIe{iQkQ)sIHVy zBgItnPBFamrv6Kb{eE($Q(f`ZPeW!Hm%Y@F*OF1sKB{Yy|C>WEv_mfvv-N-jh)B-5 z4a!1WcT@9a+hGaBrc~sz=>G?Q!*Zp^JFRUvBMyNR1;`)j$RhH$6gEyVKhd$&K-CFT zXaWC-Y=fyOnqT84iMn9o5oLEOI(_3fk!W^8-74|q1QhQ|CmT0i=b;6Z3u?E{p7V{? z;f#Q-33!L+4&QQcZ~GAqu$NS{M;u%`+#9=7^Oa5PKvCCCWNG_~l(CidS!+xr-*gg{ z$UQ`_1tLT_9jB=Hckkwu>G{s0b0F4bnR7GibmHo?>TR&<3?D;5Fb#gd8*wYa$$~ar z7epl1qM)L{kwiNjQk}?)CFpNTd?0wAOUZ|gC{Ub|c-7h~+Rm(JbdoRe!RNVBQi!M8 z+~U6E2X&KSA*T6KJvsqwqZl#1&==Dm(#b^&VAKQ>7ygv*Fyr;)q9*^F@dCTg2g!w~ z%hg)UXAUyIpIbLXJv1nZX+a_C)BOH2hUim|>=JHCRf(!dtTidb&*~I!JrfRe+PO>w z@ox$G2a3i9d_N9J=|2$y2m-P&#PTNwe!oLBZFs;z|F5kXvBDn<)WwE0E3$ow=zg3R zK(9;sf0t;VEV3@gAg7jRtnj%-6O@!Hvg*;XcUAw}!=2*aErvB(eQIm(-UGmq^J=XN zTqJo$Y|WKo^HlBF3BXJrA#}7ZLg=r*w`I*~Ix`o&2k8^(0mt8Rp=A>F`&gehhp@Jy z^e^#B2!~$LvNCKugg)8)-G%&THdk~kfextilegP9?#C#()F59U$&eo(h|5>ceo*Em z{PEE79T$YP|Kr7K`WBHbtQwyxFkCl6xX&+oUf90B5xoi3_5KHHCyEE*oPbOQkfMz& z6^hT8_NXd2iWk{q9IKae1{_7hMPH8I7_BMtVOM4 z6jm?E0QJOn$qrgsJ`9w##GB9?G})-GXSQo6(tYS(Q0-Ct$co?Zzl0?NHsDRron?;_ zZZgQg)%XW>P?8_&zoGuF(>Och2kEJXsu1_X&~w87x!b z>~h!a>e7{`p@+#hXF88wI*JeWRZ;J4ev4<}HWf|Z;(7$E!S5l9wzBHFe>^I{2`a;a)QnAwa2xv1e(bq$<}!8o^ofGvYpk7dBR+`*%iE;hUY5 zaHF}OjGO9r*{%lmcK^uFiTHgoUD`^9Nx@~;Bg!V* zuuJ&ti{DQiq7RyJAR94wem{}cPK1J(Yxnn_{=>?USqz-~&QXRStS^s-7TksZ$AEI! z#og36s3JGtGU{CnDHRFtipFqvrE*gw7_K@NN0h+ItTq@4fqN!HeQU1y7*X?9+IfZT4Vxebpt z%#VzgdDK~-&+=Z*#>=n#XUhNvBZp3=Cr41jMqwJkHLf3L7Vm~V#GgJ(Jpii~PmJ#s zA7Ft!{xD@z>9DUb4JbiUBdNEcU4BO$651iN*mp*f)HbRRM`Cx5cR?5IfEcU{IZWwf zz(M6CDv)>xa3x}K6%tP^i15P1&&DOLK=k~+jNR$UK3frSl+|PjSC-dBItvD~LL! z>_g(YYdO4k(5EbPOw+v+;G7~jYm>F@Ai|o`gs%F)F8tDz$dl7Q%aCe|v|$UkAul_R zNlA-beBX^IJU?kgS`E$it7nF4DaI!SJAGq)2P&Few(-|tp z?K+%D3e4{pfkayrcbm0ftu6Ol2ZzdKM+4i!hNP3NRL`EvvZJ3yvNr2MV%igZ4kj``Qrdb_OI$7jWP z;l0DYf&0(-*QcP5zrP`HVznW+SbH63Qx$7_9~NjRNg7eKqI!UJ=XH`g^=t8GiFTu( z?2L{JKEu%jJx&XjNzU(*!ZNmL1@RlJA0G$2_LrAb_7lmjil(GSlSM zwTes`m+3R;3#N~Xg#9owh3ycXV8@ZlaY_16kpPFA={721b~URO4HD3sp%fmkZM}k) zZB0#)kP=RkNB~R-MCk8aljG_bagt4vIb~8)BV%(b8_;)&Kf9GX+%O_cNG|(D$!3&D zL(I8}*LqN5NntipFlN13=`D>6!{D@CFMBH0kW3=HccJV+xW~|$qeFR5i-2{X+iWMu zI2$gepQ)H_B%ip_BlWOQ*|pErXs|4ir{IHccgaIJ84irE{?+$KDABXr&f`jB^V-c% z$$u`uU1YB^{<+UN2cNg#7&0bz@yF?5>j|;)5&IV3wIQp58X#OE-M^$HdyvL|Um5t? zhZlAG!Mz%XkUe3t471JM*Yur}o30vzu6RN7gJyNcf!IItsDO730mcJ*O!~V``y5=3 zNJGp34DZ}wd1H6V`Uuy%es>BiO_aE-S8jzir#$& zyk)@2a5tP$@g%jW^b^JGdo)X@Q%sE`^lDQmY9m%uDFpPX`w9%=yQ+nneMm#OaXcD` z9}{tn5A2b2z9783vL2_jSao?uxJhWJoq%47*RafM4o0@gY(p)F>qT4^XM5GLzV#6j zC+HoGhAne7o_w{WUo(B++z7lU3Y0k1rYv9|TSv0vR-Du(5=VakbbelgZTeDn+a_Wv zq_j-^+Qz1WAl;Zg>ahX|CERbX1V%B!hTKN?M}fGoA07M(WU&NfT&TmN`P@56U2 z^)vLDs|Ln~0iTtn-?KTeQl@T&bskJFuTUS!m+$CS9vnd}8(UMO|Kv6TCfGN9NUu&4 zL{)GTxPq>fwsJ~aU=4Qhuq8*RzDsP(LZh$BHezq&9gK$IS<|DYbm})$QTGCS6T;Dr zEkLct!b+#<1r9OKG@P!f1wm8>=Nz!7OzJm!g<+`?N3;YaA3(P@EL=(sTaRMDD!c8=-XN^4BXp(eVkj$NmEMYPP>YJ4bJ3yUud z<3BeJAJ$6z^TuywnfH5lv#$lgwraNw{IV=tIznPH1DT`v-5yS=!)J<}xxl}uZf9azA2A97Haf!;<3y01hlw?dWNEv@TLi1s-mO4vmIT%O_42nS z$VRWrs9NngqRRkWAnWkn%`Rw@?wH|)7XL`EL5EZu$qyJW31&CB^T_)qwIv!{;E_6 zo-9XAryQRlk-O0>o#-SZO>|6OYq;}<*>Wu1AsVRiXY4f8qb;+sItv3AyS!4Ry+q}) zA!pAB|BmC;=RIOk^^vlsEH(!Q!7_1FK~ZB2err*o!+b(r=m1b?$6d!%zmN+69LXnT z&gRmM+n_R-F@sT*IYv0_mGPvur!u`iWbQO7SqiGFLeY&yga zf`lM&B74FA2C?N@8_z652fjhBEoDUKbP8hL{0{HAF%qDo7)o3=3rg#6)T7%%5^wl% z9R0*S*<~>nzYOdQk2l`9h#t+gJy_xujw6xjV(8S<_DbVg61&pT%Hi42l%D73G?adn znB%UdNM0p}lEF-P2%TAMam2zpQev71e>a$$%i+r~b+D9G9pF|oY_*(-u*89oKsXLY+UIbqq)MQ%(GYS{(*n_S_*RN$*~`zUtab%0aKwhx znc)Yo?{xq1sJCgQD)TeTci1ucvbez9q=A72H(-SB18Kl&6^vHV8^i!p@>iF!DIw17 z+8Q)TNisB7>pwyww4y)yJx*wX6SJO78eLBC-ar1+k$Z9fy;wBD|3kzI{<+l*>PSY^ z_?nLOZaeWbU@C3hfK?X;Di*8CHCPkx2qco6(ZyJdqSzp^TJ_5Lpa0UP{Gy+!b0Lr% z@xYxSjUKoY6L#>$qx~KD$-0=|OF7zhVP~ntMgEALYPIfhj@+ z!;JJ7te>CcovruwHsJH6Lta$nm|%^C@=V-rmhU{+I~0(|XHQ9jt@L7pb{gx#{4r!) zg($FyFTslcgu(~6lYr$nW?)%*l#VJ=R-jxK(x=t1bWlu(nL66T#qj%3aZ@uVhy}Co zDU_q61DD5FqqJ*#c|(M5tV)XBN?Ac^12*q)VN4yKPJ|#==S_`_QD9|0ls!`2)SwuHDRA_OfXQDq3%qW&MZB}Z!=k-9xqev8jHz(H z{^D@cIB~QiK>~wa)A&^Ll^Wi6QgCzU;iv-BHsLBs zH7=jN%|>0S`SjP%M&AF1PNVDp_FZ?2Bm@7`DC&v(pYrw!!yD#4 z6+<=HS0Ln6MhoKxF<%~H`y20{vf#pxh=;j{zY381gvAFekgG|>G1zo8$&az{V=;JR zy_puF4$L$?EMhT?;TpQoR*j16ll`#AS4e96C}yp_aGKkBe?1H|k_;gG-~Xorc<;lI zkB}fB{$c-D2mGA&{rm<*@F5)c3X+6??g~XoEwuzSuch0D@W~P5(2I8v8F$c2$Vw51 zP#YLSBDqtWW^EYBl^QYHF+MA7am6f4DOhwnJM=W9$uvMOsZ%_~?)2C#wb?CkI$7{K zEi)=#|5pFvg^){zK5kpBLjB2kZ+$ZB|L=W|aNwyyb(gC2l7bcpx{E-H@)q6@D6N^xh`{1E%ItF2$eeB_SjI@b2WgTpS1thwg&n`jiIzw^TtXUyB{00($GIq>vbj|}bav}}Q_~wp3>k8!E@hVC;OMUTu|= zAy#vXH*GrUHu7^cNZWe1>y;2(51js9wbu+R3Aa*(wzH9+X0dIsf&gc_x|_LP z>~CF^?(~U}+l~ehe|i>?4eo!xkq&Lk+RR-1duNP#o~>@1x)s&i&u zRaYL@+D&_M|JLI6fHbEr_`U;HgPTh#E3?sB)A$*gqyBgg*ql|a-m*TX5rACbWKCE6 zdeQ`v8m6>g^ugv`p|HY^#1QZrGGUj0^HVDc@{?Q0yhalbBEV{+|HzC^-{&e{5K%z9 z6Bxtnfu1!@Mp+Q&*&~;FOg&*Vm<@4b;{FG0-!UUXX!|)1w}op!B_|7_s~d(+=9Gba zKp8`LaB4D(H=cGcspJ_TjYaOwMb=sGn^gtUVhK!UI~2KKYEE-NC}F>+BEY7IVvy%KRvm00tg!Q`y=er}wpEetX}K@;}(}{s9AzV#q2@ zBy7}->|N?13POrs`;U?(qAG(I$~Gt+Rgw%aNZ_0fs_utVvRJT-7z4!@x36v@=NBX=IqkK{#Kg0w48de@?#Yb4M(Svj5=T+<ONr8-oh7l?Cji@+erqur zFhZ=9|Lk=$`c}v4u`)-!!UI=!9Jo@h&7p4RlS#u! zZ7-prn75JkV?VjptX;@$#`U`{vB!=Z?V`T*FBF>J?vsML7e6@2GbUteMFfX-TUu{2 zLNIG*;dV)8GV8gAgEf#)X3A>p3^CRka1v?~8x^anBhQ=L=LsOl=&pcOYHo98m##ye z34MtGCDK!`ptl?taGMr5q{!zVc? zG00e){TV?`YA9eB;(lA3lXI?RrB4BYQGk?vOmTIUJED=(`_*gtn2DB-t4WW54as*W zb2kD-lWX>lb$+W!VFakki>B^Vc+u$?NLF>)!U%b@Y}gYJ>m2H=^x0=nsE0TF^Yu0h ztgH8-o1%+jCk(+&`|)tTfEVHq0cMeFa{Uz)X$;fCq%Y=SOWML6bYfeP8j5hktL`KK z(18`XrUn&WN9PtFxh&dX`y~YBsmdhi7Kw%tKzM%^VEhdD<_XkulW-x=JN6OPbFI4@ zzDDRN+f=@{0h*MswwOqG6gJ?{NuHx(y-|FUGsxyZ*x0~$MW(eY>vqq4Fh#t7uzw=- zKB?|!0N~!h^AMdLa)oR!Ca#HZ9&Zf)ghuO<^RN)4twRlygHnQG(BE{cDc5E}OF4;xss6gYyV~EcJvJkX)xNWb=@yw!uq0v-sf^rvkp-;?DPWK@*SEw|V;IH=7 zfQqEV_>DjOPT~8X*J|H8=&RnzK4~S7ML~nLX^%s-Vqc^aWy7N$y57qciZGcqy#=zU zs8hcHiI=D$+RB{|62{ohCTiaML6FI4Uhzo5D{Jik@poCs0w7F)*w}F4r0sJ~#u-72 z5bK=ANt=M$Dh5NKnxGsg9NRR?WD-x|FhTwBjd zD<-K>44DB~i%frJOfnzh1R>PRY34kw!6~p3M$JLaD1r@`=h)~Ngks-(gdXh^Q?BTP zZ^Zj5w1AwtuR2$~E7s9iZdF}z%pv1em^V2rM{1tLUY@-+Sc0(9jA|iZWml1;v13=U zHf?y@#mb--7z6$ue>`qjhE~brk$AY-RG90~5wcBbDReXR2)pKg{L>;H(DI`U!MLNQ zY9rFJP@ZQ}jlcMh%WSCo%vf+nd0Gmd*F%KMIe>slCUh)8Ma|;M_I+v#;|ueg9oLg; zq2HtZX%&#F7vdpNlkX?}(C7dGC^y#NB#m4%69RzTNrk%4ol~hSI%>2r6B|*ZkW(*P z;u#s;+faHo{tfy+1L^RzWDi*^JR0iY(zJDB36y_QJ+|E-2x+cY z!V8uLNktH~q>WQZuY!Ap66WP|E!0PA1jK~)^8oJVGbspJs6QL!!-5Qm7 zHYI|_`Actg?vDzdg5{86w@GS$G6ANzff7->6i5pB$T4O}`fZ_;{217Om0gN5zTr12 z5mW{hCzCE-QubjxN$TAE-XgI-8dTY@OZmq`y+y_>dk*(qXF0{nam|q@~i}Utp*k{yurq(DW54hkDT4bbg z=_etM?Nf5W^o-HEu9_?&xEqPg^P^mTxLH8n%u$!mWvFG|{&)jtnU&6|5-`~eaNz0%D1BDo`{ zS1N5(KW5v^2eLdd_%`uaRndF@h0Uo6=M|8?b~KbOLZk{HXEnGmtgZXf2inI*1r%n! zQ3&%RI4r{f&dwW~HwH0Ked9b!k6{>_19H z_Ai>5IChDMY(FfMyG%;30?SQ{iV9KyGru62+Y)~qSQ91}b~}w<&*}R&1c#$O`H@~c z5)2S_eXx}M#N{MuGeQS9@#UJB@;W_j50b}jIhxMPloEFQZdvwxiU^RYycTzgK)-vl3LT&$L8~@68$C8~5_U{cR$E#w*x65(qw&eoL@>%ZHvj zWnEMlSh*(o&oy|J7eJ5OD`ssy%F?*Vp?`Cq;FShyl{ZoKCG5g{y}>usznni#8ki(i zO{w@n{iAj1_ooX@+s*!uW60WcH~*bNOT6z%0jVML5};wVrQp~`Uss_{cO2oud_nNA8^B$?07fJ6?iI)Q zuo9G)O-z)DqstrBqf>B%S05hf-wep0@$BFHKSrkZ{za3D)yVzRz)2{wf8(Wp+xyAM z$rtyx$gi3A=V~V!`Q3;BM0$>*VVtxEM|xDL^gew7ydy3Q6YzD&THRz*q33Ms_D;M- zbCx1Ft#UNB)V3bf`~{ImI72OTp^|bF8?G8#FRj+Biy8ET5#rA3sd|0FR@U(LAJ%w8 zS1%n8Z=Amhw)92rIsof=YVWF4jw&F*j1LG@-`+cR0-~2LqXRH8(Ccne{y#MCPncF64U`0uO zWmi$dlii~1D0rLR{qc|_2M!C$t8^=G7xQY)9!#Y331A|>N)EhmyVdLWL9I3YLJ`7? zZmpqUJB>Ni9oiL)^1IK1UoMyhWE{$9M2M6Xi zPKk7GpMsA6vjZbU7~i+u|J6Nk|Ci!Y3UMUT2|`M;JsNQACdJ%ooo9Yt{?A+0hMpxi znEa~~sxC>rKrU6bd=WRb;%wsH>A#j4{({&1GYSNR57Gama(3)2A;SM>qop}l>Jk2* zn1+C$fIxuwzg3mCU#SOqb-wOCb6mBcYlA5+mt<&_J~sBxc(GQtBFINUO~Mr7<-uu($>P HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ zF^}Ea+#Je`Xy6;#D0FPnSrR%Y!QGA~NA^{oWmW8C<3dr{x6wWQ{4+bzemqV5W$i5~ z=J0jXZ>uZb>DT@0Ks?4QJ{`z?8JWl3$y;2pj#$XP*pv$>$g(z43{YH9KmmR6<#sIn zA`#=0#sgycaBQ^&}Xba!|KaZ8~b30v~nLt z9%#gz_*=~KD{3t^X~l>480*}PhKN=??g`RV|4Ud{Gyyl187MJ}r(#e+H$GEdI+p1s zq_25h;fV)$EPK%Dw-(G=f`yHB-_tttsC!?k7*#!|4a>`Ahj8nm?&n>NRs%jkZW^3-0P_yMP5&*6a26{MRj1&TPF zyE#|c)5uUHzMWx=rMKpuPih*V=S;W3MzIZTw2uTbr}8`p2bm+Z6Sa%vvWAWSf4H)p(+ zSQ8;EvUa#wqWV+9vmIio(%7wukK2SwjUS8Yl%Rq%=~PU)2$Tvm6`1!r3H@U#_|bB0 zmlT1PS3wPB(b&^+@YY7Y$n4l3mV3-X0$>z|gZp6O*Lhzn&?Gad2ZCF;+#95-Y?#y+ z?*l@Yf=a4w{Px=o!N|3~_XKfk&G;fN>Ps&dp2FpA~qD=0~=!NOS@B#XAKKkND>Y{4>rqxrViKD7;?>j8`R` z&G)3FN|dfsxnaI^!d1G%=>AbTTxZWo;n-DLrQ!sj=f~VAOe5zhGS(dgx|!ls62fbX zV@<7Ck^!}R=`Swr?(7w1rY6Nmq~sfXJ?TiKJLn=&SQdEt9$@0 zA+h1Wbwbri0s-stc8yVq;mRa6@kEf8^KXUz&jcic!+avDvvJFa>k0ioWug=T3oPw; zyj4it&0@>_*uI@2=^+T7sL1_!^aJW@Xfo8aC#3^WtQC7fET8b9C} z*u^ue6Ojn z7@(eskJ2+cNnH9~VyfIh<-|7!je~vGy*odz(sk-u$~SrYF3glruZ*W`{sqnS+9=;Z zh{D@MSG91%lr&ua8%$sJF%y1I<|e;EdfJykY8#D$Hc_81n5`$7;1N|b0tvvPLzSg& zn7!5x?T*@rQUKcUhTIjV(rw*5oQYlm5DbEO?60#mohHfbR$3_x#+PZoYi@Vd4`#YgKyTd^!4n{fN~WZDY61sAOm6 zl!d^i*a01QxpWM9Pcl?&{RgO}uq%ErOk5WpECvnfEh!*YP&1Sl)uTN4hg??Vqs~i5 zYsfufz3?{TtwuBN=`0~Qg1PlWH#OGG$ zLLWU17$v``)CE1cds_7kj8mJ{-+l8{DS|zAQ&3|qpOY=!J|kXUhXue9|H>4gqk|n) z-i34GmxLFj8asb3D#D&=ya*a5`C<=o?G;Ev^LV%;l#nH#O=7Nh@z1Do>j6Q;I5S2P zhg|AZbC&|c7}uSJt57s2IK#rSWuararn-02dkptTjo*R{c5o(bWV}_k3BBnKcE|6l zrHl&ezUyw^DmaMdDFVn<8ZY=7_{u{uW&*F<7Al6};lD(u;SB=RpIwI)PTyL=e25h* zGi{lRT}snjbMK~IUx|EGonH+w;iC2Ws)x>=5_{5$m?K z5(*1jMn%u0V1Y%m@`YS3kskt~`1p(rA4uk;Cs!w^KL$w>MH)+cP6|XKr4FfHIATJH z!EGAK4N>1yFR`-zW|w%ByRe#=&kA&#WyUldDGpt!wf-8SFWiSi!5QZL+l7*CE?u!NW1T$<1rdLJ9y3u{_zvHaM?#Rm4 zFk}^1!ffcrB|XK3gsO-s=wr*sUe&^$yN|KxrA)uW00Gu60%pw_+DcUjW`oW<35OC8 zq2{j8SgC}W$?10pvFU83(SL$%C?Kctu3*cs0aa%q!fjn1%xD*Jrm!F3HGR9-C{b?- zHp(cL;ezXMpL@0-1v0DMWddSDNZ5h?q50cOZyVi#bU3&PWE=(hpVn|M4_KYG5h9LffKNRsfhr^=SYiKg?#r&HNMi2@cd4aYL9lw(5_IvQJ zcB*DD()hUSAD^PdA0y|QrVnqwgI@pUXZXjHq3lG2OU&7sPOxxU$Y3&ytj6Qb=2#cC z;{d-{k|xI*bu+Vy&N+}{i(+1me!M;nshY_*&ZQLTGG*xNw#{RpI`3^eGfHck+*38NRgiGahkFethtVY=czJs#)VVc{T65rhU#3Vf?X)8f0)X{w!J3J{z|Sq|%?)nA+zo?$>L9@o`Kc|*7sJo4UjIqu0Ir~S5k^vEH};6K?-dZ0h*m%-1L zf!VC%YbM1~sZOG5zu&Sh>R;(md*_)kGHP)<;OA44W?y53PI%{&@MEN}9TOiqu+1a3AGetBr$c)Ao3OX>iGxmA;^^_alwS818r4Pn&uYe^;z6dh z)68T|AN=hjNdGpF7n>y+RTAZc9&opTXf zqWfK_dUv=mW{p_vN>|(cIkd(+Jy}qnK{IW%X*3!l`^H~FbAHwof+vLZ0C2ZXN1$v7 zgN&R9c8IO`fkR{6U%ERq8FN<1DQYbAN0-pH7EfcA{A&nhT!Be>jj>J!bNRw4NF|}! z1c70_#fkk!VQ!q1h2ff@`yDyrI1`np>*e#D4-Z~*!T^8#o*$V~!8bWQaie?P@KGBb z8rXc!YDL!$3ZgZZ%;-%~0Kn<+d+{xJ$stQbtN8GWV?MCJvzPU|(E(1z;rFw{&6vy) z3*@y%7Tx8rH-p$boS>bLyod?OKRE8v`QSBvGfY6f}_{Zo1q85xoyOF16n~yHx2W ziydUoYLkJmzq|n&2S(O!ZmLdP1(o1Jsq88cX)x3V-BK5eF&0e_0G!5?U7&3KN0`mc zH&Lt)q8!d_VgzxyL^(@xrbp2y)Hmr^V48));RSfE=*Ly0uh9!$3dv-vMZr2URf@l5zdwLjGZB zugY>7_fd_vbV*Qv1?H~>Z%RD%nEeFSI$n$$Lrpc6g>i4+XdBB!%zM$Bhrz5Swzyg? z$~I~n@~-wTBY3-T&pr+|gC+OHDoR?I(eLWa{Z#Rsh>lc~%u0!&R|s0pA*w<7QZ}{i z*AFr~0F3y~f$MGh_HDL7J_1?SxKL}fWIk!$G}`^{)xh*dZ5kK>xGL9>V`WZZg_ z)^Vm)EQK`yfh5KiR(vb&aHvhich z_5o+{d~0+4BEBqYJXyXBIEb1UgVDs;a!N2$9WA>CbfrWryqT25)S4E4)QXBd*3jN} z?phkAt`1rKW?xoLzEm!*IfkH|P>BtECVr0l8-IGk_`UjE#IWkUGqvyS+dMrCnFl<7RCgSMX^qn|Ld_4iYRldO zY&cHhv)GDo8nKvKwAbfyLR%t?9gG?R7~PSD#4D-;?F&!kV59O}neYut5AGbKwy-(U zqyBi=&Mgj|VIo>$u!DHM`R7O?W8-idbePuxiJMH``6c_5L-chKd}=rGC5Gfrc{f!* zWFEBm?l@_b7kzY7%1RQQbG5V<4=ZlkZ%sF74Q|mKOc7Ak7dP2#quiGcZ0_J%7Q?j{ zv9{WFw;n5G-Mn%r#0R;{jLt{yy}9J6rQ(>X9pJ`7Xy?Zv z=lNit#qXaq?CnElK^zF~sG}U5oCpR0T>FH=ZX}Prju$);?;VOhFH8L3I><9P_A|C+ z{;>~dk%9rrq(snjsEm}oUz2FQ21MCG*e?g)?{!&|eg7PX@I+Q0!hL6C7ZVY|g2E>i zr!Ri2@OfEu$)d52+>+cpgh6Z;cLYCZ&EMR0i<^~4&wEu_bdo;y^6}+U2GIQgW$|Od z_jg{O=pU>0-H$P-EOlWyQy#W0r@@_uT}Lg+!d5NxMii7aT1=|qm6BRaWOf{Pws54v zTu=}LR!V(JzI07>QR;;px0+zq=(s+XH-0~rVbmGp8<)7G+Jf)UYs<$Dd>-K+4}CsD zS}KYLmkbRvjwBO3PB%2@j(vOpm)!JABH_E7X^f#V-bzifSaKtE)|QrczC1$sC<<*Y z$hY*3E10fYk`2W09gM_U<2>+r^+ro$Bqh-O7uSa)cfPE_<#^O) zF+5V;-8LaCLKdIh3UB@idQZL`0Vx8`OE#6*1<;8(zi&E7MWB1S%~HAm%axyIHN2vd zA(pJGm_PraB0Aat3~?obWBs?iSc*NhM!{-l_WNCx4@F7I?)5&oI|z{o@JKd1HZ}zf*#}JjK3$ z-;3V*WJZvUcKvSOBH4c7C{fl8oRw8-vfgKQjNiR|KhQ%k6hWNEke(k8w-Ro| z7Y3)FsY-?7%;VT64vRM)l0%&HI~BXkSAOV#F3Bf#|3QLZM%6C{paqLTb3MU-_)`{R zRdfVQ)uX90VCa3ja$8m;cdtxQ*(tNjIfVb%#TCJWeH?o4RY#LWpyZBJHR| z6G-!4W5O^Z8U}e5GfZ!_M{B``ve{r0Z#CXV0x@~X#Pc;}{{ClY_uw^=wWurj0RKnoFzeY` z;gS!PCLCo*c}-hLc?C&wv&>P1hH75=p#;D3{Q8UZ0ctX!b)_@Ur=WCMEuz>pTs$@s z#7bIutL9Pm2FDb~d+H}uBI#pu6R}T{nzpz9U0XLb9lu@=9bTY&PEyFwhHHtXFX~6C zrcg|qqTk(|MIM%KQ<@j=DOjt|V)+8K26wE_CBNnZTg+Z+s}AU|jp6CFoIptG1{J*# z7Ne~l;ba*=bSwAMQ|Vq#fW~+je4PXA91YFzBubNF?ovIOw-$C-8=Ehed{lGD0}(Id zRe4sh8L>&T%{>8o))he}eE;5_ zxoXk3wX?MyNl-xF!q1d$G?=wp^`@09(jU&X zOqZIBI#dN`2PJNdATR3ivtub|nO$dulSaP|e4)WXF1YAGN1pDQIbIjXFG!oC85Mt; zW$eteoL{y^5t4TMRwP$jNPjZFpGsWnGe=jMMqKtcZm9Y9PFZLi*1p@qoKKub^T@2+ zk$@*KYdQ?Z`}<%4ALwk*Yc{(WTf@#u;as(fvE^9{Gk)lWbJP*SjttWofV0s?AB({~l zZI1hZVWFT~W-T?nfMMcnCS4-#6H-MU7H$KxD;yaM46K4Kc@~Q>xzB+QnD_I`b_l3m zo9pRx46b!p?a^&zCDwygqqV3epjs(s0NQI6ARA1n!Yy-qduipxQ& zUAlqRpNjBS+y-ZheD(!R;F}&^V_}b_gqH%tVZ5%%ziO7k^w=es+wZtK^i*vmrWNLMs{oWu_CIov|s1raZiS)>38>pYu;i+-t zI_DiNe6aA4KTZ2P09qPj(0~K4nUq^0+f(2$g`229zkG4jLzRvJUWE0oF1XHL4t3UN zDH466G56sy9hTZoAJB!C3;@F;ONxEk5u6Mv%zdo}Rq`=* zw1n7MOhfNSV48TS989ArIcj`C%Gk8~93~u>)!Yt2b4ZriKj9x2d`H2HQNJ=I>hkDlcZn zqRj>!;oRMTIOu zx|Zfsu~v76T{z7AC(jxj^c@tnJHZtGPsq$DE!8kqvkDx5W?KUJPL+!Ffpwfa+|5z5 zKPCiOPqZZrAG;2%OH0T$W|`C@C*!Z`@Wkop{CTjB&Tk`+{XPnt`ND`Haz;xV`H^RS zyXYtw@WlqTvToi;=mq1<-|IQ(gcOpU%)b#_46|IuWL#4$oYLbqwuk6=Q@xZaJSKVF zZcHs~ZBl;&lF3=+nK; zF`4gSCeZXlwmC_t4I`#PUNQ*)Uv&oGxMALip|sxv^lyVV73tKI7)+QY5=tEMas{vTD-BaTJ^*Y6gq~PU;F5X!sxqiq$iFCo+Uv7m%1w((=e}Vf*=dtds|6 zbX}91!G?C*KG03eHoN}RZS9DJxa&8YwNCT8?JxMXyZqZr13NA|GB{+vG`08C{V(yy zf*Lw$+tYSU_+dI`3n{bMrPdDb`A=Mkg!O=k>1|*3MC8j~- zXL79J4E=U^H=iBLTeHE_OKzE&dws8RNynsSJ!d;`zK?P92U{f)xvD7VQVosrXZrL+ z6lMVdD1YgL;%(1cq{#bS6yXmp|DS@nax#AqqlZhtUQdh<^2vr5`EpAO

LGYq)sa(w9^3-f}NHy=GR4v%t2YZly3m1G@5y`xBh_HGrD%f z>;|Ty?9FiJAc&UVD(StT4I` zfVQwxhE9bXE6r2mKO8Ag7{L^jCyqQb0QqKDPE=RAgqn8q1O^>(z7h5kE(6va%QqRZ zkIOmp(})rLSS(2{=C12e&@!W2=Jel-^_R``0xHO^+t!(oXbcv5yhD4g*$t_F)_5Dl zSVCgesW%;DtYPCFs{G;GX_o?1J3;QQPPv)rWw;>} zJ&KwnUqwNXloNXlK_+pNDfI~hON#SokVJb&ilg8d7^NWo2ZQymCqQMnjfi>ePibjr z-Z@q!?RGN$Mj}Nk){X_vaj6?Mj$>ACR*z|6MsXy3VZ^PFn@yHkPo(>m(iWepn8SC@ z>D2;R4m+gDRZ=SIX!b+CP(qE=JDIUkn=D$aUu+Ihn9-+k1LS3PreQg0N5eWIG@x${nC3v^7caS>1!PKNAY9J z#}E}Q9w#SP>(GY7Hbj&z4$Li6o5taBO|4+F`yS9zq*LJ<38wy4I>HA9(&GYrk4dLajKGww))BWli6Ln1A^Lda@N~p+snkb9C z@OthI+<##vp8!HVQT4Wk(=@zQ{OvZ$EKWS73+JHb)eYLGD-cqi6^|vd$<+IHuc?Nq zW7JertT~3))4?J|28n$I@nAD0c1%9C&IVhEZX~mUsf{efyS(XNG%ch;!N~d7S(Ri7 zb&=BuON95aVA&kLn6&MVU|x}xPMp7xwWxNU1wS+F6#y}1@^wQZB*(&ecT?RnQcI}Y z2*z!^!D?gDUhc@;M^OpLs4mq>C&p{}OWVv<)S9KMars@0JQ{c_ScGsFo3BJ)Irg++ zAWwypJdTO-_{Uh8m(Z!3KL7K{ZZzKHj;{M8I$mV>k znTM?sa0);^=X^cglL`uC+^J)M7nEa$w=VwFULg~%DJllw+7dJAj3{qnP5i3@wr7%y zjXp?Wl2%Th=my&3u?Q$RV6N5tzKMSPTsc#J+-cDDp~qFB6bL2C8AS7Y3PKtVhdhl) zIaLqH5+OnWPWSt(lQCgkN8lczc-V%_iZ{>#1%Z$N*>lu#S;0MZ$T2Y8Kg!U;hAZj> z6S#%$DQ_`Ic%Zr@?}GgjRXg@qTj^17n`65oJ@Wj0u1X8&+UVd|Xs?J+i_^GZ94m6= zUc96~Q`OJvlKB_Lr15*Yw_PUPEr?f?H&00b^-W%26mD)(n(rGGNfK9~2h=C>p-7BZ zFd&*&Msdu{w~(eyFOglwCPH^Rb}O(N7LtS+nnEwDx*pGD?|&9Si~M43a+*L(b0$5A zv`T`(G3xO;I_sx;FwTP21ZlfDpz zOo?}Vlgf~fo{YWm@n_JyD*frOg{XsvBA~|Tn4V6hu>Gd>89-rblfVJUaGvj6X%NZ} z$tFF9sx=4_$*c~G`9iPLGh@=sV+O{D2-t*K@J7H=`V+oVt}8?04WwU3h1BgS!f%1P zFak-T#7`TtLcR=Yz>g0R!ZQrH!YiZOQN=_V-UyncN1Rc18?KY?#O`v#JK+pq0K$~H z3D@v9DZF42R)b9#BBX{^$DOMlJ!g)Gc za{o-1e%F6NvgKq9tC8pV+9S$;9*zNv{J*)n&dmf~anP1)4~N%~h#c(=B#3*KgzhCKhFdgDoWi2IDog{RVyzK|Y`rCUs3T~pJMmdZJy4?b z&s5G=zhf**(t7Y^oC_mcTsE-{^}wiaoUu&?kojLKs>SJPxjcP>{a5CbXCx92AcBE) zHtqP}LjZ{W>PH?Tu(E0X=%{PBMW@F_?#7b&#!^q`<-5$ur+-q6 z{dn=(^UZw6*3-XM_(=@<1_*i&XM4=0t5u!gm6 z{UlmNGPKgO_;e;q9|#esq~Sq`<}%d{+sRmhvsA{5i*91=tub>OZZ%)xUA#4q$dDyy z1`w4%?OPLg3JeZb#cqSMO?*Xn%|-FCcuH2i2fn_{IFusub6;NQdN|7TD1N?%E8*g? z$apAt@cEe!I%jB=*q$p_3=t_5R0ph%{qaq+QDg!c99Y!Xa!&oDZOeis_ot)gNXr{l zdY$|So2Qed2Y7KMNBrS^E169kG%h<+z{Z_p_;shB!uY)>yAVcK=&!bg`lVg)4T1|7 z0}7FpfydVH4F87K@c!nEG+WGKm{Ouo)Slpl;#qcEIQ0zdMfLA#;dBxYw;p;KoVv6| z3_D5&7rJdG12CnDSvZUW?$UC6^UVSW^|vw|o-_4bz)(w5(3AiVhpeT(|=f#x_}E?s#qHZF#xA6AF_ujl$G z-jHD%q(d2}v2PhXx&6YWps~m(^+RXl91Q#xRRJBhjKl$FG4bk);|ag;ieUZ&!Ii3$ z(iGz1+0m7#g5>ASldBbNZL=ZHh=tmmJt$!71; zIML2GhEz1pg@1rQN(M^_691wAGkJ@Pga_05WuQ6! zG5RkGY2^`@(H~pp7&Ga+Pwh3L!Njj!-rc;^bTIfo5hP@H##1X8xUZJckrx>id`bAd3QUx9GuomqBYZ!uN1-&o zvTxC?;p8vL67&fW8fw(YOqt>L@bdLrEF*3OgYe$4n4{ zEB40LiU#6-0@5jdN`0w}N0qi@c0~oT2FP z)LNk&a82my?jv(tQpiMi$TK_L@lub#lsM$R{Dk?Ya@%%%huZkct~tSWM714c!45k}-ZLVA-bVM`>|_ZBbW_m-7| z3U%xrAhi}n?T(2F{_n4EZ10inkIFl#y09?7$uwBoJgqY8vylwev)fDOn;>0R!aEnV zBz%j0Mqpx~EZU3q@%+oV7;}|vt7$~ou@faEIq{p?FY$XXg&6*K)b_LP=}gi9`Bij3 zN`zEo|B6*|-;>S`rNa^BKRDbDAk>X#MsR`EvL>6bqU@SaDDs z8>bu@3YdRaWs*Te@G-UHjU%F~kTHw5(0PVJ+pwh#ha2u;DB+UMo@A5UYIl#5rtBV- zGX_hIpw}3C@H*Us(Cc-d#-gNrG#w$(9+S=GxO>3SR`SE2fHZ2KrDc#_C^$jI>Y}#; zMwY=R6@+dWi~0RXw(c@3GZ&%~9K(q&ee0Zw;pwL`E_tZak-#8^_b)Dpyi73^he?xV zXJ08&wh5-M&}qy4f7!D&=E)puDD(Nmg1d_(j`4LvxM5x_huNg-pGG%9rYqO6mImyJ@}*3Y>^3OvcnTG%EV1) zq_Ap?Z!Iw__7#D=pOWnQN$gB!Mr0!9yx|g<4icJh{cFOu3B8}&RiYm+Mb;VEK``LK zL(NcpcTiGieOIssSjr?ob}^``nNf&UcJhXyncO9m{6gD$kqSD`S69(aF8dkWz5>!9 zBLe4Sib7Hs2x_L2Ls6Ish$MGVKrGt5+_2zCyP1byaCg3upo+-I}R4&$m)8 zQ7|jc1Z^VWggpuQj*cP;>Zo9LS!VSzrqmZczaf;u`d0J(f%Z9r%An@s!e>n9%y=n!IZ_tVGu{Jmsbp}Fk%HJIU?a+-~bjfLTuH|JExA8EROowzr zqW9{YyZhR0a4clRK>1I4Ncx&WER~{iE;F^$T7K%X@3PGOA%6#Z%p3TS^&M;Dnjw@i z^o!$9nhcsmcHcY4?4j9+ofL_CWsZ4Hcch(rjsGfGD(nsH>w}^ERqGnz%iGj0j{g}h z7wMkJ-2Z2~eS>2!i}0~B63i;>SyFJU2+>VCS^AxaDOx%g6-t0eM^P<3+*z`ztvOqrG3)&#$K?& z_Y0wbWID47@cU`E1A6A&!`aZk0ZE@z-h#l1NqX2#`$Uev2gepW`rf8*!=rD5&;Jb{ zl08rU>dPo=K%-1Ao1~G-@4ve~y5#9E8x;TE0k5d^TC(=Zc>mwjW^c=+U-<9}b0ku~}gj z3sbW>R2M6DR!g#NUP;nxo>)@7*=RP{U18SDop6b2&PHce^&h97@xx3t+VK+!keE#} z;(Uf&89as9k8{$nkLbuB!-d7TP`_VJpL^Xs8OKB~ri$YUbW8fch64}7|0EWoT(TRj{ z*GT<7Y<7DsrCi79ZsM)z#c(!nNOGySOCkY1fAuQOq12&iUVC!a`#O;dBLf=d?&4*B zI~LgAO7E0qxK(uRTM;IgJ}+z^gD+bi-6I!3x{r9`l~%8TRP%UE0V8E*Sz>Nl1NVG<<7(wDHZ+HcOkQm$O&k+vyx)y)x{Pz!U8hS$*m zByc0h6BUI*BOpuL==P+H|Hx%`>7!W+1H!l9vi&)`V zyn2o9{z=lc+VX*!Vh~SF=)L}Z40XeG>LF6cP^b+R$NxSeUqbK^Q*UTalKzP8X%{9@RSCXm_NhF>{=S2 zi}ezam_^P`S!!-cyEW9y7DBbK93roz@Raccy*v}?mKXScU9E_4g;hBU7}zSofAFda zKYEe?{{I54 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138c..e2847c820 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf133..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e46..9b42019c7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## From 7ed3ce92ce25f5c6b51eadf824eccb8181426a40 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Tue, 26 Nov 2024 13:18:28 +0700 Subject: [PATCH 64/88] increase gradle build memory --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0716ad888..2f9a97595 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1G -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx2G -XX:MaxMetaspaceSize=1024m -XX:ThreadStackSize=4096 -XX:CompilerThreadStackSize=4096 -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError org.gradle.caching=false From 822517899546f19cd04ac40952535e47eacfbe9e Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Sat, 30 Nov 2024 06:35:37 +0700 Subject: [PATCH 65/88] fix: JSon functions with Column parameters - fixes #1753 Signed-off-by: Andreas Reichel --- build.gradle | 6 +- .../expression/JsonAggregateFunction.java | 11 +- .../expression/JsonKeyValuePair.java | 6 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 193 ++++++++++-------- .../expression/JsonFunctionTest.java | 13 ++ 5 files changed, 138 insertions(+), 91 deletions(-) diff --git a/build.gradle b/build.gradle index 66d4d27f9..9816e74a4 100644 --- a/build.gradle +++ b/build.gradle @@ -95,9 +95,9 @@ dependencies { testImplementation 'com.h2database:h2:+' // for JaCoCo Reports - testImplementation 'org.junit.jupiter:junit-jupiter-api:+' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:+' - testImplementation 'org.junit.jupiter:junit-jupiter-params:+' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.3' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter testImplementation 'org.mockito:mockito-junit-jupiter:+' diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java index 13e3ba296..20bfa272e 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonAggregateFunction.java @@ -23,7 +23,7 @@ public class JsonAggregateFunction extends FilterOverImpl implements Expression private JsonFunctionType functionType; private Expression expression = null; private boolean usingKeyKeyword = false; - private String key; + private Object key; private boolean usingValueKeyword = false; private Object value; @@ -112,15 +112,15 @@ public JsonAggregateFunction withUsingKeyKeyword(boolean usingKeyKeyword) { return this; } - public String getKey() { + public Object getKey() { return key; } - public void setKey(String key) { + public void setKey(Object key) { this.key = key; } - public JsonAggregateFunction withKey(String key) { + public JsonAggregateFunction withKey(Object key) { this.setKey(key); return this; } @@ -188,6 +188,7 @@ public T accept(ExpressionVisitor expressionVisitor, S context) { public StringBuilder append(StringBuilder builder) { switch (functionType) { case OBJECT: + case MYSQL_OBJECT: appendObject(builder); break; case ARRAY: @@ -209,6 +210,8 @@ public StringBuilder appendObject(StringBuilder builder) { builder.append("KEY "); } builder.append(key).append(" VALUE ").append(value); + } else if (functionType == JsonFunctionType.MYSQL_OBJECT) { + builder.append(key).append(", ").append(value); } else { builder.append(key).append(":").append(value); } diff --git a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java index f1119071d..82c8a355a 100644 --- a/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java +++ b/src/main/java/net/sf/jsqlparser/expression/JsonKeyValuePair.java @@ -18,13 +18,13 @@ */ public class JsonKeyValuePair implements Serializable { - private final String key; + private final Object key; private final Object value; private boolean usingKeyKeyword = false; private boolean usingValueKeyword = false; private boolean usingFormatJson = false; - public JsonKeyValuePair(String key, Object value, boolean usingKeyKeyword, + public JsonKeyValuePair(Object key, Object value, boolean usingKeyKeyword, boolean usingValueKeyword) { this.key = Objects.requireNonNull(key, "The KEY of the Pair must not be null"); this.value = value; @@ -93,7 +93,7 @@ public boolean equals(Object obj) { return Objects.equals(this.key, other.key); } - public String getKey() { + public Object getKey() { return key; } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 4d26413b5..ebfa58af6 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5193,101 +5193,109 @@ JsonFunction JsonFunction() : { Column column = null; JsonKeyValuePair keyValuePair; + Object key = null; Expression expression = null; JsonFunctionExpression functionExpression; } { ( - ( - ( - "(" { result.setType( JsonFunctionType.OBJECT ); } - ( + ( + "(" { result.setType( JsonFunctionType.OBJECT ); } + ( + // SQL2016 compliant Syntax + LOOKAHEAD(2) ( + LOOKAHEAD(2) ( + "KEY" { usingKeyKeyword = true; } ( keyToken = { key = keyToken.image; } | key = Column() ) + ) + | + keyToken = { key = keyToken.image; } + | + key = Column() + ) + + ( LOOKAHEAD(2) + ( ":" | "," { result.setType( JsonFunctionType.POSTGRES_OBJECT ); } | "VALUE" { usingValueKeyword = true; } ) ( - // SQL2016 compliant Syntax - ( - [ "KEY" { usingKeyKeyword = true; } ] - keyToken = + expression = Expression() + ) + [ { usingFormatJason = true; } ] + )? + { + if (expression !=null) { + keyValuePair = new JsonKeyValuePair( key, expression, usingKeyKeyword, usingValueKeyword ); + keyValuePair.setUsingFormatJson( usingFormatJason ); + result.add(keyValuePair); + } else { + result.setType( JsonFunctionType.POSTGRES_OBJECT ); + keyValuePair = new JsonKeyValuePair( key, null, false, false ); + result.add(keyValuePair); + } + } - ( LOOKAHEAD(2) - ( ":" | "," { result.setType( JsonFunctionType.POSTGRES_OBJECT ); } | "VALUE" { usingValueKeyword = true; } ) - ( - expression = Expression() - ) - [ { usingFormatJason = true; } ] - )? { - if (expression !=null) { - keyValuePair = new JsonKeyValuePair( keyToken.image, expression, usingKeyKeyword, usingValueKeyword ); - keyValuePair.setUsingFormatJson( usingFormatJason ); - result.add(keyValuePair); - } else { - result.setType( JsonFunctionType.POSTGRES_OBJECT ); - keyValuePair = new JsonKeyValuePair( keyToken.image, null, false, false ); - result.add(keyValuePair); - } - } - - // --- Next Elements - ( "," { usingKeyKeyword = false; usingValueKeyword = false; } - [ "KEY" { usingKeyKeyword = true; } ] - keyToken = - ( ":" | "," { result.setType( JsonFunctionType.MYSQL_OBJECT ); } | "VALUE" { usingValueKeyword = true; } ) - ( - expression = Expression() { keyValuePair = new JsonKeyValuePair( keyToken.image, expression, usingKeyKeyword, usingValueKeyword ); result.add(keyValuePair); } - ) - [ { keyValuePair.setUsingFormatJson( true ); } ] - )* + // --- Next Elements + ( "," { usingKeyKeyword = false; usingValueKeyword = false; } + ( + LOOKAHEAD(2) ( + "KEY" { usingKeyKeyword = true; } ( keyToken = { key = keyToken.image; } | key = Column() ) ) - )? + | + keyToken = { key = keyToken.image; } + | + key = Column() + ) + ( ":" | "," { result.setType( JsonFunctionType.MYSQL_OBJECT ); } | "VALUE" { usingValueKeyword = true; } ) + expression = Expression() { keyValuePair = new JsonKeyValuePair( key, expression, usingKeyKeyword, usingValueKeyword ); result.add(keyValuePair); } + [ { keyValuePair.setUsingFormatJson( true ); } ] + )* + )? - [ - ( - { result.setOnNullType( JsonAggregateOnNullType.NULL ); } - ) - | - ( - { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } - ) - ] + [ + ( + { result.setOnNullType( JsonAggregateOnNullType.NULL ); } + ) + | + ( + { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } + ) + ] - [ - ( - { result.setUniqueKeysType( JsonAggregateUniqueKeysType.WITH ); } - ) - | - ( - { result.setUniqueKeysType( JsonAggregateUniqueKeysType.WITHOUT ); } - ) - ] + [ + ( + { result.setUniqueKeysType( JsonAggregateUniqueKeysType.WITH ); } + ) + | + ( + { result.setUniqueKeysType( JsonAggregateUniqueKeysType.WITHOUT ); } + ) + ] + ")" + ) + | + ( + { result.setType( JsonFunctionType.ARRAY ); } + "(" + ( + LOOKAHEAD(2) ( + { result.setOnNullType( JsonAggregateOnNullType.NULL ); } ) - ")" - ) - | - ( - { result.setType( JsonFunctionType.ARRAY ); } - "(" + | + expression=Expression() { functionExpression = new JsonFunctionExpression( expression ); result.add( functionExpression ); } + + [ LOOKAHEAD(2) { functionExpression.setUsingFormatJson( true ); } ] ( - LOOKAHEAD(2) ( - { result.setOnNullType( JsonAggregateOnNullType.NULL ); } - ) - | + "," expression=Expression() { functionExpression = new JsonFunctionExpression( expression ); result.add( functionExpression ); } - [ LOOKAHEAD(2) { functionExpression.setUsingFormatJson( true ); } ] - ( - "," - expression=Expression() { functionExpression = new JsonFunctionExpression( expression ); result.add( functionExpression ); } - [ LOOKAHEAD(2) { functionExpression.setUsingFormatJson( true ); } ] - )* )* + )* - [ - { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } - ] + [ + { result.setOnNullType( JsonAggregateOnNullType.ABSENT ); } + ] - ")" - ) - ) + ")" + ) ) { @@ -5298,6 +5306,7 @@ JsonFunction JsonFunction() : { JsonAggregateFunction JsonAggregateFunction() : { JsonAggregateFunction result = new JsonAggregateFunction(); Token token; + Object key; Expression expression; List expressionOrderByList = null; @@ -5312,10 +5321,32 @@ JsonAggregateFunction JsonAggregateFunction() : { ( ( "(" { result.setType( JsonFunctionType.OBJECT ); } - [ "KEY" { result.setUsingKeyKeyword( true ); } ] - ( token = | token = | token = | token = | token = | token = | token = ) { result.setKey( token.image ); } - ( ":" | "VALUE" {result.setUsingValueKeyword( true ); } ) - ( token = | token = ) { result.setValue( token.image ); } + ( + LOOKAHEAD(2) ( + "KEY" { result.setUsingKeyKeyword( true ); } + ( + ( token = | token = | token = | token = | token = ) + { + key = token.image; + } + | + key = Column() + ) + ) + | + ( token = | token = | token = | token = | token = ) + { + key = token.image; + } + | + key = Column() + ) + { + result.setKey( key ); + } + + ( ":" | "," { result.setType( JsonFunctionType.MYSQL_OBJECT ); } | "VALUE" {result.setUsingValueKeyword( true ); } ) + expression = Expression() { result.setValue( expression ); } [ { result.setUsingFormatJson( true ); } ] diff --git a/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java b/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java index 1ce33d52e..ef1335e6c 100644 --- a/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/JsonFunctionTest.java @@ -131,6 +131,10 @@ public void testArrayAgg() throws JSQLParserException { @Test public void testObject() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "WITH Items AS (SELECT 'hello' AS key, 'world' AS value)\n" + + "SELECT JSON_OBJECT(key, value) AS json_data FROM Items", + true); TestUtils.assertSqlCanBeParsedAndDeparsed( "SELECT JSON_OBJECT( KEY 'foo' VALUE bar, KEY 'foo' VALUE bar) FROM dual ", true); TestUtils.assertSqlCanBeParsedAndDeparsed( @@ -280,4 +284,13 @@ public void testJavaMethods() throws JSQLParserException { Assertions.assertEquals(JsonAggregateUniqueKeysType.WITH, jsonFunction .withUniqueKeysType(JsonAggregateUniqueKeysType.WITH).getUniqueKeysType()); } + + @Test + void testIssue1753JSonObjectAggWithColumns() throws JSQLParserException { + String sqlStr = "SELECT JSON_OBJECTAGG( KEY q.foo VALUE q.bar) FROM dual"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr); + + sqlStr = "SELECT JSON_OBJECTAGG(foo, bar) FROM dual"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr); + } } From 92bbd90e8755d8d728c7083fadc1b2e3d6bd4509 Mon Sep 17 00:00:00 2001 From: Andreas Reichel Date: Wed, 4 Dec 2024 07:22:52 +0700 Subject: [PATCH 66/88] feat: add JSON to the list of data types Signed-off-by: Andreas Reichel --- src/main/java/net/sf/jsqlparser/expression/CastExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java index 8325e493a..f06682068 100644 --- a/src/main/java/net/sf/jsqlparser/expression/CastExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/CastExpression.java @@ -273,7 +273,7 @@ public boolean isText() { } public enum DataType { - ARRAY, BIT, BITSTRING, BLOB, BYTEA, BINARY, VARBINARY, BYTES, BOOLEAN, BOOL, ENUM, INTERVAL, LIST, MAP, STRUCT, TINYINT, INT1, SMALLINT, INT2, SHORT, INTEGER, INT4, INT, SIGNED, BIGINT, INT8, LONG, HUGEINT, UTINYINT, USMALLINT, UINTEGER, UBIGINT, UHUGEINT, DECIMAL, NUMBER, NUMERIC, REAL, FLOAT4, FLOAT, DOUBLE, DOUBLE_PRECISION, FLOAT8, FLOAT64, UUID, VARCHAR, NVARCHAR, CHAR, NCHAR, BPCHAR, STRING, TEXT, CLOB, DATE, TIME, TIME_WITHOUT_TIME_ZONE, TIMETZ, TIME_WITH_TIME_ZONE, TIMESTAMP_NS, TIMESTAMP, TIMESTAMP_WITHOUT_TIME_ZONE, DATETIME, TIMESTAMP_MS, TIMESTAMP_S, TIMESTAMPTZ, TIMESTAMP_WITH_TIME_ZONE, UNKNOWN, VARBYTE; + ARRAY, BIT, BITSTRING, BLOB, BYTEA, BINARY, VARBINARY, BYTES, BOOLEAN, BOOL, ENUM, INTERVAL, LIST, MAP, STRUCT, TINYINT, INT1, SMALLINT, INT2, SHORT, INTEGER, INT4, INT, SIGNED, BIGINT, INT8, LONG, HUGEINT, UTINYINT, USMALLINT, UINTEGER, UBIGINT, UHUGEINT, DECIMAL, NUMBER, NUMERIC, REAL, FLOAT4, FLOAT, DOUBLE, DOUBLE_PRECISION, FLOAT8, FLOAT64, UUID, VARCHAR, NVARCHAR, CHAR, NCHAR, BPCHAR, STRING, TEXT, CLOB, DATE, TIME, TIME_WITHOUT_TIME_ZONE, TIMETZ, TIME_WITH_TIME_ZONE, TIMESTAMP_NS, TIMESTAMP, TIMESTAMP_WITHOUT_TIME_ZONE, DATETIME, TIMESTAMP_MS, TIMESTAMP_S, TIMESTAMPTZ, TIMESTAMP_WITH_TIME_ZONE, UNKNOWN, VARBYTE, JSON; public static DataType from(String typeStr) { Matcher matcher = PATTERN.matcher(typeStr.trim().replaceAll("\\s+", "_").toUpperCase()); From b0b0f4d6178918bef1d7d52fc99ae3ee6ad096bd Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sat, 7 Dec 2024 10:13:15 +0700 Subject: [PATCH 67/88] feat: functions with extra keywords, like BigQuery Timeseries functions - fixes #2120 Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../net/sf/jsqlparser/expression/Function.java | 15 +++++++++++++++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 4 +++- .../statement/select/BigQueryTest.java | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/Function.java b/src/main/java/net/sf/jsqlparser/expression/Function.java index bdf0bb08b..e3a5156ec 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Function.java +++ b/src/main/java/net/sf/jsqlparser/expression/Function.java @@ -39,6 +39,7 @@ public class Function extends ASTNodeAccessImpl implements Expression { private Limit limit = null; private KeepExpression keep = null; private String onOverflowTruncate = null; + private String extraKeyword = null; public Function() {} @@ -255,6 +256,15 @@ public void setKeep(KeepExpression keep) { this.keep = keep; } + public String getExtraKeyword() { + return extraKeyword; + } + + public Function setExtraKeyword(String extraKeyword) { + this.extraKeyword = extraKeyword; + return this; + } + @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public String toString() { @@ -272,6 +282,11 @@ public String toString() { if (isAllColumns()) { b.append("ALL "); } + + if (extraKeyword != null) { + b.append(extraKeyword).append(" "); + } + b.append(parameters); if (havingClause != null) { diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index ebfa58af6..07748213c 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5903,6 +5903,7 @@ Function InternalFunction(boolean escaped): String onOverflowTruncate = null; Token overflowToken = null; Limit limit; + Token extraKeywordToken; } { [ LOOKAHEAD(2) prefixToken = ] @@ -5922,7 +5923,8 @@ Function InternalFunction(boolean escaped): | LOOKAHEAD( AllTableColumns() ) expr=AllTableColumns() { expressionList = new ExpressionList(expr); } | - LOOKAHEAD(3) expressionList=ExpressionList() + LOOKAHEAD(3) [ LOOKAHEAD(2) extraKeywordToken = { retval.setExtraKeyword(extraKeywordToken.image); } ] + expressionList=ExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/LISTAGG.html diff --git a/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java b/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java index d4dbd74b0..81a321784 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/BigQueryTest.java @@ -11,6 +11,7 @@ import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -92,4 +93,21 @@ void testAsValue() throws JSQLParserException { String sqlStr = "SELECT AS VALUE STRUCT(1 AS a, 2 AS b) xyz"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + void testTimeSeriesFunction() throws JSQLParserException { + String sqlStr = "with raw_data as (\n" + + " select timestamp('2024-12-01') zetime\n" + + " union all \n" + + " select timestamp('2024-12-04')\n" + + " )\n" + + "select zetime from GAP_FILL(\n" + + " TABLE raw_data,\n" + + " ts_column => 'zetime',\n" + + " bucket_width => INTERVAL 4 HOUR\n" + + ")"; + PlainSelect select = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + TableFunction function = select.getFromItem(TableFunction.class); + Assertions.assertEquals("TABLE", function.getFunction().getExtraKeyword()); + } } From e8ff9fb98d299dce82922291ec347a1e5e19e356 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sun, 8 Dec 2024 15:27:44 +0700 Subject: [PATCH 68/88] feat: syntax sugar for table functions Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../java/net/sf/jsqlparser/expression/Function.java | 3 ++- .../sf/jsqlparser/statement/select/TableFunction.java | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/Function.java b/src/main/java/net/sf/jsqlparser/expression/Function.java index e3a5156ec..d8ef6cb2e 100644 --- a/src/main/java/net/sf/jsqlparser/expression/Function.java +++ b/src/main/java/net/sf/jsqlparser/expression/Function.java @@ -17,6 +17,7 @@ import net.sf.jsqlparser.statement.select.OrderByElement; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -44,7 +45,7 @@ public class Function extends ASTNodeAccessImpl implements Expression { public Function() {} public Function(String name, Expression... parameters) { - this.nameparts = Arrays.asList(name); + this.nameparts = Collections.singletonList(name); this.parameters = new ExpressionList<>(parameters); } diff --git a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java index 4f51179fc..7d3a5242a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/TableFunction.java @@ -10,6 +10,7 @@ package net.sf.jsqlparser.statement.select; import net.sf.jsqlparser.expression.Alias; +import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Function; @SuppressWarnings({"PMD.UncommentedEmptyMethodBody"}) @@ -29,6 +30,15 @@ public TableFunction(String prefix, Function function) { this.function = function; } + public TableFunction(String prefix, String name, Expression... parameters) { + this.prefix = prefix; + this.function = new Function(name, parameters); + } + + public TableFunction(String name, Expression... parameters) { + this(null, name, parameters); + } + public Function getFunction() { return function; } From 469190d03709254048d2fd2a40441e02b29fe7ba Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sun, 8 Dec 2024 15:39:53 +0700 Subject: [PATCH 69/88] fix: Alias of the ParenthesedSelect when FromItem is a TableFunction Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../net/sf/jsqlparser/statement/select/ParenthesedSelect.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java index 2e09a429f..7fa729e37 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/ParenthesedSelect.java @@ -75,6 +75,9 @@ private static Alias getAliasFromItem(FromItem fromItem) { if (fromItem instanceof Table && fromItem.getAlias() == null) { Table t = (Table) fromItem; return new Alias(t.getName(), true); + } else if (fromItem instanceof TableFunction && fromItem.getAlias() == null) { + TableFunction t = (TableFunction) fromItem; + return new Alias(t.getName(), true); } else { return new Alias(fromItem.getAlias().getName(), true); } From e122bcf7d7a01cf78ffecbd4fb5e22b5a5a91cb5 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sun, 8 Dec 2024 16:12:18 +0700 Subject: [PATCH 70/88] fix: De-parse `TableFunction` Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- .../sf/jsqlparser/util/deparser/ExpressionDeParser.java | 5 +++++ .../net/sf/jsqlparser/util/deparser/SelectDeParser.java | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) 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 dc0c2b21f..d0f175e78 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -833,6 +833,11 @@ public StringBuilder visit(Function function, S context) { } else if (function.isUnique()) { buffer.append("UNIQUE "); } + + if (function.getExtraKeyword() != null) { + buffer.append(function.getExtraKeyword()).append(" "); + } + if (function.getNamedParameters() != null) { function.getNamedParameters().accept(this, context); } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index 9fb1673e9..a80af55ad 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -704,7 +704,14 @@ public StringBuilder visit(TableStatement tableStatement, S context) { @Override public StringBuilder visit(TableFunction tableFunction, S context) { - buffer.append(tableFunction.toString()); + if (tableFunction.getPrefix() != null) { + buffer.append(tableFunction.getPrefix()).append(" "); + } + tableFunction.getFunction().accept(this.expressionVisitor, context); + + if (tableFunction.getAlias() != null) { + buffer.append(tableFunction.getAlias()); + } return buffer; } From 18c1a2c63d9719b8a622db874711b56de995aa3b Mon Sep 17 00:00:00 2001 From: Minjae Lee Date: Mon, 9 Dec 2024 18:09:37 +0900 Subject: [PATCH 71/88] feat mysql alter force,engine,algorithm,lock (#2121) Co-authored-by: mj-db --- .../statement/alter/AlterExpression.java | 36 +++++++++++++++ .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 23 +++++----- .../jsqlparser/statement/alter/AlterTest.java | 44 ++++++++++++++++++- 4 files changed, 89 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 4fd1f4209..3a8f25910 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -61,6 +61,8 @@ public class AlterExpression implements Serializable { private String characterSet; private String collation; private String lockOption; + private String algorithmOption; + private String engineOption; private String commentText; private String tableOption; @@ -438,6 +440,22 @@ public void setLockOption(String lockOption) { this.lockOption = lockOption; } + public String getAlgorithmOption() { + return algorithmOption; + } + + public void setAlgorithmOption(String algorithmOption) { + this.algorithmOption = algorithmOption; + } + + public String getEngineOption() { + return engineOption; + } + + public void setEngineOption(String engineOption) { + this.engineOption = engineOption; + } + public boolean getUseEqual() { return useEqual; } @@ -478,6 +496,24 @@ public String toString() { b.append(optionalSpecifier); } else if (operation == AlterOperation.SET_TABLE_OPTION) { b.append(tableOption); + } else if (operation == AlterOperation.ENGINE) { + b.append("ENGINE "); + if (useEqual) { + b.append("= "); + } + b.append(engineOption); + } else if (operation == AlterOperation.ALGORITHM) { + b.append("ALGORITHM "); + if (useEqual) { + b.append("= "); + } + b.append(algorithmOption); + } else if (operation == AlterOperation.LOCK) { + b.append("LOCK "); + if (useEqual) { + b.append("= "); + } + b.append(lockOption); } else if (getOldIndex() != null) { b.append("RENAME"); switch (operation) { diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index fceeb9cae..053f6892a 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, TRUNCATE_PARTITION, SET_TABLE_OPTION, LOCK; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, TRUNCATE_PARTITION, SET_TABLE_OPTION, ENGINE, FORCE, LOCK; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 07748213c..cfe72baca 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -7167,7 +7167,6 @@ AlterExpression AlterExpression(): ( ( { alterExp.setOperation(AlterOperation.ADD); - System.out.println("test"); } | { alterExp.setOperation(AlterOperation.ALTER); } @@ -7438,12 +7437,16 @@ AlterExpression AlterExpression(): ) ) | + ( + { alterExp.setOperation(AlterOperation.FORCE); } + ) + | ( { alterExp.setOperation(AlterOperation.ALGORITHM); } ["=" { alterExp.setUseEqual(true);} ] - sk3 = RelObjectName() {alterExp.addParameters(sk3); } + sk3 = RelObjectName() {alterExp.setAlgorithmOption(sk3); } ) | ( @@ -7453,6 +7456,11 @@ AlterExpression AlterExpression(): ["=" { alterExp.setUseEqual(true);} ] sk3 = RelObjectName() {alterExp.setLockOption(sk3); } ) + | + ( {alterExp.setOperation(AlterOperation.ENGINE);} + ["=" { alterExp.setUseEqual(true);} ] + sk3 = RelObjectName() {alterExp.setEngineOption(sk3); } + ) | LOOKAHEAD(2) { alterExp.setOperation(AlterOperation.RENAME); } [ { alterExp.hasColumn(true);} ] ( tk= | tk= ) { alterExp.setColOldName(tk.image); } @@ -7516,17 +7524,6 @@ AlterExpression AlterExpression(): } ) | - ( {alterExp.setOperation(AlterOperation.SET_TABLE_OPTION);} - ["=" { alterExp.setUseEqual(true);} ] - tk= { - if (alterExp.getUseEqual()) { - alterExp.setTableOption("ENGINE = " + tk.image); - } else { - alterExp.setTableOption("ENGINE " + tk.image); - } - } - ) - | LOOKAHEAD(2) ( (( {alterExp.setOperation(AlterOperation.RENAME_INDEX);} | {alterExp.setOperation(AlterOperation.RENAME_KEY);}) diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 03ec3e85e..28af60b71 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1354,8 +1354,48 @@ public void testIssue2114AlterTableEngine() throws JSQLParserException { assertEquals(1, alterExpressions.size()); AlterExpression engineExp = alterExpressions.get(0); - assertEquals(AlterOperation.SET_TABLE_OPTION, engineExp.getOperation()); - assertEquals(engineExp.getTableOption(), "ENGINE = InnoDB"); + assertEquals(AlterOperation.ENGINE, engineExp.getOperation()); + assertEquals(engineExp.getEngineOption(), "InnoDB"); assertSqlCanBeParsedAndDeparsed(sql); } + + @Test + public void testIssue2118AlterTableForceAndEngine() throws JSQLParserException { + String sql1 = "ALTER TABLE my_table FORCE"; + Statement stmt1 = CCJSqlParserUtil.parse(sql1); + assertTrue(stmt1 instanceof Alter); + Alter alter1 = (Alter) stmt1; + List alterExpressions1 = alter1.getAlterExpressions(); + assertNotNull(alterExpressions1); + assertEquals(1, alterExpressions1.size()); + + AlterExpression forceExp = alterExpressions1.get(0); + assertEquals(AlterOperation.FORCE, forceExp.getOperation()); + assertSqlCanBeParsedAndDeparsed(sql1); + + String sql2 = "ALTER TABLE tbl_name FORCE, ENGINE=InnoDB, ALGORITHM=INPLACE, LOCK=NONE"; + Statement stmt2 = CCJSqlParserUtil.parse(sql2); + assertTrue(stmt2 instanceof Alter); + Alter alter2 = (Alter) stmt2; + List alterExpressions2 = alter2.getAlterExpressions(); + assertNotNull(alterExpressions2); + assertEquals(4, alterExpressions2.size()); + + AlterExpression forceExp2 = alterExpressions2.get(0); + assertEquals(AlterOperation.FORCE, forceExp2.getOperation()); + + AlterExpression engineExp = alterExpressions2.get(1); + assertEquals(AlterOperation.ENGINE, engineExp.getOperation()); + assertEquals(engineExp.getEngineOption(), "InnoDB"); + + AlterExpression algorithmExp = alterExpressions2.get(2); + assertEquals(AlterOperation.ALGORITHM, algorithmExp.getOperation()); + assertEquals("INPLACE", algorithmExp.getAlgorithmOption()); + + AlterExpression lockExp = alterExpressions2.get(3); + assertEquals(AlterOperation.LOCK, lockExp.getOperation()); + assertEquals("NONE", lockExp.getLockOption()); + + assertSqlCanBeParsedAndDeparsed(sql2); + } } From 8f8439e485a412e6b7046bf2de28c44db0ca7a24 Mon Sep 17 00:00:00 2001 From: Cedric Dandoy <153516516+cptnricard@users.noreply.github.com> Date: Sun, 15 Dec 2024 09:12:26 -0600 Subject: [PATCH 72/88] fix: [FEATURE] TablesNamesFinder does not support CREATE VIEW #2123 (#2124) --- .../java/net/sf/jsqlparser/util/TablesNamesFinder.java | 7 +++++-- .../net/sf/jsqlparser/util/TablesNamesFinderTest.java | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 122d5cf2e..3e8bc9e1b 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -1151,8 +1151,11 @@ public void visit(CreateTable createTable) { } @Override - public Void visit(CreateView createView, S context) { - throwUnsupported(createView); + public Void visit(CreateView create, S context) { + visit(create.getView(), null); + if (create.getSelect() != null) { + create.getSelect().accept((SelectVisitor) this, context); + } return null; } diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index 66304b1da..111fba75a 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -152,12 +152,19 @@ public void testInsertSelect() throws Exception { } @Test - public void testCreateSelect() throws Exception { + public void testCreateTableSelect() throws Exception { String sqlStr = "CREATE TABLE mytable AS SELECT mycolumn FROM mytable2"; assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("mytable", "mytable2"); } + @Test + public void testCreateViewSelect() throws Exception { + String sqlStr = "CREATE VIEW mytable AS SELECT mycolumn FROM mytable2"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("mytable", + "mytable2"); + } + @Test public void testInsertSubSelect() throws JSQLParserException { String sqlStr = From 39004642b55ceac534d6467ff10a351633df5f29 Mon Sep 17 00:00:00 2001 From: Tomer Shay Date: Mon, 23 Dec 2024 18:35:38 +1300 Subject: [PATCH 73/88] add support for MATERIALIZED in WITH clause (#2128) --- .../sf/jsqlparser/statement/select/WithItem.java | 14 +++++++++++++- .../jsqlparser/util/deparser/SelectDeParser.java | 3 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 4 +++- .../sf/jsqlparser/statement/select/SelectTest.java | 6 ++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java index 2b2c4cba5..f1e5be3cd 100644 --- a/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java +++ b/src/main/java/net/sf/jsqlparser/statement/select/WithItem.java @@ -28,6 +28,8 @@ public class WithItem { private List> withItemList; private boolean recursive = false; + private boolean materialized = false; + public WithItem(T statement, Alias alias) { this.statement = statement; this.alias = alias; @@ -79,6 +81,14 @@ public void setRecursive(boolean recursive) { this.recursive = recursive; } + public boolean isMaterialized() { + return materialized; + } + + public void setMaterialized(boolean materialized) { + this.materialized = materialized; + } + /** * The {@link SelectItem}s in this WITH (for example the A,B,C in "WITH mywith (A,B,C) AS ...") * @@ -108,6 +118,7 @@ public String toString() { builder.append(")"); } builder.append(" AS "); + builder.append(materialized ? "MATERIALIZED " : ""); builder.append(statement); return builder.toString(); } @@ -121,8 +132,9 @@ public WithItem withWithItemList(List> withItemList) { return this; } - public WithItem withRecursive(boolean recursive) { + public WithItem withRecursive(boolean recursive, boolean materialized) { this.setRecursive(recursive); + this.setMaterialized(materialized); return this; } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java index a80af55ad..f7ac3ccf1 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java @@ -682,6 +682,9 @@ public StringBuilder visit(WithItem withItem, S context) { .append(PlainSelect.getStringList(withItem.getWithItemList(), true, true)); } buffer.append(" AS "); + if (withItem.isMaterialized()) { + buffer.append("MATERIALIZED "); + } StatementDeParser statementDeParser = new StatementDeParser((ExpressionDeParser) expressionVisitor, this, buffer); statementDeParser.deParse(withItem.getParenthesedStatement()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index cfe72baca..7413d79f9 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2705,6 +2705,7 @@ List> WithList(): WithItem WithItem() #WithItem: { boolean recursive = false; + boolean materialized = false; String name; List> selectItems = null; ParenthesedStatement statement; @@ -2714,6 +2715,7 @@ WithItem WithItem() #WithItem: name=RelObjectName() [ "(" selectItems=SelectItemsList() ")" ] + [ LOOKAHEAD(2) { materialized = true; } ] ( LOOKAHEAD(2) statement = ParenthesedSelect() | @@ -2726,7 +2728,7 @@ WithItem WithItem() #WithItem: { WithItem withItem = new WithItem(statement, new Alias(name, false)); return withItem - .withRecursive(recursive) + .withRecursive(recursive, materialized) .withWithItemList(selectItems); } } 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 dca870860..7964118f6 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -3186,6 +3186,12 @@ public void testSelectOracleColl() throws JSQLParserException { "SELECT * FROM the_table tt WHERE TT.COL1 = lines(idx).COL1"); } + @Test + public void testSelectWithMaterializedWith() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "WITH tokens_with_supply AS MATERIALIZED (SELECT * FROM tokens) SELECT * FROM tokens_with_supply"); + } + @Test public void testSelectInnerWith() throws JSQLParserException { String stmt = From f6c3c7dc2a1b4ffcf5cf76edd28ec572ac067e38 Mon Sep 17 00:00:00 2001 From: Liming Deng Date: Tue, 24 Dec 2024 15:33:56 +0800 Subject: [PATCH 74/88] feat: add support MATCH_ANY MATCH_ALL MATCH_PHRASE MATCH_PHRASE_PREFIX MATCH_REGEXP (#2132) * feat: add support MATCH_ANY MATCH_ALL MATCH_PHRASE MATCH_PHRASE_PREFIX MATCH_REGEXP * fix: formatting * fix: updateKeywords --- .../operators/relational/LikeExpression.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 12 ++++- .../relational/LikeExpressionTest.java | 44 ++++++++++++++++++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java index 08ac4888c..f450de1c1 100644 --- a/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java @@ -117,7 +117,7 @@ public LikeExpression withRightExpression(Expression arg0) { } public enum KeyWord { - LIKE, ILIKE, RLIKE, REGEXP_LIKE, REGEXP, SIMILAR_TO; + LIKE, ILIKE, RLIKE, REGEXP_LIKE, REGEXP, SIMILAR_TO, MATCH_ANY, MATCH_ALL, MATCH_PHRASE, MATCH_PHRASE_PREFIX, MATCH_REGEXP; public static KeyWord from(String keyword) { return Enum.valueOf(KeyWord.class, keyword.toUpperCase().replaceAll("\\s+", "_")); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 7413d79f9..70afaa46d 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -336,6 +336,11 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| +| +| +| +| | | | @@ -2040,7 +2045,7 @@ String RelObjectNameWithoutValue() : { Token tk = null; } { ( tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= - | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="AUTO_INCREMENT" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="ENCRYPTION" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) + | tk="ACTION" | tk="ACTIVE" | tk="ADD" | tk="ADVANCE" | tk="ADVISE" | tk="AGAINST" | tk="ALGORITHM" | tk="ALTER" | tk="ANALYZE" | tk="APPLY" | tk="APPROXIMATE" | tk="ARCHIVE" | tk="ARRAY" | tk="ASC" | tk="AT" | tk="AUTHORIZATION" | tk="AUTO" | tk="AUTO_INCREMENT" | tk="BASE64" | tk="BEGIN" | tk="BERNOULLI" | tk="BINARY" | tk="BIT" | tk="BLOCK" | tk="BROWSE" | tk="BUFFERS" | tk="BY" | tk="BYTE" | tk="BYTES" | tk="CACHE" | tk="CALL" | tk="CASCADE" | tk="CASE" | tk="CAST" | tk="CHANGE" | tk="CHANGES" | tk="CHAR" | tk="CHARACTER" | tk="CHECKPOINT" | tk="CLOSE" | tk="COLLATE" | tk="COLUMN" | tk="COLUMNS" | tk="COMMENT" | tk="COMMIT" | tk="CONCURRENTLY" | tk="CONFLICT" | tk="CONSTRAINTS" | tk="CONVERT" | tk="COSTS" | tk="COUNT" | tk="CS" | tk="CYCLE" | tk="DATA" | tk="DATABASE" | tk="DATETIME" | tk="DBA_RECYCLEBIN" | tk="DDL" | tk="DECLARE" | tk="DEFERRABLE" | tk="DELAYED" | tk="DELETE" | tk="DESC" | tk="DESCRIBE" | tk="DISABLE" | tk="DISCONNECT" | tk="DIV" | tk="DML" | tk="DO" | tk="DOMAIN" | tk="DROP" | tk="DUMP" | tk="DUPLICATE" | tk="ELEMENTS" | tk="EMIT" | tk="ENABLE" | tk="ENCRYPTION" | tk="END" | tk="ENGINE" | tk="ERROR" | tk="ESCAPE" | tk="EXCLUDE" | tk="EXEC" | tk="EXECUTE" | tk="EXPLAIN" | tk="EXPLICIT" | tk="EXTENDED" | tk="EXTRACT" | tk="FILTER" | tk="FIRST" | tk="FLUSH" | tk="FN" | tk="FOLLOWING" | tk="FORMAT" | tk="FULLTEXT" | tk="FUNCTION" | tk="GRANT" | tk="GROUP_CONCAT" | tk="GUARD" | tk="HASH" | tk="HIGH_PRIORITY" | tk="HISTORY" | tk="HOPPING" | tk="INCLUDE" | tk="INCLUDE_NULL_VALUES" | tk="INCREMENT" | tk="INDEX" | tk="INSERT" | tk="INTERLEAVE" | tk="INTERPRET" | tk="INVALIDATE" | tk="ISNULL" | tk="JSON" | tk="JSON_ARRAY" | tk="JSON_ARRAYAGG" | tk="JSON_OBJECT" | tk="JSON_OBJECTAGG" | tk="KEEP" | tk="KEY" | tk="KEYS" | tk="LAST" | tk="LEADING" | tk="LESS" | tk="LINK" | tk="LOCAL" | tk="LOCK" | tk="LOCKED" | tk="LOG" | tk="LONGTEXT" | tk="LOOP" | tk="LOW_PRIORITY" | tk="MATCH" | tk="MATCHED" | tk="MATCH_ALL" | tk="MATCH_ANY" | tk="MATCH_PHRASE" | tk="MATCH_PHRASE_PREFIX" | tk="MATCH_REGEXP" | tk="MATERIALIZED" | tk="MAX" | tk="MAXVALUE" | tk="MEDIUMTEXT" | tk="MEMBER" | tk="MERGE" | tk="MIN" | tk="MINVALUE" | tk="MODIFY" | tk="MOVEMENT" | tk="NEXT" | tk="NO" | tk="NOCACHE" | tk="NOKEEP" | tk="NOLOCK" | tk="NOMAXVALUE" | tk="NOMINVALUE" | tk="NOORDER" | tk="NOTHING" | tk="NOTNULL" | tk="NOVALIDATE" | tk="NOWAIT" | tk="NULLS" | tk="OF" | tk="OFF" | tk="OPEN" | tk="OVER" | tk="OVERFLOW" | tk="OVERLAPS" | tk="PARALLEL" | tk="PARENT" | tk="PARTITION" | tk="PATH" | tk="PERCENT" | tk="PLACING" | tk="PLAN" | tk="PRECEDING" | tk="PRIMARY" | tk="PURGE" | tk="QUERY" | tk="QUICK" | tk="QUIESCE" | tk="RANGE" | tk="RAW" | tk="READ" | tk="RECURSIVE" | tk="RECYCLEBIN" | tk="REFERENCES" | tk="REFRESH" | tk="REGEXP" | tk="REGEXP_LIKE" | tk="REGISTER" | tk="REMOTE" | tk="RENAME" | tk="REPEATABLE" | tk="REPLACE" | tk="RESET" | tk="RESPECT" | tk="RESTART" | tk="RESTRICT" | tk="RESTRICTED" | tk="RESUMABLE" | tk="RESUME" | tk="RETURN" | tk="RLIKE" | tk="ROLLBACK" | tk="ROLLUP" | tk="ROOT" | tk="ROW" | tk="ROWS" | tk="RR" | tk="RS" | tk="SAFE_CAST" | tk="SAVEPOINT" | tk="SCHEMA" | tk="SECURE" | tk="SEED" | tk="SEPARATOR" | tk="SEQUENCE" | tk="SESSION" | tk="SETS" | tk="SHARE" | tk="SHOW" | tk="SHUTDOWN" | tk="SIBLINGS" | tk="SIGNED" | tk="SIMILAR" | tk="SIZE" | tk="SKIP" | tk="STORED" | tk="STRING" | tk="STRUCT" | tk="SUMMARIZE" | tk="SUSPEND" | tk="SWITCH" | tk="SYNONYM" | tk="SYSTEM" | tk="TABLE" | tk="TABLESPACE" | tk="TEMP" | tk="TEMPORARY" | tk="TEXT" | tk="THAN" | tk="THEN" | tk="TIMEOUT" | tk="TIMESTAMPTZ" | tk="TIMEZONE" | tk="TINYTEXT" | tk="TO" | tk="TRIGGER" | tk="TRUNCATE" | tk="TRY_CAST" | tk="TUMBLING" | tk="TYPE" | tk="UNLOGGED" | tk="UNQIESCE" | tk="UNSIGNED" | tk="UPDATE" | tk="UPSERT" | tk="UR" | tk="USER" | tk="VALIDATE" | tk="VERBOSE" | tk="VIEW" | tk="VOLATILE" | tk="WAIT" | tk="WITHIN" | tk="WITHOUT" | tk="WITHOUT_ARRAY_WRAPPER" | tk="WORK" | tk="XML" | tk="XMLAGG" | tk="XMLDATA" | tk="XMLSCHEMA" | tk="XMLTEXT" | tk="XSINIL" | tk="YAML" | tk="YES" | tk="ZONE" ) { return tk.image; } } @@ -4220,6 +4225,11 @@ Expression LikeExpression(Expression leftExpression) #LikeExpression: | token = | token = | token = + | token = + | token = + | token = + | token = + | token = ) { result.setLikeKeyWord( LikeExpression.KeyWord.from(token.image)); } [ LOOKAHEAD(2) {result.setUseBinary(true); } ] rightExpression=SimpleExpression() diff --git a/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java b/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java index acc1ef6be..eb11e86e2 100644 --- a/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java @@ -9,6 +9,8 @@ */ package net.sf.jsqlparser.expression.operators.relational; +import static org.junit.jupiter.api.Assertions.*; + import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.StringValue; @@ -16,8 +18,6 @@ import net.sf.jsqlparser.test.TestUtils; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - /** * * @author Tobias Warneke (t.warneke@gmx.net) @@ -58,4 +58,44 @@ void testDuckDBSimuilarTo() throws JSQLParserException { + " ORDER BY v;"; TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); } + + @Test + public void testMatchAny() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v MATCH_ANY 'keyword1 keyword2'", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v NOT MATCH_ANY 'keyword1 keyword2'", true); + } + + @Test + public void testMatchAll() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v MATCH_ALL 'keyword1 keyword2'", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v NOT MATCH_ALL 'keyword1 keyword2'", true); + } + + @Test + public void testMatchPhrase() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v MATCH_PHRASE 'keyword1 keyword2'", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v NOT MATCH_PHRASE 'keyword1 keyword2'", true); + } + + @Test + public void testMatchPhrasePrefix() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v MATCH_PHRASE_PREFIX 'keyword1 keyword2'", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v NOT MATCH_PHRASE_PREFIX 'keyword1 keyword2'", true); + } + + @Test + public void testMatchRegexp() throws JSQLParserException { + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v MATCH_REGEXP 'keyword1 keyword2'", true); + TestUtils.assertSqlCanBeParsedAndDeparsed( + "select * from dual where v NOT MATCH_REGEXP 'keyword1 keyword2'", true); + } } From 642e7a794c3077df95f6dfbbdd6e2c7c0281ceff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 14:35:21 +0700 Subject: [PATCH 75/88] build(deps): bump org.junit.jupiter:junit-jupiter-engine (#2129) Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-engine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9816e74a4..d2fe1bdd6 100644 --- a/build.gradle +++ b/build.gradle @@ -96,7 +96,7 @@ dependencies { // for JaCoCo Reports testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.3' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter From 1edc439a5fd045b7297bfc670014263b64e62b29 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Tue, 24 Dec 2024 14:52:45 +0700 Subject: [PATCH 76/88] build: update memory settings Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- build.gradle | 6 +++--- pom.xml | 41 ++--------------------------------------- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/build.gradle b/build.gradle index d2fe1bdd6..bc19bee83 100644 --- a/build.gradle +++ b/build.gradle @@ -95,9 +95,9 @@ dependencies { testImplementation 'com.h2database:h2:+' // for JaCoCo Reports - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.3' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.3' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.+' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.+' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.+' // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter testImplementation 'org.mockito:mockito-junit-jupiter:+' diff --git a/pom.xml b/pom.xml index f01ff7452..706dddce0 100644 --- a/pom.xml +++ b/pom.xml @@ -283,15 +283,6 @@ forked-path sign-release-artifacts - org.apache.maven.plugins @@ -336,41 +327,11 @@ - - maven-site-plugin - 3.12.1 - - - attach-descriptor - - attach-descriptor - - - - - en - - org.eluder.coveralls coveralls-maven-plugin 4.3.0 - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - xml - - - net/sf/jsqlparser/parser/*.class - net/sf/jsqlparser/JSQLParserException.class - - - - - org.apache.felix maven-bundle-plugin @@ -388,6 +349,7 @@ --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED + -Xmx2G -Xms512m @@ -465,6 +427,7 @@ 3.0.0-M7 ${project.reporting.outputDirectory}/testresults + -Xmx2G -Xms512m From d9acb5f4a6a878ada65bb5639327a9d8697a4da0 Mon Sep 17 00:00:00 2001 From: Tomer Shay Date: Sat, 28 Dec 2024 22:59:22 +1300 Subject: [PATCH 77/88] Fix null exception in ExpressionVisitorAdapter with simple INTERVAL expression (#2133) --- .../sf/jsqlparser/expression/ExpressionVisitorAdapter.java | 5 ++++- .../expression/ExpressionVisitorAdapterTest.java | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index 89bacff48..96f3c5ea2 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -430,7 +430,10 @@ public T visit(ExtractExpression extractExpression, S context) { @Override public T visit(IntervalExpression intervalExpression, S context) { - return intervalExpression.getExpression().accept(this, context); + if (intervalExpression.getExpression() != null) { + intervalExpression.getExpression().accept(this, context); + } + return null; } @Override diff --git a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java index d9f45c2ca..0654480da 100644 --- a/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java +++ b/src/test/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapterTest.java @@ -321,4 +321,11 @@ public Void visit(ExcludesExpression expr, S parameters) { assertInstanceOf(Column.class, exprList.get(0)); assertInstanceOf(ParenthesedExpressionList.class, exprList.get(1)); } + + @Test + public void testIntervalWithNoExpression() throws JSQLParserException { + Expression expr = CCJSqlParserUtil.parseExpression("INTERVAL 1 DAY"); + ExpressionVisitorAdapter adapter = new ExpressionVisitorAdapter<>(); + expr.accept(adapter, null); + } } From 55d2da671d65ce8341e63dbdeda617711940cea5 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sat, 28 Dec 2024 17:17:04 +0700 Subject: [PATCH 78/88] build: update memory settings Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index 706dddce0..3468a73b4 100644 --- a/pom.xml +++ b/pom.xml @@ -199,11 +199,15 @@ true ${project.build.sourceEncoding} true + true + 128m + 2g org.javacc.plugin javacc-maven-plugin + 3.0.3 javacc From 52d801015f7a80c46eab8c758d80c107f1dd7127 Mon Sep 17 00:00:00 2001 From: manticore-projects Date: Sat, 28 Dec 2024 17:23:08 +0700 Subject: [PATCH 79/88] build: update memory settings Signed-off-by: Andreas Reichel Signed-off-by: manticore-projects --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3468a73b4..09e21896e 100644 --- a/pom.xml +++ b/pom.xml @@ -440,7 +440,7 @@ 3.4.1 true - 800m + 2048m none + 2g + 800m none