16 package org.apache.calcite.prepare;
18 import com.google.common.collect.ImmutableList;
20 import org.apache.calcite.sql.SqlBasicCall;
21 import org.apache.calcite.sql.SqlDataTypeSpec;
22 import org.apache.calcite.sql.SqlDelete;
23 import org.apache.calcite.sql.SqlIdentifier;
24 import org.apache.calcite.sql.SqlInsert;
25 import org.apache.calcite.sql.SqlJoin;
26 import org.apache.calcite.sql.SqlKind;
27 import org.apache.calcite.sql.SqlLiteral;
28 import org.apache.calcite.sql.SqlNode;
29 import org.apache.calcite.sql.SqlNodeList;
30 import org.apache.calcite.sql.SqlOrderBy;
31 import org.apache.calcite.sql.SqlSelect;
32 import org.apache.calcite.sql.SqlUpdate;
33 import org.apache.calcite.sql.SqlWith;
34 import org.apache.calcite.sql.SqlWithItem;
35 import org.apache.calcite.sql.parser.SqlParser;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import java.lang.reflect.Method;
40 import java.lang.reflect.Modifier;
41 import java.util.Collection;
42 import java.util.HashSet;
43 import java.util.IdentityHashMap;
46 import java.util.Stack;
47 import java.util.concurrent.ConcurrentHashMap;
55 LoggerFactory.getLogger(SqlIdentifierCapturer.class);
58 new ConcurrentHashMap<>();
60 private IdentityHashMap<SqlNode, SqlNode>
visitedNodes =
new IdentityHashMap<>();
62 private Stack<Set<ImmutableList<String>>>
currentList =
new Stack<>();
64 public final Set<ImmutableList<String>>
selects =
new HashSet<>();
65 public final Set<ImmutableList<String>>
inserts =
new HashSet<>();
66 public final Set<ImmutableList<String>>
updates =
new HashSet<>();
67 public final Set<ImmutableList<String>>
deletes =
new HashSet<>();
69 private final Set<ImmutableList<String>>
ignore =
new HashSet<>();
71 { currentList.push(
ignore); }
78 if (root instanceof SqlLiteral || root instanceof SqlDataTypeSpec) {
86 if (root instanceof SqlNodeList) {
87 SqlNodeList snl = (SqlNodeList) root;
88 for (SqlNode node : snl) {
94 if (root instanceof SqlIdentifier) {
96 currentList.peek().add(((SqlIdentifier) root).names.reverse());
100 if (root instanceof SqlBasicCall) {
101 SqlBasicCall call = (SqlBasicCall) root;
102 if (call.getOperator().getKind() == SqlKind.ARGUMENT_ASSIGNMENT) {
107 if (call.operandCount() == 0) {
110 if (call.getOperands()[0].getKind() == SqlKind.CURSOR) {
111 SqlBasicCall cursor_call = (SqlBasicCall) call.getOperands()[0];
112 if (cursor_call.operandCount() == 0) {
115 scan(cursor_call.getOperands()[0]);
120 }
else if (call.getOperator().getKind() == SqlKind.AS) {
122 scan(call.getOperands()[0]);
127 if (root instanceof SqlOrderBy) {
128 scan(((SqlOrderBy) root).fetch);
129 scan(((SqlOrderBy) root).offset);
130 scan(((SqlOrderBy) root).query);
134 boolean needsPop =
false;
135 if (root instanceof SqlSelect) {
137 scan(((SqlSelect) root).getFrom());
141 }
else if (root instanceof SqlInsert) {
143 scan(((SqlInsert) root).getTargetTable());
147 }
else if (root instanceof SqlUpdate) {
149 scan(((SqlUpdate) root).getTargetTable());
153 }
else if (root instanceof SqlDelete) {
155 scan(((SqlDelete) root).getTargetTable());
159 }
else if (root instanceof SqlJoin) {
161 scan(((SqlJoin) root).getCondition());
166 for (Method m : methods) {
169 value = m.invoke(
root);
170 }
catch (Exception e) {
173 if (value instanceof SqlNode[]) {
174 SqlNode[] nodes = (SqlNode[]) value;
175 for (SqlNode node : nodes) {
178 }
else if (value instanceof SqlNode) {
179 scan((SqlNode) value);
180 }
else if (value instanceof Collection) {
181 for (Object vobj : ((Collection<?>) value)) {
182 if (vobj instanceof SqlNode) {
183 scan((SqlNode) vobj);
189 if (root instanceof SqlWith) {
190 SqlWith with = (SqlWith) root;
192 for (SqlNode node : with.withList) {
193 SqlWithItem item = (SqlWithItem) node;
194 selects.remove(((SqlIdentifier) item.name).names.reverse());
204 Class<?>
root = obj.getClass();
206 Set<Method> methods = GETTERS_CACHE.get(
root);
207 if (null != methods) {
210 methods =
new HashSet<>();
213 while (root != null) {
214 if (root == SqlNode.class)
break;
216 for (Method m : root.getDeclaredMethods()) {
217 if (m.getParameterTypes().length > 0)
continue;
219 if (!Modifier.isPublic(m.getModifiers()))
continue;
221 Class<?> returnType = m.getReturnType();
222 if (!SqlNode.class.isAssignableFrom(returnType) && SqlNode[].class != returnType
223 && !Collection.class.isAssignableFrom(returnType)) {
230 root = root.getSuperclass();
233 GETTERS_CACHE.put(obj.getClass(), methods);
240 out +=
" Selects: " +
selects +
"\n";
241 out +=
" Inserts: " +
inserts +
"\n";
242 out +=
" Updates: " +
updates +
"\n";
243 out +=
" Deletes: " +
deletes +
"\n";
244 out +=
" Ignore : " +
ignore +
"\n";
249 public static void main(String[]
args)
throws Exception {
250 String sql =
"UPDATE sales set f=(SELECT max(r.num) from report as r)";
251 sql =
"INSER INTO sales (a, b, c ) VALUES(10, (SELECT max(foo) from bob), 0)";
252 sql =
"SELECT * FROM sales a left outer join (select (select max(id) from rupert) from report2) r on a.id=(select max(r.di) from test)";
254 SqlParser
parser = SqlParser.create(sql);
257 capturer.scan(parser.parseQuery());
259 System.out.println(capturer.selects);
260 System.out.println(capturer.inserts);
261 System.out.println(capturer.updates);
262 System.out.println(capturer.deletes);
263 System.out.println(capturer.ignore);
final Set< ImmutableList< String > > inserts
static void main(String[] args)
final Set< ImmutableList< String > > updates
final Set< ImmutableList< String > > selects
final Set< ImmutableList< String > > ignore
static final Map< Class<?>, Set< Method > > GETTERS_CACHE
static final Logger HEAVYDBLOGGER
IdentityHashMap< SqlNode, SqlNode > visitedNodes
final Set< ImmutableList< String > > deletes
Set< Method > getRelevantGetters(Object obj)
Stack< Set< ImmutableList< String > > > currentList