File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\tools\ConvertTraceFile.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.tools;
8 import java.io.IOException;
9 import java.io.LineNumberReader;
10 import java.io.PrintWriter;
11 import java.sql.SQLException;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.StringTokenizer;
16
17 import org.h2.message.DbException;
18 import org.h2.store.fs.FileUtils;
19 import org.h2.util.IOUtils;
20 import org.h2.util.MathUtils;
21 import org.h2.util.New;
22 import org.h2.util.StringUtils;
23 import org.h2.util.Tool;
24
25 /**
26 * Converts a .trace.db file to a SQL script and Java source code.
27 * <br />
28 * SQL statement statistics are listed as well.
29 * @h2.resource
30 */
31 public class ConvertTraceFile extends Tool {
32
33 private final HashMap<String, Stat> stats = New.hashMap();
34 private long timeTotal;
35
36 /**
37 * This class holds statistics about a SQL statement.
38 */
39 static class Stat implements Comparable<Stat> {
40 String sql;
41 int executeCount;
42 long time;
43 long resultCount;
44
45 public int compareTo(Stat other) {
46 if (other == this) {
47 return 0;
48 }
49 int c = MathUtils.compareLong(other.time, time);
50 if (c == 0) {
51 c = MathUtils.compareInt(other.executeCount, executeCount);
52 if (c == 0) {
53 c = sql.compareTo(other.sql);
54 }
55 }
56 return c;
57 }
58 }
59
60 /**
61 * Options are case sensitive. Supported options are:
62 * <table>
63 * <tr><td>[-help] or [-?]</td>
64 * <td>Print the list of options</td></tr>
65 * <tr><td>[-traceFile &lt;file&gt;]</td>
66 * <td>The trace file name (default: test.trace.db)</td></tr>
67 * <tr><td>[-script &lt;file&gt;]</td>
68 * <td>The script file name (default: test.sql)</td></tr>
69 * <tr><td>[-javaClass &lt;file&gt;]</td>
70 * <td>The Java directory and class file name (default: Test)</td></tr>
71 * </table>
72 * @h2.resource
73 *
74 * @param args the command line arguments
75 */
76 public static void main(String... args) throws SQLException {
77 new ConvertTraceFile().runTool(args);
78 }
79
80 public void runTool(String... args) throws SQLException {
81 String traceFile = "test.trace.db";
82 String javaClass = "Test";
83 String script = "test.sql";
84 for (int i = 0; args != null && i < args.length; i++) {
85 String arg = args[i];
86 if (arg.equals("-traceFile")) {
87 traceFile = args[++i];
88 } else if (arg.equals("-javaClass")) {
89 javaClass = args[++i];
90 } else if (arg.equals("-script")) {
91 script = args[++i];
92 } else if (arg.equals("-help") || arg.equals("-?")) {
93 showUsage();
94 return;
95 } else {
96 showUsageAndThrowUnsupportedOption(arg);
97 }
98 }
99 try {
100 convertFile(traceFile, javaClass, script);
101 } catch (IOException e) {
102 throw DbException.convertIOException(e, traceFile);
103 }
104 }
105
106 /**
107 * Converts a trace file to a Java class file and a script file.
108 *
109 * @param traceFileName
110 * @param javaClassName
111 * @throws IOException
112 */
113 private void convertFile(String traceFileName, String javaClassName, String script) throws IOException {
114 LineNumberReader reader = new LineNumberReader(IOUtils.getBufferedReader(
115 FileUtils.newInputStream(traceFileName)));
116 PrintWriter javaWriter = new PrintWriter(IOUtils.getBufferedWriter(
117 FileUtils.newOutputStream(javaClassName + ".java", false)));
118 PrintWriter scriptWriter = new PrintWriter(IOUtils.getBufferedWriter(
119 FileUtils.newOutputStream(script, false)));
120 javaWriter.println("import java.io.*;");
121 javaWriter.println("import java.sql.*;");
122 javaWriter.println("import java.math.*;");
123 javaWriter.println("import java.util.Calendar;");
124 String cn = javaClassName.replace('\\', '/');
125 int idx = cn.lastIndexOf('/');
126 if (idx > 0) {
127 cn = cn.substring(idx + 1);
128 }
129 javaWriter.println("public class " + cn + " {");
130 javaWriter.println(" public static void main(String... args) throws Exception {");
131 javaWriter.println(" Class.forName(\"org.h2.Driver\");");
132 while (true) {
133 String line = reader.readLine();
134 if (line == null) {
135 break;
136 }
137 if (line.startsWith("/**/")) {
138 line = " " + line.substring(4);
139 javaWriter.println(line);
140 } else if (line.startsWith("/*SQL")) {
141 int end = line.indexOf("*/");
142 String sql = line.substring(end + "*/".length());
143 sql = StringUtils.javaDecode(sql);
144 line = line.substring("/*SQL".length(), end);
145 if (line.length() > 0) {
146 String statement = sql;
147 int count = 0;
148 long time = 0;
149 line = line.trim();
150 if (line.length() > 0) {
151 StringTokenizer tk = new StringTokenizer(line, " :");
152 while (tk.hasMoreElements()) {
153 String token = tk.nextToken();
154 if ("l".equals(token)) {
155 int len = Integer.parseInt(tk.nextToken());
156 statement = sql.substring(0, len) + ";";
157 } else if ("#".equals(token)) {
158 count = Integer.parseInt(tk.nextToken());
159 } else if ("t".equals(token)) {
160 time = Long.parseLong(tk.nextToken());
161 }
162 }
163 }
164 addToStats(statement, count, time);
165 }
166 scriptWriter.println(sql);
167 }
168 }
169 javaWriter.println(" }");
170 javaWriter.println('}');
171 reader.close();
172 javaWriter.close();
173 if (stats.size() > 0) {
174 scriptWriter.println("-----------------------------------------");
175 scriptWriter.println("-- SQL Statement Statistics");
176 scriptWriter.println("-- time: total time in milliseconds (accumulated)");
177 scriptWriter.println("-- count: how many times the statement ran");
178 scriptWriter.println("-- result: total update count or row count");
179 scriptWriter.println("-----------------------------------------");
180 scriptWriter.println("-- self accu time count result sql");
181 int accumTime = 0;
182 ArrayList<Stat> list = New.arrayList(stats.values());
183 Collections.sort(list);
184 if (timeTotal == 0) {
185 timeTotal = 1;
186 }
187 for (Stat stat : list) {
188 accumTime += stat.time;
189 StringBuilder buff = new StringBuilder(100);
190 buff.append("-- ").
191 append(padNumberLeft(100 * stat.time / timeTotal, 3)).
192 append("% ").
193 append(padNumberLeft(100 * accumTime / timeTotal, 3)).
194 append('%').
195 append(padNumberLeft(stat.time, 8)).
196 append(padNumberLeft(stat.executeCount, 8)).
197 append(padNumberLeft(stat.resultCount, 8)).
198 append(' ').
199 append(removeNewlines(stat.sql));
200 scriptWriter.println(buff.toString());
201 }
202 }
203 scriptWriter.close();
204 }
205
206 private static String removeNewlines(String s) {
207 return s == null ? s : s.replace('\r', ' ').replace('\n', ' ');
208 }
209
210 private static String padNumberLeft(long number, int digits) {
211 return StringUtils.pad(String.valueOf(number), digits, " ", false);
212 }
213
214 private void addToStats(String sql, int resultCount, long time) {
215 Stat stat = stats.get(sql);
216 if (stat == null) {
217 stat = new Stat();
218 stat.sql = sql;
219 stats.put(sql, stat);
220 }
221 stat.executeCount++;
222 stat.resultCount += resultCount;
223 stat.time += time;
224 timeTotal += time;
225 }
226
227 }
228