Skip to content

Commit 7f8aace

Browse files
doc: document the new Visitors
Signed-off-by: Andreas Reichel <[email protected]>
1 parent 3f99548 commit 7f8aace

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

src/site/sphinx/index.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ Java SQL Parser Library
1212

1313
usage
1414
contribution
15-
migration
15+
migration47
16+
migration50
1617
SQL Grammar Stable <syntax_stable>
1718
SQL Grammar Snapshot <syntax_snapshot>
1819
Unsupported Grammar <unsupported>
@@ -51,6 +52,7 @@ Java SQL Parser Library
5152

5253

5354
**JSQLParser** is a SQL statement parser built from JavaCC. It translates SQLs in a traversable hierarchy of Java classes.
55+
The upcoming 5.0 release will depend on Java 11 and introduces new Visitors. Please see the :ref:`Migration to 5.0` guide.
5456

5557
Latest stable release: |JSQLPARSER_STABLE_VERSION_LINK|
5658

File renamed without changes.

src/site/sphinx/migration50.rst

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
*********************************
2+
Migration to 5.0
3+
*********************************
4+
5+
The new JSQLParser 5 introduces API-breaking changes:
6+
7+
1. **Dependency on Java 11 or newer**
8+
9+
2. **Reworked AST Visitors**
10+
11+
The AST Visitors have been reworked to pass a Generic Context from the Root Node down to the Leaves.
12+
13+
.. code-block:: java
14+
:caption: Generic Interface
15+
16+
public interface SelectVisitor<T> {
17+
18+
<S> T visit(PlainSelect plainSelect, S context);
19+
20+
default void visit(PlainSelect plainSelect) {
21+
this.visit(plainSelect, null);
22+
}
23+
24+
}
25+
26+
.. code-block:: java
27+
:caption: Sample Implementation
28+
29+
public class JSQLColumnResolver
30+
implements SelectVisitor<JdbcResultSetMetaData>, FromItemVisitor<JdbcResultSetMetaData> {
31+
32+
@Override
33+
public <S> JdbcResultSetMetaData visit(PlainSelect select, S context) {
34+
if (context instanceof JdbcMetaData) {
35+
return visit(select, (JdbcMetaData) context);
36+
}
37+
return null;
38+
}
39+
40+
public JdbcResultSetMetaData visit(PlainSelect select, JdbcMetaData metaData) {
41+
JdbcResultSetMetaData resultSetMetaData = new JdbcResultSetMetaData();
42+
43+
// Logic to retrieve the column information
44+
resultSetMetaData = getColumn(metaData, select.getFromItem(), select.getJoins());
45+
46+
return resultSetMetaData;
47+
}
48+
}
49+
50+
3. **Generic Result from Leaves to Root**
51+
52+
Node objects now return a Generic Result from the Leaves up to the Root.
53+
54+
.. code-block:: java
55+
:caption: AST Node
56+
57+
public class PlainSelect extends Select {
58+
@Override
59+
public <T, S> T accept(SelectVisitor<T> selectVisitor, S context) {
60+
return selectVisitor.visit(this, context);
61+
}
62+
}
63+
64+
How is this useful? Consider resolving the `AllColumns` ``*`` or `AllTableColumns` ``t.*`` expressions to retrieve the actual column names. This process depends on the database's physical metadata and the context of the current scope, including virtual data frames (like sub-selects and with-clauses).
65+
66+
Therefore, every branch of the AST must receive scoped metadata from its parent node. Each AST node must receive the resolved columns from its child nodes. A global result object (like the `StringBuilder` in the `DepParser` implementations) is inadequate.
67+
68+
Alternatively, consider substituting `TimeValueKey` (``CURRENT_DATE``, ``CURRENT_TIME``, etc.) with actual date or time values. You can push a simple `Map` of key/value pairs down to the Expression Visitor:
69+
70+
.. code-block:: java
71+
:caption: Expression Visitor
72+
73+
@Override
74+
public <S> StringBuilder visit(TimeKeyExpression expression, S context) {
75+
if (context instanceof Map) {
76+
return visit(expression, (Map<String, Object>) substitutions);
77+
} else {
78+
return expression.toString();
79+
}
80+
}
81+
82+
public StringBuilder visit(TimeKeyExpression expression, Map<String, Object> substitutions) {
83+
// Remove possible trailing brackets "()"
84+
String value = expression.getStringValue().toUpperCase().replaceAll("[()]", "");
85+
86+
if (substitutions.containsKey(value)) {
87+
// @todo: Cast Date/Time types
88+
return castDateTime(substitutions.get(value).toString()).accept(this, null);
89+
} else {
90+
return super.visit(expression, null);
91+
}
92+
}
93+
94+
Another advantage is parallel processing: Without relying on a global result object, the AST can be traversed in parallel (whereas it currently must be traversed strictly in serial).
95+
96+
Finally, any child node can now know its parent and identify who called it.

0 commit comments

Comments
 (0)