Repository navigation
Expand file tree
/
Copy pathLookaheadCleanupTest.java
More file actions
163 lines (150 loc) · 8.09 KB
/
Copy pathLookaheadCleanupTest.java
File metadata and controls
163 lines (150 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*-
* #%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.parser;
import static org.junit.jupiter.api.Assertions.*;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
import net.sf.jsqlparser.statement.ConnectionDefinition;
import net.sf.jsqlparser.statement.CloudConnectionDefinition;
import net.sf.jsqlparser.statement.export.DBMSDestination;
import org.junit.jupiter.api.Test;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.MySqlSelectIntoClause;
import net.sf.jsqlparser.statement.execute.Execute;
import net.sf.jsqlparser.statement.lock.LockStatement;
import net.sf.jsqlparser.statement.create.rule.CreateRule;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.notify.NotifyStatement;
import net.sf.jsqlparser.expression.LongValue;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class LookaheadCleanupTest {
@ParameterizedTest
@ValueSource(strings = {"EXA AT conn TABLE t", "ORA AT conn TABLE schemaName.tableName",
"JDBC DRIVER = 'driverName' AT conn TABLE \"t\"",
"EXA AT conn TABLE t (c1, c2) REPLACE TRUNCATE"})
void dispatchesTableDestinationsWithCompleteConsumption(String sql) throws Exception {
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);
DBMSDestination destination = parser.DBMSDestination();
assertNotNull(destination.getTable());
assertNull(destination.getStatement());
assertNotNull(destination.getConnectionDefinition());
assertEquals(CCJSqlParserConstants.EOF, parser.getToken(1).kind);
assertSqlCanBeParsedAndDeparsed("EXPORT sourceTable INTO " + sql, true,
p -> p.withDialect(Dialect.EXASOL));
}
@ParameterizedTest
@ValueSource(strings = {"EXA AT conn STATEMENT 'insert into t values (?)'",
"ORA AT conn STATEMENT 'insert into t values (?)'"})
void preservesStatementDestinations(String sql) throws Exception {
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);
DBMSDestination destination = parser.DBMSDestination();
assertNull(destination.getTable());
assertEquals("insert into t values (?)", destination.getStatement().getValue());
assertEquals(CCJSqlParserConstants.EOF, parser.getToken(1).kind);
assertSqlCanBeParsedAndDeparsed("EXPORT sourceTable INTO " + sql, true,
p -> p.withDialect(Dialect.EXASOL));
}
@ParameterizedTest
@ValueSource(strings = {"EXA AT conn TABLE", "ORA AT conn STATEMENT", "EXA AT conn SELECT t"})
void rejectsIncompleteAndWrongDestinationPrefixes(String sql) {
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);
assertThrows(ParseException.class, parser::DBMSDestination);
if (sql.endsWith("TABLE")) {
assertEquals(CCJSqlParserConstants.K_TABLE, parser.getToken(0).kind);
assertEquals(CCJSqlParserConstants.EOF, parser.getToken(1).kind);
}
}
@ParameterizedTest
@ValueSource(strings = {"AT conn", "AT '127.0.0.1'", "AT CLOUD NONE conn",
"AT CLOUD AZURE BLOBSTORAGE conn"})
void preservesCloudAndOrdinaryConnections(String sql) throws Exception {
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);
ConnectionDefinition connection = parser.ConnectionOrCloudConnectionDefinition();
if (sql.startsWith("AT CLOUD")) {
assertInstanceOf(CloudConnectionDefinition.class, connection);
} else {
assertEquals(ConnectionDefinition.class, connection.getClass());
}
assertEquals(CCJSqlParserConstants.EOF, parser.getToken(1).kind);
assertSqlCanBeParsedAndDeparsed("EXPORT sourceTable INTO CSV " + sql + " FILE 'file.csv'",
true, p -> p.withDialect(Dialect.EXASOL));
}
@ParameterizedTest
@ValueSource(strings = {"SELECT id FROM t LIMIT 7 OFFSET 2",
"SELECT id FROM t UNION ALL SELECT id FROM u LIMIT 7 OFFSET 2"})
void boundedSelectTailsKeepTheirAstAndFollowingStatement(String sql) throws Exception {
Select select = (Select) complete(sql);
assertEquals(7, ((LongValue) select.getLimit().getRowCount()).getValue());
assertEquals(2, ((LongValue) select.getOffset().getOffset()).getValue());
assertEquals("SELECT 42", CCJSqlParserUtil.parseStatements(sql + "; SELECT 42").get(1)
.toString());
}
@Test
void boundedFetchKeepsItsCount() throws Exception {
Select select = (Select) complete("SELECT id FROM t OFFSET 2 ROWS FETCH NEXT 7 ROWS ONLY");
assertEquals(2, ((LongValue) select.getOffset().getOffset()).getValue());
assertEquals(7, ((LongValue) select.getFetch().getExpression()).getValue());
}
@ParameterizedTest
@ValueSource(strings = {"SELECT a INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' "
+ "OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY 'end' FROM t",
"SELECT a FROM t INTO OUTFILE '/tmp/result.txt' COLUMNS TERMINATED BY ',' "
+ "OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY 'end'"})
void boundedOutfileOptionsKeepTheirOrderingAndValues(String sql) throws Exception {
MySqlSelectIntoClause into = ((Select) complete(sql)).getPlainSelect()
.getMySqlSelectIntoClause();
assertEquals(MySqlSelectIntoClause.Type.OUTFILE, into.getType());
assertEquals("/tmp/result.txt", into.getFileName().getValue());
assertEquals(",", into.getFieldsTerminatedBy().getValue());
assertTrue(into.isFieldsOptionallyEnclosed());
assertEquals("end", into.getLinesTerminatedBy().getValue());
}
@Test
void boundedParenthesesKeepExecutionArgumentsAndRuleActions() throws Exception {
Execute execute = (Execute) complete("CALL p (:a, :b)");
assertEquals("p", execute.getName());
assertEquals(2, execute.getExprList().size());
assertEquals(":a", execute.getExprList().get(0).toString());
assertEquals(":b", execute.getExprList().get(1).toString());
CreateRule rule = (CreateRule) complete("CREATE RULE r AS ON INSERT TO t DO "
+ "(INSERT INTO log VALUES (9); NOTIFY ch, 'changed')");
assertEquals(2, rule.getActions().size());
assertEquals("log", ((Insert) rule.getActions().get(0)).getTable().getName());
assertEquals("changed",
((NotifyStatement) rule.getActions().get(1)).getPayload().getValue());
}
@ParameterizedTest
@ValueSource(strings = {"LOCK TABLE a IN SHARE MODE WAIT 5", "LOCK a IN SHARE MODE WAIT 5"})
void boundedTableKeywordKeepsLockTargetAndWait(String sql) throws Exception {
LockStatement lock = (LockStatement) complete(sql);
assertEquals(sql.startsWith("LOCK TABLE"), lock.isUseTableKeyword());
assertEquals("a", lock.getTable().getName());
assertEquals("SHARE", lock.getLockMode().getValue());
assertEquals(5L, lock.getWaitSeconds());
}
@ParameterizedTest
@ValueSource(strings = {"SELECT id FROM t LIMIT", "SELECT id FROM t OFFSET",
"SELECT id FROM t FETCH NEXT", "CALL p (", "CALL p (:a,)", "LOCK TABLE",
"CREATE RULE r AS ON INSERT TO t DO (NOTIFY ch", "SELECT a FROM t INTO OUTFILE 'x' "
+ "LINES TERMINATED BY 'end' FIELDS TERMINATED BY ','"})
void boundedGuardsRejectIncompleteAndReorderedNeighbors(String sql) {
assertThrows(net.sf.jsqlparser.JSQLParserException.class,
() -> CCJSqlParserUtil.parse(sql));
}
private static Statement complete(String sql) throws Exception {
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql);
Statement statement = parser.Statement();
assertEquals(CCJSqlParserConstants.EOF, parser.getToken(1).kind);
assertEquals(statement.toString(), CCJSqlParserUtil.parse(statement.toString()).toString());
return statement;
}
}