Skip to content

Commit 8c735be

Browse files
authored
Validation visitor framework (#1045)
* * add with prefix for fluent setters. #1004 * add getters * * add with prefix for fluent setters. (revert to chaining setters, do not break current api) #1004 * * add with prefix for fluent setters. (revert to chaining setters, do not break current api) #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 #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 #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 * #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
1 parent ac74622 commit 8c735be

File tree

110 files changed

+9189
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+9189
-81
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@
5555
<version>3.10</version>
5656
<scope>test</scope>
5757
</dependency>
58+
<dependency>
59+
<groupId>com.h2database</groupId>
60+
<artifactId>h2</artifactId>
61+
<version>1.4.200</version>
62+
<scope>test</scope>
63+
</dependency>
64+
5865
</dependencies>
5966

6067
<developers>

src/main/java/net/sf/jsqlparser/JSQLParserException.java

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,51 +11,22 @@
1111

1212
public class JSQLParserException extends Exception {
1313

14-
private static final long serialVersionUID = -1099039459759769980L;
15-
private Throwable cause = null;
14+
private static final long serialVersionUID = -4200894355696788796L;
1615

1716
public JSQLParserException() {
1817
super();
1918
}
2019

21-
public JSQLParserException(String arg0) {
22-
super(arg0);
20+
public JSQLParserException(String message, Throwable cause) {
21+
super(message, cause);
2322
}
2423

25-
public JSQLParserException(Throwable arg0) {
26-
this.cause = arg0;
24+
public JSQLParserException(String message) {
25+
super(message);
2726
}
2827

29-
public JSQLParserException(String arg0, Throwable arg1) {
30-
super(arg0);
31-
this.cause = arg1;
28+
public JSQLParserException(Throwable cause) {
29+
super(cause == null ? null : cause.getMessage(), cause);
3230
}
3331

34-
@Override
35-
public synchronized Throwable getCause() {
36-
return cause;
37-
}
38-
39-
@Override
40-
public void printStackTrace() {
41-
printStackTrace(System.err);
42-
}
43-
44-
@Override
45-
public void printStackTrace(java.io.PrintWriter pw) {
46-
super.printStackTrace(pw);
47-
if (cause != null) {
48-
pw.println("Caused by:");
49-
cause.printStackTrace(pw);
50-
}
51-
}
52-
53-
@Override
54-
public void printStackTrace(java.io.PrintStream ps) {
55-
super.printStackTrace(ps);
56-
if (cause != null) {
57-
ps.println("Caused by:");
58-
cause.printStackTrace(ps);
59-
}
60-
}
6132
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2020 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.parser;
11+
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
15+
import net.sf.jsqlparser.parser.feature.Feature;
16+
import net.sf.jsqlparser.parser.feature.FeatureConfiguration;
17+
18+
public abstract class AbstractJSqlParser<P> {
19+
20+
protected int jdbcParameterIndex = 0;
21+
protected boolean errorRecovery = false;
22+
protected List<ParseException> parseErrors = new ArrayList<>();
23+
24+
public P withSquareBracketQuotation(boolean allowSquareBracketQuotation) {
25+
return withFeature(Feature.allowSquareBracketQuotation, allowSquareBracketQuotation);
26+
}
27+
28+
public P withFeature(Feature f, boolean enabled) {
29+
getConfiguration().setValue(f, enabled);
30+
return me();
31+
}
32+
33+
public abstract FeatureConfiguration getConfiguration();
34+
35+
public abstract P me();
36+
37+
public boolean getAsBoolean(Feature f) {
38+
return getConfiguration().getAsBoolean(f);
39+
}
40+
41+
public void setErrorRecovery(boolean errorRecovery) {
42+
this.errorRecovery = errorRecovery;
43+
}
44+
45+
public List<ParseException> getParseErrors() {
46+
return parseErrors;
47+
}
48+
49+
}

src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.parser;
1111

12+
import java.io.IOException;
1213
import java.io.InputStream;
1314
import java.io.Reader;
1415
import java.util.function.Consumer;
@@ -29,11 +30,7 @@ private CCJSqlParserUtil() {
2930

3031
public static Statement parse(Reader statementReader) throws JSQLParserException {
3132
CCJSqlParser parser = new CCJSqlParser(new StreamProvider(statementReader));
32-
try {
33-
return parser.Statement();
34-
} catch (Exception ex) {
35-
throw new JSQLParserException(ex);
36-
}
33+
return parseStatement(parser);
3734
}
3835

3936
public static Statement parse(String sql) throws JSQLParserException {
@@ -42,32 +39,40 @@ public static Statement parse(String sql) throws JSQLParserException {
4239

4340
/**
4441
* Parses an sql statement while allowing via consumer to configure the used parser before.
45-
*
42+
*
4643
* For instance to activate SQLServer bracket quotation on could use:
47-
*
48-
* {@code
44+
*
45+
* {@code
4946
* CCJSqlParserUtil.parse("select * from [mytable]", parser -> parser.withSquareBracketQuotation(true));
5047
* }
51-
*
48+
*
5249
* @param sql
5350
* @param consumer
5451
* @return
55-
* @throws JSQLParserException
52+
* @throws JSQLParserException
5653
*/
5754
public static Statement parse(String sql, Consumer<CCJSqlParser> consumer) throws JSQLParserException {
58-
CCJSqlParser parser = new CCJSqlParser(new StringProvider(sql));
55+
CCJSqlParser parser = newParser(sql);
5956
if (consumer != null) {
6057
consumer.accept(parser);
6158
}
62-
try {
63-
return parser.Statement();
64-
} catch (Exception ex) {
65-
throw new JSQLParserException(ex);
66-
}
59+
return parseStatement(parser);
60+
}
61+
62+
public static CCJSqlParser newParser(String sql) {
63+
return new CCJSqlParser(new StringProvider(sql));
64+
}
65+
66+
public static CCJSqlParser newParser(InputStream is) throws IOException {
67+
return new CCJSqlParser(new StreamProvider(is));
68+
}
69+
70+
public static CCJSqlParser newParser(InputStream is, String encoding) throws IOException {
71+
return new CCJSqlParser(new StreamProvider(is, encoding));
6772
}
6873

6974
public static Node parseAST(String sql) throws JSQLParserException {
70-
CCJSqlParser parser = new CCJSqlParser(new StringProvider(sql));
75+
CCJSqlParser parser = newParser(sql);
7176
try {
7277
parser.Statement();
7378
return parser.jjtree.rootNode();
@@ -78,7 +83,7 @@ public static Node parseAST(String sql) throws JSQLParserException {
7883

7984
public static Statement parse(InputStream is) throws JSQLParserException {
8085
try {
81-
CCJSqlParser parser = new CCJSqlParser(new StreamProvider(is));
86+
CCJSqlParser parser = newParser(is);
8287
return parser.Statement();
8388
} catch (Exception ex) {
8489
throw new JSQLParserException(ex);
@@ -87,7 +92,7 @@ public static Statement parse(InputStream is) throws JSQLParserException {
8792

8893
public static Statement parse(InputStream is, String encoding) throws JSQLParserException {
8994
try {
90-
CCJSqlParser parser = new CCJSqlParser(new StreamProvider(is, encoding));
95+
CCJSqlParser parser = newParser(is, encoding);
9196
return parser.Statement();
9297
} catch (Exception ex) {
9398
throw new JSQLParserException(ex);
@@ -99,7 +104,7 @@ public static Expression parseExpression(String expression) throws JSQLParserExc
99104
}
100105

101106
public static Expression parseExpression(String expression, boolean allowPartialParse) throws JSQLParserException {
102-
CCJSqlParser parser = new CCJSqlParser(new StringProvider(expression));
107+
CCJSqlParser parser = newParser(expression);
103108
try {
104109
Expression expr = parser.SimpleExpression();
105110
if (!allowPartialParse && parser.getNextToken().kind != CCJSqlParserTokenManager.EOF) {
@@ -113,20 +118,28 @@ public static Expression parseExpression(String expression, boolean allowPartial
113118
}
114119
}
115120

121+
/**
122+
* Parse an conditional expression. This is the expression after a where clause.
123+
* Partial parsing is enabled.
124+
*
125+
* @param condExpr
126+
* @return the expression parsed
127+
* @see #parseCondExpression(String, boolean)
128+
*/
116129
public static Expression parseCondExpression(String condExpr) throws JSQLParserException {
117130
return parseCondExpression(condExpr, true);
118131
}
119132

120133
/**
121-
* Parse an conditional expression. This is the expression after a where
122-
* clause.
134+
* Parse an conditional expression. This is the expression after a where clause.
123135
*
124136
* @param condExpr
125137
* @param allowPartialParse false: needs the whole string to be processed.
126-
* @return
138+
* @return the expression parsed
139+
* @see #parseCondExpression(String)
127140
*/
128141
public static Expression parseCondExpression(String condExpr, boolean allowPartialParse) throws JSQLParserException {
129-
CCJSqlParser parser = new CCJSqlParser(new StringProvider(condExpr));
142+
CCJSqlParser parser = newParser(condExpr);
130143
try {
131144
Expression expr = parser.Expression();
132145
if (!allowPartialParse && parser.getNextToken().kind != CCJSqlParserTokenManager.EOF) {
@@ -140,11 +153,35 @@ public static Expression parseCondExpression(String condExpr, boolean allowParti
140153
}
141154
}
142155

156+
/**
157+
* @param parser
158+
* @return the statement parsed
159+
* @throws JSQLParserException
160+
*/
161+
public static Statement parseStatement(CCJSqlParser parser) throws JSQLParserException {
162+
try {
163+
return parser.Statement();
164+
} catch (Exception ex) {
165+
throw new JSQLParserException(ex);
166+
}
167+
}
168+
143169
/**
144170
* Parse a statement list.
171+
*
172+
* @return the statements parsed
145173
*/
146174
public static Statements parseStatements(String sqls) throws JSQLParserException {
147-
CCJSqlParser parser = new CCJSqlParser(new StringProvider(sqls));
175+
CCJSqlParser parser = newParser(sqls);
176+
return parseStatements(parser);
177+
}
178+
179+
/**
180+
* @param parser
181+
* @return the statements parsed
182+
* @throws JSQLParserException
183+
*/
184+
public static Statements parseStatements(CCJSqlParser parser) throws JSQLParserException {
148185
try {
149186
return parser.Statements();
150187
} catch (Exception ex) {
@@ -154,7 +191,7 @@ public static Statements parseStatements(String sqls) throws JSQLParserException
154191

155192
public static void streamStatements(StatementListener listener, InputStream is, String encoding) throws JSQLParserException {
156193
try {
157-
CCJSqlParser parser = new CCJSqlParser(new StreamProvider(is, encoding));
194+
CCJSqlParser parser = newParser(is, encoding);
158195
while (true) {
159196
Statement stmt = parser.SingleStatement();
160197
listener.accept(stmt);

0 commit comments

Comments
 (0)