diff --git a/src/main/java/net/sf/jsqlparser/util/validation/DatabaseType.java b/src/main/java/net/sf/jsqlparser/util/validation/DatabaseType.java new file mode 100644 index 000000000..3083b77eb --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/DatabaseType.java @@ -0,0 +1,23 @@ +package net.sf.jsqlparser.util.validation; + +/** + *

+ * The DatabaseType is named like the identifier used within the + * jdbc-connection-url, this may change in future, therefore use + * {@link #get(String)} to retrieve the {@link DatabaseType}. + *

+ */ +public enum DatabaseType { + + oracle, mysql, sqlserver; + + /** + * @param jdbcIdentifier - the database-identifier-part of jdbc-url + * @return the {@link DatabaseType} + * @throws IllegalArgumentException - if the specified jdbcIdentifier cannot be mapped to a {@link DatabaseType} + */ + public static DatabaseType get(String jdbcIdentifier) { + return DatabaseType.valueOf(jdbcIdentifier); + } + +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/ExpressionValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/ExpressionValidator.java new file mode 100644 index 000000000..4b5278544 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/ExpressionValidator.java @@ -0,0 +1,661 @@ +/*- + * #%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.util.validation; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.Addition; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift; +import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor; +import net.sf.jsqlparser.expression.operators.arithmetic.Concat; +import net.sf.jsqlparser.expression.operators.arithmetic.Division; +import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision; +import net.sf.jsqlparser.expression.operators.arithmetic.Modulo; +import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication; +import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.OrderByElement; +import net.sf.jsqlparser.statement.select.SelectVisitor; +import net.sf.jsqlparser.statement.select.SubSelect; +import net.sf.jsqlparser.statement.select.WithItem; + +public class ExpressionValidator implements ExpressionVisitor, ItemsListVisitor, Validation { + + protected Map> errors = new EnumMap<>(DatabaseType.class); + private SelectVisitor selectVisitor; + private boolean useBracketsInExprList = true; + private OrderByValidator orderByDeParser = new OrderByValidator(); + + public ExpressionValidator() { + this(null, new EnumMap<>(DatabaseType.class)); + } + + public ExpressionValidator(SelectVisitor selectVisitor, Map> errors) { + this(selectVisitor, errors, new OrderByValidator()); + } + + ExpressionValidator(SelectVisitor selectVisitor, Map> errors, + OrderByValidator orderByDeValidator) { + this.selectVisitor = selectVisitor; + this.errors = errors; + this.orderByDeParser = orderByDeValidator; + } + + @Override + public void visit(Addition addition) { + visitBinaryExpression(addition, " + "); + } + + @Override + public void visit(AndExpression andExpression) { + visitBinaryExpression(andExpression, andExpression.isUseOperator()?" && ":" AND "); + } + + @Override + public void visit(Between between) { + between.getLeftExpression().accept(this); + between.getBetweenExpressionStart().accept(this); + between.getBetweenExpressionEnd().accept(this); + } + + @Override + public void visit(EqualsTo equalsTo) { + visitOldOracleJoinBinaryExpression(equalsTo, " = "); + } + + @Override + public void visit(Division division) { + visitBinaryExpression(division, " / "); + } + + @Override + public void visit(IntegerDivision division) { + visitBinaryExpression(division, " DIV "); + } + + @Override + public void visit(DoubleValue doubleValue) { + } + + @Override + public void visit(HexValue hexValue) { + } + + @Override + public void visit(NotExpression notExpr) { + notExpr.getExpression().accept(this); + } + + @Override + public void visit(BitwiseRightShift expr) { + visitBinaryExpression(expr, " >> "); + } + + @Override + public void visit(BitwiseLeftShift expr) { + visitBinaryExpression(expr, " << "); + } + + public void visitOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression expression, String operator) { + expression.getLeftExpression().accept(this); + if (expression.getOldOracleJoinSyntax() != SupportsOldOracleJoinSyntax.NO_ORACLE_JOIN) { + Validation.mapAllExcept(errors, EnumSet.of(DatabaseType.oracle), + String.format("oldOracleJoinSyntax=%d not supported", expression.getOldOracleJoinSyntax())); + } + expression.getRightExpression().accept(this); + if (expression.getOraclePriorPosition() != SupportsOldOracleJoinSyntax.NO_ORACLE_PRIOR) { + Validation.mapAllExcept(errors, EnumSet.of(DatabaseType.oracle), + String.format("oraclePriorPosition=%d not supported", expression.getOraclePriorPosition())); + } + } + + @Override + public void visit(GreaterThan greaterThan) { + visitOldOracleJoinBinaryExpression(greaterThan, " > "); + } + + @Override + public void visit(GreaterThanEquals greaterThanEquals) { + visitOldOracleJoinBinaryExpression(greaterThanEquals, " >= "); + + } + + @Override + public void visit(InExpression inExpression) { + if (inExpression.getLeftExpression() == null) { + inExpression.getLeftItemsList().accept(this); + } else { + inExpression.getLeftExpression().accept(this); + if (inExpression.getOldOracleJoinSyntax() == SupportsOldOracleJoinSyntax.ORACLE_JOIN_RIGHT) { + } + } + if (inExpression.isNot()) { + } + + if (inExpression.getMultiExpressionList() != null) { + parseMultiExpressionList(inExpression); + } else { + if (inExpression.getRightExpression() != null) { + inExpression.getRightExpression().accept(this); + } else { + inExpression.getRightItemsList().accept(this); + } + } + } + + /** + * Produces a multi-expression in clause: {@code ((a, b), (c, d))} + */ + private void parseMultiExpressionList(InExpression inExpression) { + MultiExpressionList multiExprList = inExpression.getMultiExpressionList(); + for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + for (Iterator iter = it.next().getExpressions().iterator(); iter.hasNext();) { + Expression expression = iter.next(); + expression.accept(this); + if (iter.hasNext()) { + } + } + if (it.hasNext()) { + } + } + } + + @Override + public void visit(FullTextSearch fullTextSearch) { + } + + @Override + public void visit(SignedExpression signedExpression) { + signedExpression.getExpression().accept(this); + } + + @Override + public void visit(IsNullExpression isNullExpression) { + isNullExpression.getLeftExpression().accept(this); + } + + @Override + public void visit(IsBooleanExpression isBooleanExpression) { + isBooleanExpression.getLeftExpression().accept(this); + } + + @Override + public void visit(JdbcParameter jdbcParameter) { + } + + @Override + public void visit(LikeExpression likeExpression) { + visitBinaryExpression(likeExpression, + (likeExpression.isNot() ? " NOT" : "") + + (likeExpression.isCaseInsensitive() ? " ILIKE " : " LIKE ")); + } + + @Override + public void visit(ExistsExpression existsExpression) { + if (existsExpression.isNot()) { + } else { + } + existsExpression.getRightExpression().accept(this); + } + + @Override + public void visit(LongValue longValue) { + + } + + @Override + public void visit(MinorThan minorThan) { + visitOldOracleJoinBinaryExpression(minorThan, " < "); + + } + + @Override + public void visit(MinorThanEquals minorThanEquals) { + visitOldOracleJoinBinaryExpression(minorThanEquals, " <= "); + + } + + @Override + public void visit(Multiplication multiplication) { + visitBinaryExpression(multiplication, " * "); + + } + + @Override + public void visit(NotEqualsTo notEqualsTo) { + visitOldOracleJoinBinaryExpression(notEqualsTo, " " + notEqualsTo.getStringExpression() + " "); + + } + + @Override + public void visit(NullValue nullValue) { + + } + + @Override + public void visit(OrExpression orExpression) { + visitBinaryExpression(orExpression, " OR "); + + } + + @Override + public void visit(Parenthesis parenthesis) { + parenthesis.getExpression().accept(this); + } + + @Override + public void visit(StringValue stringValue) { + if (stringValue.getPrefix() != null) { + } + + } + + @Override + public void visit(Subtraction subtraction) { + visitBinaryExpression(subtraction, " - "); + } + + protected void visitBinaryExpression(BinaryExpression binaryExpression, String operator) { + binaryExpression.getLeftExpression().accept(this); + binaryExpression.getRightExpression().accept(this); + + } + + @Override + public void visit(SubSelect subSelect) { + if (subSelect.isUseBrackets()) { + } + if (selectVisitor != null) { + if (subSelect.getWithItemsList() != null) { + for (Iterator iter = subSelect.getWithItemsList().iterator(); iter. + hasNext();) { + iter.next().accept(selectVisitor); + if (iter.hasNext()) { + } + } + } + + subSelect.getSelectBody().accept(selectVisitor); + } + if (subSelect.isUseBrackets()) { + } + } + + @Override + public void visit(Column tableColumn) { + final Table table = tableColumn.getTable(); + String tableName = null; + if (table != null) { + if (table.getAlias() != null) { + tableName = table.getAlias().getName(); + } else { + tableName = table.getFullyQualifiedName(); + } + } + if (tableName != null && !tableName.isEmpty()) { + } + + } + + @Override + public void visit(Function function) { + if (function.isEscaped()) { + } + + if (function.isAllColumns() && function.getParameters() == null) { + } else if (function.getParameters() == null && function.getNamedParameters() == null) { + } else { + boolean oldUseBracketsInExprList = useBracketsInExprList; + useBracketsInExprList = true; + if (function.isDistinct()) { + useBracketsInExprList = false; + } else if (function.isAllColumns()) { + useBracketsInExprList = false; + } + if (function.getNamedParameters() != null) { + visit(function.getNamedParameters()); + } + if (function.getParameters() != null) { + visit(function.getParameters()); + } + useBracketsInExprList = oldUseBracketsInExprList; + if (function.isDistinct() || function.isAllColumns()) { + } + } + + if (function.getAttribute() != null) { + } else if (function.getAttributeName() != null) { + } + if (function.getKeep() != null) { + } + if (function.isEscaped()) { + } + } + + @Override + public void visit(ExpressionList expressionList) { + if (useBracketsInExprList) { + } + for (Iterator iter = expressionList.getExpressions().iterator(); iter.hasNext();) { + Expression expression = iter.next(); + expression.accept(this); + if (iter.hasNext()) { + } + } + if (useBracketsInExprList) { + } + } + + @Override + public void visit(NamedExpressionList namedExpressionList) { + if (useBracketsInExprList) { + } + List names = namedExpressionList.getNames(); + List expressions = namedExpressionList.getExpressions(); + for (int i = 0; i < names.size(); i++) { + if (i > 0) { + } + String name = names.get(i); + if (!name.equals("")) { + } + expressions.get(i).accept(this); + } + if (useBracketsInExprList) { + } + } + + public SelectVisitor getSelectVisitor() { + return selectVisitor; + } + + public void setSelectVisitor(SelectVisitor visitor) { + selectVisitor = visitor; + } + + @Override + public void visit(DateValue dateValue) { + } + + @Override + public void visit(TimestampValue timestampValue) { + } + + @Override + public void visit(TimeValue timeValue) { + } + + @Override + public void visit(CaseExpression caseExpression) { + Expression switchExp = caseExpression.getSwitchExpression(); + if (switchExp != null) { + switchExp.accept(this); + } + + for (Expression exp : caseExpression.getWhenClauses()) { + exp.accept(this); + } + + Expression elseExp = caseExpression.getElseExpression(); + if (elseExp != null) { + elseExp.accept(this); + } + + } + + @Override + public void visit(WhenClause whenClause) { + whenClause.getWhenExpression().accept(this); + whenClause.getThenExpression().accept(this); + } + + @Override + public void visit(AllComparisonExpression allComparisonExpression) { + allComparisonExpression.getSubSelect().accept((ExpressionVisitor) this); + } + + @Override + public void visit(AnyComparisonExpression anyComparisonExpression) { + anyComparisonExpression.getSubSelect().accept((ExpressionVisitor) this); + } + + @Override + public void visit(Concat concat) { + visitBinaryExpression(concat, " || "); + } + + @Override + public void visit(Matches matches) { + visitOldOracleJoinBinaryExpression(matches, " @@ "); + } + + @Override + public void visit(BitwiseAnd bitwiseAnd) { + visitBinaryExpression(bitwiseAnd, " & "); + } + + @Override + public void visit(BitwiseOr bitwiseOr) { + visitBinaryExpression(bitwiseOr, " | "); + } + + @Override + public void visit(BitwiseXor bitwiseXor) { + visitBinaryExpression(bitwiseXor, " ^ "); + } + + @Override + public void visit(CastExpression cast) { + if (cast.isUseCastKeyword()) { + cast.getLeftExpression().accept(this); + } else { + cast.getLeftExpression().accept(this); + } + } + + @Override + public void visit(Modulo modulo) { + visitBinaryExpression(modulo, " % "); + } + + @Override + public void visit(AnalyticExpression aexpr) { + String name = aexpr.getName(); + Expression expression = aexpr.getExpression(); + Expression offset = aexpr.getOffset(); + Expression defaultValue = aexpr.getDefaultValue(); + boolean isAllColumns = aexpr.isAllColumns(); + KeepExpression keep = aexpr.getKeep(); + ExpressionList partitionExpressionList = aexpr.getPartitionExpressionList(); + List orderByElements = aexpr.getOrderByElements(); + WindowElement windowElement = aexpr.getWindowElement(); + + if (aexpr.isDistinct()) { + } + if (expression != null) { + expression.accept(this); + if (offset != null) { + offset.accept(this); + if (defaultValue != null) { + defaultValue.accept(this); + } + } + } else if (isAllColumns) { + } + if (aexpr.isIgnoreNulls()) { + } + if (keep != null) { + keep.accept(this); + } + + if (aexpr.getFilterExpression() != null) { + aexpr.getFilterExpression().accept(this); + } + + switch (aexpr.getType()) { + case WITHIN_GROUP: + break; + default: + } + + if (partitionExpressionList != null && !partitionExpressionList.getExpressions().isEmpty()) { + if (aexpr.isPartitionByBrackets()) { + } + List expressions = partitionExpressionList.getExpressions(); + for (int i = 0; i < expressions.size(); i++) { + if (i > 0) { + } + expressions.get(i).accept(this); + } + if (aexpr.isPartitionByBrackets()) { + } + } + if (orderByElements != null && !orderByElements.isEmpty()) { + // orderByDeValidator.setExpressionVisitor(this); + // orderByDeValidator.setBuffer(errors); + for (int i = 0; i < orderByElements.size(); i++) { + if (i > 0) { + } + // orderByDeParser.deParseElement(orderByElements.get(i)); + } + } + + if (windowElement != null) { + if (orderByElements != null && !orderByElements.isEmpty()) { + } + } + + } + + @Override + public void visit(ExtractExpression eexpr) { + eexpr.getExpression().accept(this); + } + + @Override + public void visit(MultiExpressionList multiExprList) { + for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) { + it.next().accept(this); + if (it.hasNext()) { + } + } + } + + @Override + public void visit(IntervalExpression iexpr) { + } + + @Override + public void visit(JdbcNamedParameter jdbcNamedParameter) { + } + + @Override + public void visit(OracleHierarchicalExpression oexpr) { + } + + @Override + public void visit(RegExpMatchOperator rexpr) { + visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); + } + + @Override + public void visit(RegExpMySQLOperator rexpr) { + visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); + } + + @Override + public void visit(JsonExpression jsonExpr) { + } + + @Override + public void visit(JsonOperator jsonExpr) { + visitBinaryExpression(jsonExpr, " " + jsonExpr.getStringExpression() + " "); + } + + @Override + public void visit(UserVariable var) { + } + + @Override + public void visit(NumericBind bind) { + } + + @Override + public void visit(KeepExpression aexpr) { + } + + @Override + public void visit(MySQLGroupConcat groupConcat) { + } + + @Override + public void visit(ValueListExpression valueList) { + } + + @Override + public void visit(RowConstructor rowConstructor) { + if (rowConstructor.getName() != null) { + } + boolean first = true; + for (Expression expr : rowConstructor.getExprList().getExpressions()) { + if (first) { + first = false; + } else { + } + expr.accept(this); + } + } + + @Override + public void visit(OracleHint hint) { + } + + @Override + public void visit(TimeKeyExpression timeKeyExpression) { + } + @Override + public void visit(DateTimeLiteralExpression literal) { + } + + @Override + public void visit(NextValExpression nextVal) { + } + + @Override + public void visit(CollateExpression col) { + } + + @Override + public void visit(SimilarToExpression expr) { + visitBinaryExpression(expr, (expr.isNot() ? " NOT" : "") + " SIMILAR TO "); + } + + @Override + public void visit(ArrayExpression array) { + array.getObjExpression().accept(this); + array.getIndexExpression().accept(this); + } + + @Override + public Map> getValidationErrors() { + return errors; + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/OrderByValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/OrderByValidator.java new file mode 100644 index 000000000..14bb1b9f5 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/OrderByValidator.java @@ -0,0 +1,5 @@ +package net.sf.jsqlparser.util.validation; + +public class OrderByValidator { + +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/SelectValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/SelectValidator.java new file mode 100644 index 000000000..ce021b931 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/SelectValidator.java @@ -0,0 +1,503 @@ +/*- + * #%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.util.validation; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Set; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.*; +import net.sf.jsqlparser.statement.values.ValuesStatement; + +public class SelectValidator implements SelectVisitor, SelectItemVisitor, FromItemVisitor, PivotVisitor, Validation { + + protected Map> errors; + private ExpressionValidator expressionVisitor; + + public SelectValidator() { + this(new ExpressionValidator(), new EnumMap<>(DatabaseType.class)); + } + + public SelectValidator(ExpressionValidator expressionVisitor, Map> errors) { + this.errors = errors; + this.expressionVisitor = expressionVisitor; + } + + @Override + public void visit(PlainSelect plainSelect) { + // if (plainSelect.isUseBrackets()) { + // errors.append("("); + // } + // errors.append("SELECT "); + // + // if (plainSelect.getMySqlHintStraightJoin()) { + // errors.append("STRAIGHT_JOIN "); + // } + // + // OracleHint hint = plainSelect.getOracleHint(); + // if (hint != null) { + // errors.append(hint).append(" "); + // } + // + // Skip skip = plainSelect.getSkip(); + // if (skip != null) { + // errors.append(skip).append(" "); + // } + // + // First first = plainSelect.getFirst(); + // if (first != null) { + // errors.append(first).append(" "); + // } + // + // if (plainSelect.getDistinct() != null) { + // if (plainSelect.getDistinct().isUseUnique()) { + // errors.append("UNIQUE "); + // } else { + // errors.append("DISTINCT "); + // } + // if (plainSelect.getDistinct().getOnSelectItems() != null) { + // errors.append("ON ("); + // for (Iterator iter = plainSelect.getDistinct().getOnSelectItems(). + // iterator(); iter.hasNext();) { + // SelectItem selectItem = iter.next(); + // selectItem.accept(this); + // if (iter.hasNext()) { + // errors.append(", "); + // } + // } + // errors.append(") "); + // } + // + // } + // + // Top top = plainSelect.getTop(); + // if (top != null) { + // errors.append(top).append(" "); + // } + // + // if (plainSelect.getMySqlSqlNoCache()) { + // errors.append("SQL_NO_CACHE").append(" "); + // } + // + // if (plainSelect.getMySqlSqlCalcFoundRows()) { + // errors.append("SQL_CALC_FOUND_ROWS").append(" "); + // } + // + // for (Iterator iter = plainSelect.getSelectItems().iterator(); iter.hasNext();) { + // SelectItem selectItem = iter.next(); + // selectItem.accept(this); + // if (iter.hasNext()) { + // errors.append(", "); + // } + // } + // + // if (plainSelect.getIntoTables() != null) { + // errors.append(" INTO "); + // for (Iterator iter = plainSelect.getIntoTables().iterator(); iter.hasNext();) { + // visit(iter.next()); + // if (iter.hasNext()) { + // errors.append(", "); + // } + // } + // } + // + // if (plainSelect.getFromItem() != null) { + // errors.append(" FROM "); + // plainSelect.getFromItem().accept(this); + // } + // + // if (plainSelect.getJoins() != null) { + // for (Join join : plainSelect.getJoins()) { + // deparseJoin(join); + // } + // } + // + // if (plainSelect.getKsqlWindow() != null) { + // errors.append(" WINDOW "); + // errors.append(plainSelect.getKsqlWindow().toString()); + // } + + if (plainSelect.getWhere() != null) { + plainSelect.getWhere().accept(expressionVisitor); + } + + // if (plainSelect.getOracleHierarchical() != null) { + // plainSelect.getOracleHierarchical().accept(expressionVisitor); + // } + // + // if (plainSelect.getGroupBy() != null) { + // errors.append(" "); + // new GroupByDeParser(expressionVisitor, errors).deParse(plainSelect.getGroupBy()); + // } + // + // if (plainSelect.getHaving() != null) { + // errors.append(" HAVING "); + // plainSelect.getHaving().accept(expressionVisitor); + // } + // + // if (plainSelect.getOrderByElements() != null) { + // new OrderByDeParser(expressionVisitor, errors). + // deParse(plainSelect.isOracleSiblings(), plainSelect.getOrderByElements()); + // } + // + // if (plainSelect.getLimit() != null) { + // new LimitDeparser(errors).deParse(plainSelect.getLimit()); + // } + // if (plainSelect.getOffset() != null) { + // deparseOffset(plainSelect.getOffset()); + // } + // if (plainSelect.getFetch() != null) { + // deparseFetch(plainSelect.getFetch()); + // } + // if (plainSelect.isForUpdate()) { + // errors.append(" FOR UPDATE"); + // if (plainSelect.getForUpdateTable() != null) { + // errors.append(" OF ").append(plainSelect.getForUpdateTable()); + // } + // if (plainSelect.getWait() != null) { + // // wait's toString will do the formatting for us + // errors.append(plainSelect.getWait()); + // } + // if (plainSelect.isNoWait()) { + // errors.append(" NOWAIT"); + // } + // } + // if (plainSelect.getOptimizeFor() != null) { + // deparseOptimizeFor(plainSelect.getOptimizeFor()); + // } + // if (plainSelect.getForXmlPath() != null) { + // errors.append(" FOR XML PATH(").append(plainSelect.getForXmlPath()).append(")"); + // } + // if (plainSelect.isUseBrackets()) { + // errors.append(")"); + // } + } + + @Override + public void visit(AllTableColumns allTableColumns) { + // errors.append(allTableColumns.getTable().getFullyQualifiedName()).append(".*"); + } + + @Override + public void visit(SelectExpressionItem selectExpressionItem) { + // selectExpressionItem.getExpression().accept(expressionVisitor); + // if (selectExpressionItem.getAlias() != null) { + // errors.append(selectExpressionItem.getAlias().toString()); + // } + } + + @Override + public void visit(SubSelect subSelect) { + // errors.append("("); + // if (subSelect.getWithItemsList() != null && !subSelect.getWithItemsList().isEmpty()) { + // errors.append("WITH "); + // for (Iterator iter = subSelect.getWithItemsList().iterator(); iter.hasNext();) { + // WithItem withItem = iter.next(); + // withItem.accept(this); + // if (iter.hasNext()) { + // errors.append(","); + // } + // errors.append(" "); + // } + // } + // subSelect.getSelectBody().accept(this); + // errors.append(")"); + // Alias alias = subSelect.getAlias(); + // if (alias != null) { + // errors.append(alias.toString()); + // } + // Pivot pivot = subSelect.getPivot(); + // if (pivot != null) { + // pivot.accept(this); + // } + } + + @Override + public void visit(Table tableName) { + // errors.append(tableName.getFullyQualifiedName()); + // Alias alias = tableName.getAlias(); + // if (alias != null) { + // errors.append(alias); + // } + // Pivot pivot = tableName.getPivot(); + // if (pivot != null) { + // pivot.accept(this); + // } + // UnPivot unpivot = tableName.getUnPivot(); + // if (unpivot != null) { + // unpivot.accept(this); + // } + // MySQLIndexHint indexHint = tableName.getIndexHint(); + // if (indexHint != null) { + // errors.append(indexHint); + // } + // SQLServerHints sqlServerHints = tableName.getSqlServerHints(); + // if (sqlServerHints != null) { + // errors.append(sqlServerHints); + // } + } + + @Override + public void visit(Pivot pivot) { + // List forColumns = pivot.getForColumns(); + // errors.append(" PIVOT (") + // .append(PlainSelect.getStringList(pivot.getFunctionItems())) + // .append(" FOR ") + // .append(PlainSelect. + // getStringList(forColumns, true, forColumns != null && forColumns.size() > 1)). + // append(" IN ") + // .append(PlainSelect.getStringList(pivot.getInItems(), true, true)) + // .append(")"); + // if (pivot.getAlias() != null) { + // errors.append(pivot.getAlias().toString()); + // } + } + + @Override + public void visit(UnPivot unpivot) { + // boolean showOptions = unpivot.getIncludeNullsSpecified(); + // boolean includeNulls = unpivot.getIncludeNulls(); + // List unpivotForClause = unpivot.getUnPivotForClause(); + // errors.append(" UNPIVOT") + // .append(showOptions && includeNulls ? " INCLUDE NULLS" : "") + // .append(showOptions && !includeNulls ? " EXCULDE NULLS" : "") + // .append(" (") + // .append(unpivot.getUnPivotClause()) + // .append(" FOR ").append(PlainSelect.getStringList(unpivotForClause, true, unpivotForClause != null && unpivotForClause.size() > 1)) + // .append(" IN ").append(PlainSelect.getStringList(unpivot.getUnPivotInClause(), true, true)) + // .append(")"); + } + + @Override + public void visit(PivotXml pivot) { + // List forColumns = pivot.getForColumns(); + // errors.append(" PIVOT XML (") + // .append(PlainSelect.getStringList(pivot.getFunctionItems())) + // .append(" FOR ") + // .append(PlainSelect. + // getStringList(forColumns, true, forColumns != null && forColumns.size() > 1)). + // append(" IN ("); + // if (pivot.isInAny()) { + // errors.append("ANY"); + // } else if (pivot.getInSelect() != null) { + // errors.append(pivot.getInSelect()); + // } else { + // errors.append(PlainSelect.getStringList(pivot.getInItems())); + // } + // errors.append("))"); + } + + public void deparseOffset(Offset offset) { + // // OFFSET offset + // // or OFFSET offset (ROW | ROWS) + // if (offset.getOffsetJdbcParameter() != null) { + // errors.append(" OFFSET ").append(offset.getOffsetJdbcParameter()); + // } else { + // errors.append(" OFFSET "); + // errors.append(offset.getOffset()); + // } + // if (offset.getOffsetParam() != null) { + // errors.append(" ").append(offset.getOffsetParam()); + // } + + } + + public void deparseFetch(Fetch fetch) { + // // FETCH (FIRST | NEXT) row_count (ROW | ROWS) ONLY + // errors.append(" FETCH "); + // if (fetch.isFetchParamFirst()) { + // errors.append("FIRST "); + // } else { + // errors.append("NEXT "); + // } + // if (fetch.getFetchJdbcParameter() != null) { + // errors.append(fetch.getFetchJdbcParameter().toString()); + // } else { + // errors.append(fetch.getRowCount()); + // } + // errors.append(" ").append(fetch.getFetchParam()).append(" ONLY"); + + } + + // public ExpressionVisitor getExpressionVisitor() { + // return expressionVisitor; + // } + // + // public void setExpressionVisitor(ExpressionVisitor visitor) { + // expressionVisitor = visitor; + // } + + @Override + public void visit(SubJoin subjoin) { + // errors.append("("); + // subjoin.getLeft().accept(this); + // for (Join join : subjoin.getJoinList()) { + // deparseJoin(join); + // } + // errors.append(")"); + // + // if (subjoin.getPivot() != null) { + // subjoin.getPivot().accept(this); + // } + } + + public void deparseJoin(Join join) { + // if (join.isSimple() && join.isOuter()) { + // errors.append(", OUTER "); + // } else if (join.isSimple()) { + // errors.append(", "); + // } else { + // + // if (join.isRight()) { + // errors.append(" RIGHT"); + // } else if (join.isNatural()) { + // errors.append(" NATURAL"); + // } else if (join.isFull()) { + // errors.append(" FULL"); + // } else if (join.isLeft()) { + // errors.append(" LEFT"); + // } else if (join.isCross()) { + // errors.append(" CROSS"); + // } + // + // if (join.isOuter()) { + // errors.append(" OUTER"); + // } else if (join.isInner()) { + // errors.append(" INNER"); + // } else if (join.isSemi()) { + // errors.append(" SEMI"); + // } + // + // if (join.isStraight()) { + // errors.append(" STRAIGHT_JOIN "); + // } else if (join.isApply()) { + // errors.append(" APPLY "); + // } else { + // errors.append(" JOIN "); + // } + // + // } + // + // FromItem fromItem = join.getRightItem(); + // fromItem.accept(this); + // if (join.isWindowJoin()) { + // errors.append(" WITHIN "); + // errors.append(join.getJoinWindow().toString()); + // } + // if (join.getOnExpression() != null) { + // errors.append(" ON "); + // join.getOnExpression().accept(expressionVisitor); + // } + // if (join.getUsingColumns() != null) { + // errors.append(" USING ("); + // for (Iterator iterator = join.getUsingColumns().iterator(); iterator.hasNext();) { + // Column column = iterator.next(); + // errors.append(column.toString()); + // if (iterator.hasNext()) { + // errors.append(", "); + // } + // } + // errors.append(")"); + // } + + } + + @Override + public void visit(SetOperationList list) { + // for (int i = 0; i < list.getSelects().size(); i++) { + // if (i != 0) { + // errors.append(' ').append(list.getOperations().get(i - 1)).append(' '); + // } + // boolean brackets = list.getBrackets() == null || list.getBrackets().get(i); + // if (brackets) { + // errors.append("("); + // } + // list.getSelects().get(i).accept(this); + // if (brackets) { + // errors.append(")"); + // } + // } + // if (list.getOrderByElements() != null) { + // new OrderByDeParser(expressionVisitor, errors).deParse(list.getOrderByElements()); + // } + // + // if (list.getLimit() != null) { + // new LimitDeparser(errors).deParse(list.getLimit()); + // } + // if (list.getOffset() != null) { + // deparseOffset(list.getOffset()); + // } + // if (list.getFetch() != null) { + // deparseFetch(list.getFetch()); + // } + } + + @Override + public void visit(WithItem withItem) { + // if (withItem.isRecursive()) { + // errors.append("RECURSIVE "); + // } + // errors.append(withItem.getName()); + // if (withItem.getWithItemList() != null) { + // errors.append(" ").append(PlainSelect. + // getStringList(withItem.getWithItemList(), true, true)); + // } + // errors.append(" AS ("); + // withItem.getSelectBody().accept(this); + // errors.append(")"); + } + + @Override + public void visit(LateralSubSelect lateralSubSelect) { + // errors.append(lateralSubSelect.toString()); + } + + @Override + public void visit(ValuesList valuesList) { + // errors.append(valuesList.toString()); + } + + @Override + public void visit(AllColumns allColumns) { + // errors.append('*'); + } + + @Override + public void visit(TableFunction tableFunction) { + // errors.append(tableFunction.toString()); + } + + @Override + public void visit(ParenthesisFromItem parenthesis) { + // errors.append("("); + // parenthesis.getFromItem().accept(this); + // errors.append(")"); + // if (parenthesis.getAlias() != null) { + // errors.append(parenthesis.getAlias().toString()); + // } + } + + @Override + public void visit(ValuesStatement values) { + // new ValuesStatementDeParser(expressionVisitor, errors).deParse(values); + } + + private void deparseOptimizeFor(OptimizeFor optimizeFor) { + // errors.append(" OPTIMIZE FOR "); + // errors.append(optimizeFor.getRowCount()); + // errors.append(" ROWS"); + } + + @Override + public Map> getValidationErrors() { + Validation.mergeTo(expressionVisitor.getValidationErrors(), errors); + return errors; + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/StatementValidator.java b/src/main/java/net/sf/jsqlparser/util/validation/StatementValidator.java new file mode 100644 index 000000000..4ad1b1905 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/StatementValidator.java @@ -0,0 +1,318 @@ +/*- + * #%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.util.validation; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Set; +import net.sf.jsqlparser.statement.Block; +import net.sf.jsqlparser.statement.Commit; +import net.sf.jsqlparser.statement.CreateFunctionalStatement; +import net.sf.jsqlparser.statement.DeclareStatement; +import net.sf.jsqlparser.statement.DescribeStatement; +import net.sf.jsqlparser.statement.ExplainStatement; +import net.sf.jsqlparser.statement.SetStatement; +import net.sf.jsqlparser.statement.ShowColumnsStatement; +import net.sf.jsqlparser.statement.ShowStatement; +import net.sf.jsqlparser.statement.StatementVisitor; +import net.sf.jsqlparser.statement.Statements; +import net.sf.jsqlparser.statement.UseStatement; +import net.sf.jsqlparser.statement.alter.Alter; +import net.sf.jsqlparser.statement.alter.sequence.AlterSequence; +import net.sf.jsqlparser.statement.comment.Comment; +import net.sf.jsqlparser.statement.create.index.CreateIndex; +import net.sf.jsqlparser.statement.create.schema.CreateSchema; +import net.sf.jsqlparser.statement.create.sequence.CreateSequence; +import net.sf.jsqlparser.statement.create.table.CreateTable; +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.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.Merge; +import net.sf.jsqlparser.statement.replace.Replace; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.truncate.Truncate; +import net.sf.jsqlparser.statement.update.Update; +import net.sf.jsqlparser.statement.upsert.Upsert; +import net.sf.jsqlparser.statement.values.ValuesStatement; + +public class StatementValidator implements StatementVisitor, Validation { + + protected Map> errors; + private ExpressionValidator expressionValidator; + private SelectValidator selectValidator; + + public StatementValidator() { + this(new EnumMap<>(DatabaseType.class)); + } + + public StatementValidator(Map> errors) { + this(new ExpressionValidator(), new SelectValidator(), errors); + } + + public StatementValidator(ExpressionValidator expressionDeParser, SelectValidator selectValidator, + Map> errors) { + this.expressionValidator = expressionDeParser; + this.selectValidator = selectValidator; + this.errors = errors; + } + + @Override + public void visit(CreateIndex createIndex) { + // CreateIndexDeParser createIndexDeParser = new CreateIndexDeParser(errors); + // createIndexDeParser.deParse(createIndex); + } + + @Override + public void visit(CreateTable createTable) { + // CreateTableDeParser createTableDeParser = new CreateTableDeParser(this, buffer); + // createTableDeParser.deParse(createTable); + } + + @Override + public void visit(CreateView createView) { + // CreateViewDeParser createViewDeParser = new CreateViewDeParser(buffer); + // createViewDeParser.deParse(createView); + } + + @Override + public void visit(AlterView alterView) { + // AlterViewDeParser alterViewDeParser = new AlterViewDeParser(buffer); + // alterViewDeParser.deParse(alterView); + } + + @Override + public void visit(Delete delete) { + // selectValidator.setBuffer(buffer); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(buffer); + // selectValidator.setExpressionVisitor(expressionDeParser); + // DeleteDeParser deleteDeParser = new DeleteDeParser(expressionDeParser, buffer); + // deleteDeParser.deParse(delete); + } + + @Override + public void visit(Drop drop) { + // DropDeParser dropDeParser = new DropDeParser(buffer); + // dropDeParser.deParse(drop); + } + + @Override + public void visit(Insert insert) { + // selectValidator.setBuffer(buffer); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(buffer); + // selectValidator.setExpressionVisitor(expressionDeParser); + // InsertDeParser insertDeParser = new InsertDeParser(expressionDeParser, + // selectValidator, buffer); + // insertDeParser.deParse(insert); + } + + @Override + public void visit(Replace replace) { + // selectValidator.setBuffer(buffer); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(buffer); + // selectValidator.setExpressionVisitor(expressionDeParser); + // ReplaceDeParser replaceDeParser = new ReplaceDeParser(expressionDeParser, + // selectValidator, buffer); + // replaceDeParser.deParse(replace); + } + + @Override + public void visit(Select select) { + // selectValidator.setBuffer(errors); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(errors); + // selectValidator.setExpressionVisitor(expressionDeParser); + // if (select.getWithItemsList() != null && !select.getWithItemsList().isEmpty()) { + // errors.append("WITH "); + // for (Iterator iter = select.getWithItemsList().iterator(); iter.hasNext();) { + // WithItem withItem = iter.next(); + // withItem.accept(selectValidator); + // if (iter.hasNext()) { + // errors.append(","); + // } + // errors.append(" "); + // } + // } + select.getSelectBody().accept(selectValidator); + } + + @Override + public void visit(Truncate truncate) { + // errors.append("TRUNCATE TABLE "); + // errors.append(truncate.getTable()); + // if (truncate.getCascade()) { + // errors.append(" CASCADE"); + // } + } + + @Override + public void visit(Update update) { + // selectValidator.setBuffer(errors); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(errors); + // UpdateDeParser updateDeParser = new UpdateDeParser(expressionDeParser, selectValidator, errors); + // selectValidator.setExpressionVisitor(expressionDeParser); + // updateDeParser.deParse(update); + + } + + @Override + public void visit(Alter alter) { + // AlterDeParser alterDeParser = new AlterDeParser(errors); + // alterDeParser.deParse(alter); + // + } + + @Override + public void visit(Statements stmts) { + // stmts.accept(this); + } + + @Override + public void visit(Execute execute) { + // selectValidator.setBuffer(errors); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(errors); + // ExecuteDeParser executeDeParser = new ExecuteDeParser(expressionDeParser, errors); + // selectValidator.setExpressionVisitor(expressionDeParser); + // executeDeParser.deParse(execute); + } + + @Override + public void visit(SetStatement set) { + // selectValidator.setBuffer(errors); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(errors); + // SetStatementDeParser setStatementDeparser = new SetStatementDeParser(expressionDeParser, errors); + // selectValidator.setExpressionVisitor(expressionDeParser); + // setStatementDeparser.deParse(set); + } + + @Override + public void visit(Merge merge) { + //TODO implementation of a deparser + // errors.append(merge.toString()); + } + + @Override + public void visit(Commit commit) { + // errors.append(commit.toString()); + } + + @Override + public void visit(Upsert upsert) { + // selectValidator.setBuffer(errors); + // expressionDeParser.setSelectVisitor(selectValidator); + // expressionDeParser.setBuffer(errors); + // selectValidator.setExpressionVisitor(expressionDeParser); + // UpsertDeParser upsertDeParser = new UpsertDeParser(expressionDeParser, selectValidator, errors); + // upsertDeParser.deParse(upsert); + } + + @Override + public void visit(UseStatement use) { + // new UseStatementDeParser(errors).deParse(use); + } + + @Override + public void visit(ShowColumnsStatement show) { + // new ShowColumnsStatementDeParser(errors).deParse(show); + } + + @Override + public void visit(Block block) { + // errors.append("BEGIN\n"); + // if (block.getStatements() != null) { + // for (Statement stmt : block.getStatements().getStatements()) { + // stmt.accept(this); + // errors.append(";\n"); + // } + // } + // errors.append("END"); + } + + @Override + public void visit(Comment comment) { + // errors.append(comment.toString()); + } + + @Override + public void visit(ValuesStatement values) { + // expressionDeParser.setBuffer(errors); + // new ValuesStatementDeParser(expressionDeParser, errors).deParse(values); + } + + @Override + public void visit(DescribeStatement describe) { + // errors.append("DESCRIBE "); + // errors.append(describe.getTable()); + } + + @Override + public void visit(ExplainStatement explain) { + // errors.append("EXPLAIN "); + // if (explain.getOptions() != null) { + // errors.append(explain.getOptions().values().stream().map(ExplainStatement.Option::formatOption) + // .collect(Collectors.joining(" "))); + // errors.append(" "); + // } + // explain.getStatement().accept(this); + } + + @Override + public void visit(ShowStatement show) { + // new ShowStatementDeParser(errors).deParse(show); + } + + @Override + public void visit(DeclareStatement declare) { + // expressionDeParser.setBuffer(errors); + // new DeclareStatementDeParser(expressionDeParser, errors).deParse(declare); + } + + @Override + public void visit(Grant grant) { + // GrantDeParser grantDeParser = new GrantDeParser(errors); + // grantDeParser.deParse(grant); + } + + @Override + public void visit(CreateSchema aThis) { + // errors.append(aThis.toString()); + } + + @Override + public void visit(CreateSequence createSequence) { + // new CreateSequenceDeParser(errors).deParse(createSequence); + } + + @Override + public void visit(AlterSequence alterSequence) { + // new AlterSequenceDeParser(errors).deParse(alterSequence); + } + + @Override + public void visit(CreateFunctionalStatement createFunctionalStatement) { + // errors.append(createFunctionalStatement.toString()); + } + + @Override + public Map> getValidationErrors() { + Validation.mergeTo(this.expressionValidator.getValidationErrors(), errors); + Validation.mergeTo(this.selectValidator.getValidationErrors(), errors); + return errors; + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/validation/Validation.java b/src/main/java/net/sf/jsqlparser/util/validation/Validation.java new file mode 100644 index 000000000..a79f73fc2 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/util/validation/Validation.java @@ -0,0 +1,102 @@ +package net.sf.jsqlparser.util.validation; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +public interface Validation { + + /** + * @param databaseTypes + * @return true, if the given databaseTypes support this feature. + * false otherwise. + */ + default boolean isSupported() { + return getValidationErrors().isEmpty(); + } + + default boolean isSupported(DatabaseType... databaseTypes) { + return getValidationErrors(databaseTypes).isEmpty(); + } + + /** + * Overwrite this method, if the feature support is not given on any + * {@link DatabaseType} + * + * @param databaseTypes + * @return the requested databaseTypes mapped to a list of error-messages + * (containing hints to used sql-string + * snippets not supported). + */ + public Map> getValidationErrors(); + + default Map> getValidationErrors(DatabaseType... databaseTypes) { + Map> map = new EnumMap<>(DatabaseType.class); + + EnumSet notRequested = EnumSet.allOf(DatabaseType.class); + notRequested.removeAll(Arrays.asList(databaseTypes)); + + map.putAll(getValidationErrors()); + + for (DatabaseType type : notRequested) { + map.remove(type); + } + return map; + } + + /** + * Utility-function to map all {@link DatabaseType}'s except the supported ones + * to error-messages (containing hints to used sql-string + * snippets not supported). + * + * @param databaseTypes + * @param unsupportedSqlOrFeature + * @return + */ + static Map> mapAllExcept(EnumSet databaseTypes, + String... unsupportedSqlOrFeature) { + EnumSet set = EnumSet.allOf(DatabaseType.class); + set.removeAll(databaseTypes); + List asList = Arrays.asList(unsupportedSqlOrFeature); + return set.stream().collect( + Collectors.toMap(Function.identity(), k -> new HashSet<>(asList))); + } + + /** + * Utility-function to map all {@link DatabaseType}'s except the supported ones + * to error-messages (containing hints to used sql-string + * snippets not supported). + * + * @param target + * @param databaseTypes + * @param unsupportedSqlOrFeature + * @return the given target-map containing the errors + */ + static Map> mapAllExcept(Map> target, + EnumSet databaseTypes, String... unsupportedSqlOrFeature) { + return mergeTo(mapAllExcept(databaseTypes, unsupportedSqlOrFeature), target); + } + + /** + * merge source-map to target-map + * + * @param source + * @param target + * @return + */ + static Map> mergeTo(Map> source, + Map> target) { + for (Entry> errors : source.entrySet()) { + target.computeIfAbsent(errors.getKey(), k -> errors.getValue()).addAll(errors.getValue()); + } + return target; + } + +} diff --git a/src/test/java/net/sf/jsqlparser/validation/ValidationTest.java b/src/test/java/net/sf/jsqlparser/validation/ValidationTest.java new file mode 100644 index 000000000..76af3303a --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/validation/ValidationTest.java @@ -0,0 +1,38 @@ +package net.sf.jsqlparser.validation; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.util.validation.DatabaseType; +import net.sf.jsqlparser.util.validation.StatementValidator; + +public class ValidationTest { + + // public static class ValidationVisitor implements ModelVisitor + // { + // + // } + + @Test + public void testValidaton() throws JSQLParserException { + String sql = "SELECT * FROM tab1, tab2 WHERE tab1.id (+) = tab2.ref"; + Statement stmt = CCJSqlParserUtil.parse(sql); + + StatementValidator validator = new StatementValidator(); + stmt.accept(validator); + + Map> unsupportedErrors = validator.getValidationErrors(DatabaseType.sqlserver); + assertNotNull(unsupportedErrors); + assertEquals(1, unsupportedErrors.size()); + assertEquals(new HashSet<>(Arrays.asList("oldOracleJoinSyntax=1 not supported")), + unsupportedErrors.get(DatabaseType.sqlserver)); + } + +}