/src/main/java/com/alibaba/druid/support/opds/udf/SqlCodeStat.java

https://github.com/alibaba/druid · Java · 359 lines · 284 code · 75 blank · 0 comment · 52 complexity · 8007d011d429b7330eccf0b64ef25186 MD5 · raw file

  1. package com.alibaba.druid.support.opds.udf;
  2. import com.alibaba.druid.DbType;
  3. import com.alibaba.druid.sql.SQLUtils;
  4. import com.alibaba.druid.sql.ast.*;
  5. import com.alibaba.druid.sql.ast.expr.*;
  6. import com.alibaba.druid.sql.ast.statement.*;
  7. import com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;
  8. import com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;
  9. import com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;
  10. import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
  11. import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter;
  12. import com.alibaba.druid.sql.parser.SQLParserFeature;
  13. import com.alibaba.fastjson2.JSON;
  14. import com.alibaba.fastjson2.JSONWriter;
  15. import com.alibaba.fastjson2.annotation.JSONField;
  16. import com.aliyun.odps.udf.UDF;
  17. import java.util.List;
  18. public class SqlCodeStat extends UDF {
  19. public String evaluate(String sql) {
  20. return evaluate(sql, null, false);
  21. }
  22. public String evaluate(String sql, String dbTypeName) {
  23. return evaluate(sql, dbTypeName, false);
  24. }
  25. public String evaluate(String sql, String dbTypeName, boolean throwError) {
  26. DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);
  27. try {
  28. List<SQLStatement> stmtList = SQLUtils.parseStatements(
  29. sql,
  30. DbType.odps,
  31. SQLParserFeature.EnableMultiUnion,
  32. SQLParserFeature.EnableSQLBinaryOpExprGroup
  33. );
  34. CodeStatVisitor v = new CodeStatVisitor();
  35. for (SQLStatement stmt : stmtList) {
  36. stmt.accept(v);
  37. }
  38. return v.toString();
  39. } catch (Exception ex) {
  40. if (throwError) {
  41. throw new IllegalArgumentException("error sql : \n" + sql, ex);
  42. }
  43. return null;
  44. }
  45. }
  46. public static class SqlStat {
  47. @JSONField(ordinal = 0)
  48. public int statementCount;
  49. @JSONField(ordinal = 1)
  50. public int cte;
  51. @JSONField(ordinal = 2)
  52. public int union;
  53. @JSONField(ordinal = 3)
  54. public int select;
  55. @JSONField(ordinal = 4)
  56. public int groupBy;
  57. @JSONField(ordinal = 5)
  58. public int orderBy;
  59. @JSONField(ordinal = 6)
  60. public int from;
  61. @JSONField(ordinal = 7)
  62. public int join;
  63. @JSONField(ordinal = 8)
  64. public int over;
  65. @JSONField(ordinal = 9)
  66. public int subQuery;
  67. @JSONField(ordinal = 10)
  68. public int lateralView;
  69. @JSONField(ordinal = 40)
  70. public int insert;
  71. @JSONField(ordinal = 41)
  72. public int insertInto;
  73. @JSONField(ordinal = 42)
  74. public int insertOverwrite;
  75. @JSONField(ordinal = 43)
  76. public int insertSelect;
  77. @JSONField(ordinal = 44)
  78. public int insertMulti;
  79. @JSONField(ordinal = 51)
  80. public int update;
  81. @JSONField(ordinal = 52)
  82. public int delete;
  83. @JSONField(ordinal = 60)
  84. public int create;
  85. @JSONField(ordinal = 61)
  86. public int createTable;
  87. @JSONField(ordinal = 62)
  88. public int createView;
  89. @JSONField(ordinal = 70)
  90. public int drop;
  91. @JSONField(ordinal = 71)
  92. public int dropTable;
  93. @JSONField(ordinal = 72)
  94. public int dropView;
  95. @JSONField(ordinal = 80)
  96. public int set;
  97. @JSONField(ordinal = 90)
  98. public int alter;
  99. @JSONField(ordinal = 100)
  100. public int read;
  101. @JSONField(ordinal = 200)
  102. public int condition;
  103. @JSONField(ordinal = 201)
  104. public int joinCondition;
  105. @JSONField(ordinal = 202)
  106. public int valueCondition;
  107. @JSONField(ordinal = 203)
  108. public int otherCondition;
  109. @JSONField(ordinal = 204)
  110. public int limit;
  111. @JSONField(ordinal = 300)
  112. public int aggregate;
  113. @JSONField(ordinal = 201)
  114. public int functionCall;
  115. @JSONField(ordinal = 202)
  116. public int having;
  117. }
  118. static class CodeStatVisitor extends OdpsASTVisitorAdapter {
  119. SqlStat stat = new SqlStat();
  120. public void preVisit(SQLObject x) {
  121. if (x instanceof SQLStatement) {
  122. stat.statementCount++;
  123. if (x instanceof SQLInsertStatement) {
  124. stat.insert++;
  125. SQLInsertStatement insert = (SQLInsertStatement) x;
  126. if (insert.getQuery() != null) {
  127. stat.insertSelect++;
  128. }
  129. if (insert.isOverwrite()) {
  130. stat.insertOverwrite++;
  131. } else {
  132. stat.insertInto++;
  133. }
  134. } else if (x instanceof HiveMultiInsertStatement) {
  135. stat.insert++;
  136. stat.insertMulti++;
  137. stat.insertSelect++;
  138. for (HiveInsert item : ((HiveMultiInsertStatement) x).getItems()) {
  139. if (item.isOverwrite()) {
  140. stat.insertOverwrite++;
  141. } else {
  142. stat.insertInto++;
  143. }
  144. }
  145. } else if (x instanceof SQLDropStatement) {
  146. stat.drop++;
  147. if (x instanceof SQLDropTableStatement) {
  148. stat.dropTable++;
  149. } else if (x instanceof SQLDropViewStatement) {
  150. stat.dropView++;
  151. }
  152. } else if (x instanceof SQLCreateStatement) {
  153. stat.create++;
  154. if (x instanceof SQLCreateTableStatement) {
  155. stat.createTable++;
  156. } else if (x instanceof SQLCreateViewStatement) {
  157. stat.createView++;
  158. }
  159. } else if (x instanceof SQLDeleteStatement) {
  160. stat.delete++;
  161. } else if (x instanceof SQLUpdateStatement) {
  162. stat.update++;
  163. } else if (x instanceof SQLSetStatement) {
  164. stat.set++;
  165. } else if (x instanceof SQLAlterStatement) {
  166. stat.alter++;
  167. } else if (x instanceof OdpsReadStatement) {
  168. stat.read++;
  169. }
  170. }
  171. }
  172. public boolean visit(SQLUnionQuery x) {
  173. stat.union++;
  174. return true;
  175. }
  176. public boolean visit(SQLLateralViewTableSource x) {
  177. stat.lateralView++;
  178. return true;
  179. }
  180. public boolean visit(OdpsSelectQueryBlock x) {
  181. return visit((SQLSelectQueryBlock) x);
  182. }
  183. public boolean visit(SQLSelectQueryBlock x) {
  184. stat.select++;
  185. return true;
  186. }
  187. public boolean visit(SQLSelectGroupByClause x) {
  188. stat.groupBy++;
  189. if (x.getHaving() != null) {
  190. stat.having++;
  191. }
  192. return true;
  193. }
  194. public boolean visit(SQLLimit x) {
  195. stat.limit++;
  196. return false;
  197. }
  198. public boolean visit(SQLWithSubqueryClause.Entry x) {
  199. stat.cte++;
  200. return true;
  201. }
  202. public boolean visit(SQLOrderBy x) {
  203. stat.orderBy++;
  204. return true;
  205. }
  206. public boolean visit(SQLExprTableSource x) {
  207. stat.from++;
  208. return true;
  209. }
  210. public boolean visit(SQLSubqueryTableSource x) {
  211. stat.from++;
  212. stat.subQuery++;
  213. return true;
  214. }
  215. public boolean visit(SQLJoinTableSource x) {
  216. if (!(x.getParent() instanceof SQLJoinTableSource)) {
  217. stat.from++;
  218. }
  219. stat.join++;
  220. return true;
  221. }
  222. public boolean visit(SQLMethodInvokeExpr x) {
  223. stat.functionCall++;
  224. return true;
  225. }
  226. public boolean visit(SQLAggregateExpr x) {
  227. stat.aggregate++;
  228. return true;
  229. }
  230. public boolean visit(SQLOver x) {
  231. stat.over++;
  232. return true;
  233. }
  234. public boolean visit(SQLCastExpr x) {
  235. stat.functionCall++;
  236. return true;
  237. }
  238. public boolean visit(SQLInListExpr x) {
  239. stat.condition++;
  240. return true;
  241. }
  242. public boolean visit(SQLBinaryOpExpr x) {
  243. if (x.getOperator() != null && x.getOperator().isRelational()) {
  244. stat.condition++;
  245. SQLExpr left = x.getLeft();
  246. SQLExpr right = x.getRight();
  247. if (left instanceof SQLName && right instanceof SQLName) {
  248. stat.joinCondition++;
  249. } else if ((left instanceof SQLName || right instanceof SQLName)
  250. && (left instanceof SQLLiteralExpr || right instanceof SQLLiteralExpr)
  251. ) {
  252. stat.valueCondition++;
  253. } else {
  254. stat.otherCondition++;
  255. }
  256. }
  257. return true;
  258. }
  259. public boolean visit(SQLCaseExpr x) {
  260. SQLExpr value = x.getValueExpr();
  261. if (value != null) {
  262. stat.condition += x.getItems().size();
  263. }
  264. if (x.getElseExpr() != null) {
  265. stat.condition++;
  266. }
  267. return true;
  268. }
  269. public boolean visit(SQLExistsExpr x) {
  270. stat.condition++;
  271. return true;
  272. }
  273. public String toString() {
  274. return JSON.toJSONString(
  275. stat,
  276. JSONWriter.Feature.PrettyFormat,
  277. JSONWriter.Feature.NotWriteDefaultValue
  278. );
  279. }
  280. public java.util.Map toMap() {
  281. return (java.util.Map) JSON.toJSON(stat);
  282. }
  283. }
  284. }