|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the tools applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 #include "database.h" |
|
42 #include <QtGui> |
|
43 #include <QtXml> |
|
44 |
|
45 // Database schema definition and open/create functions |
|
46 |
|
47 QString resultsTable = QString("(TestName varchar, TestCaseName varchar, Series varchar, Idx varchar, ") + |
|
48 QString("Result varchar, ChartType varchar, Title varchar, ChartWidth varchar, ") + |
|
49 QString("ChartHeight varchar, TestTitle varchar, QtVersion varchar, Iterations varchar") + |
|
50 QString(")"); |
|
51 |
|
52 void execQuery(QSqlQuery query, bool warnOnFail) |
|
53 { |
|
54 bool ok = query.exec(); |
|
55 if (!ok && warnOnFail) { |
|
56 qDebug() << "FAIL:" << query.lastQuery() << query.lastError().text(); |
|
57 } |
|
58 } |
|
59 |
|
60 void execQuery(const QString &spec, bool warnOnFail) |
|
61 { |
|
62 QSqlQuery query; |
|
63 query.prepare(spec); |
|
64 execQuery(query, warnOnFail); |
|
65 } |
|
66 |
|
67 QSqlDatabase openDataBase(const QString &databaseFile) |
|
68 { |
|
69 // qDebug() << "open data base"; |
|
70 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); |
|
71 db.setDatabaseName(databaseFile); |
|
72 bool ok = db.open(); |
|
73 if (!ok) |
|
74 qDebug() << "FAIL: could not open database"; |
|
75 return db; |
|
76 } |
|
77 |
|
78 QSqlDatabase createDataBase(const QString &databaseFile) |
|
79 { |
|
80 // qDebug() << "create data base"; |
|
81 QSqlDatabase db = openDataBase(databaseFile); |
|
82 |
|
83 execQuery("DROP TABLE Results", false); |
|
84 execQuery("CREATE TABLE Results " + resultsTable); |
|
85 |
|
86 return db; |
|
87 } |
|
88 |
|
89 struct Tag |
|
90 { |
|
91 Tag(QString key, QString value) |
|
92 : key(key.trimmed()), value(value.trimmed()) |
|
93 { |
|
94 |
|
95 } |
|
96 |
|
97 QString key; |
|
98 QString value; |
|
99 }; |
|
100 |
|
101 QList<Tag> parseTag(const QString &tag) |
|
102 { |
|
103 // Format: key1=value ; key2=value |
|
104 // key1=value key2=value |
|
105 // value--value |
|
106 |
|
107 QList<Tag> keyValues; |
|
108 |
|
109 QString keyValuePairSeparator(""); |
|
110 if (tag.contains(";")) |
|
111 keyValuePairSeparator = ';'; |
|
112 if (tag.contains("--")) |
|
113 keyValuePairSeparator = "--"; |
|
114 |
|
115 foreach (QString keyValue, tag.split(keyValuePairSeparator)) { |
|
116 if (keyValue.contains("=")) { |
|
117 QStringList parts = keyValue.split("="); |
|
118 keyValues.append(Tag(parts.at(0), parts.at(1))); |
|
119 } else { |
|
120 keyValues.append(Tag(QString(), keyValue)); // no key, just a value. |
|
121 } |
|
122 } |
|
123 |
|
124 return keyValues; |
|
125 } |
|
126 |
|
127 void loadXml(const QStringList &fileNames) |
|
128 { |
|
129 foreach(const QString &fileName, fileNames) { |
|
130 QFileInfo fi( fileName ); |
|
131 loadXml(fileName, fi.fileName()); |
|
132 } |
|
133 } |
|
134 |
|
135 void loadXml(const QString &fileName, const QString &context) |
|
136 { |
|
137 QFile f(fileName); |
|
138 f.open(QIODevice::ReadOnly); |
|
139 loadXml(f.readAll(), context); |
|
140 } |
|
141 |
|
142 void loadXml(const QByteArray &xml, const QString& context) |
|
143 { |
|
144 QDomDocument doc; |
|
145 |
|
146 int line; |
|
147 int col; |
|
148 QString errorMsg; |
|
149 if (doc.setContent(xml, &errorMsg, &line, &col) == false) { |
|
150 qDebug() << "dom setContent failed" << line << col << errorMsg; |
|
151 } |
|
152 |
|
153 // Grab "Value" from <Environment><QtVersion>Value</QtVersion></Environment> |
|
154 QString qtVersion = doc.elementsByTagName("Environment").at(0).toElement().elementsByTagName("QtVersion") |
|
155 .at(0).toElement().childNodes().at(0).nodeValue(); |
|
156 QString testCase = doc.elementsByTagName("TestCase").at(0).toElement().attributeNode("name").value(); |
|
157 |
|
158 // qDebug() << "qt version" << qtVersion; |
|
159 // qDebug() << "test case" << testCase; |
|
160 |
|
161 DataBaseWriter writer; |
|
162 writer.testName = testCase; // testCaseName and testName is mixed up in the database writer class |
|
163 writer.qtVersion = qtVersion; |
|
164 |
|
165 QDomNodeList testFunctions = doc.elementsByTagName("TestFunction"); |
|
166 for (int i = 0; i < testFunctions.count(); ++i) { |
|
167 QDomElement function = testFunctions.at(i).toElement(); |
|
168 QString functionName = function.attributeNode("name").value(); |
|
169 writer.testCaseName = functionName; // testCaseName and testName is mixed up in the database writer class |
|
170 |
|
171 // qDebug() << "fn" << functionName; |
|
172 |
|
173 QDomNodeList results = function.elementsByTagName("BenchmarkResult"); |
|
174 for (int j = 0; j < results.count(); ++j) { |
|
175 QDomElement result = results.at(j).toElement(); |
|
176 QString tag = result.attributeNode("tag").value(); |
|
177 |
|
178 Q_UNUSED(context); |
|
179 // if (!context.isEmpty()) |
|
180 // tag += QString(" (%1)").arg(context); |
|
181 |
|
182 QString series; |
|
183 QString index; |
|
184 |
|
185 // By convention, "--" separates series and indexes in tags. |
|
186 if (tag.contains("--")) { |
|
187 QStringList parts = tag.split("--"); |
|
188 series = parts.at(0); |
|
189 index = parts.at(1); |
|
190 } else { |
|
191 series = tag; |
|
192 } |
|
193 |
|
194 QString resultString = result.attributeNode("value").value(); |
|
195 QString iterationCount = result.attributeNode("iterations").value(); |
|
196 double resultNumber = resultString.toDouble() / iterationCount.toDouble(); |
|
197 writer.addResult(series, index, QString::number(resultNumber), iterationCount); |
|
198 // qDebug() << "result" << series << index << tag << resultString << iterationCount; |
|
199 } |
|
200 } |
|
201 } |
|
202 |
|
203 void displayTable(const QString &table) |
|
204 { |
|
205 QSqlTableModel *model = new QSqlTableModel(); |
|
206 model->setTable(table); |
|
207 model->select(); |
|
208 QTableView *view = new QTableView(); |
|
209 view->setModel(model); |
|
210 view->show(); |
|
211 } |
|
212 |
|
213 void printDataBase() |
|
214 { |
|
215 QSqlQuery query; |
|
216 query.prepare("SELECT TestName, TestCaseName, Result FROM Results;"); |
|
217 bool ok = query.exec(); |
|
218 qDebug() << "printDataBase ok?" << ok; |
|
219 |
|
220 query.next(); |
|
221 qDebug() << ""; |
|
222 qDebug() << "Benchmark" << query.value(0).toString(); |
|
223 query.previous(); |
|
224 |
|
225 while (query.next()) { |
|
226 // QString country = query.value(fieldNo).toString(); |
|
227 // doSomething(country); |
|
228 qDebug() << "result for" << query.value(1).toString() << query.value(2).toString(); |
|
229 } |
|
230 } |
|
231 |
|
232 // TempTable implementation |
|
233 |
|
234 static int tempTableIdentifier = 0; |
|
235 TempTable::TempTable(const QString &spec) |
|
236 { |
|
237 m_name = "TempTable" + QString::number(tempTableIdentifier++); |
|
238 execQuery("CREATE TEMP TABLE " + m_name + " " + spec); |
|
239 } |
|
240 |
|
241 TempTable::~TempTable() |
|
242 { |
|
243 // ref count and drop it? |
|
244 } |
|
245 |
|
246 QString TempTable::name() |
|
247 { |
|
248 return m_name; |
|
249 } |
|
250 |
|
251 // DataBaseWriter implementation |
|
252 |
|
253 DataBaseWriter::DataBaseWriter() |
|
254 { |
|
255 disable = false; |
|
256 chartSize = QSize(800, 400); |
|
257 databaseFileName = ":memory:"; |
|
258 qtVersion = QT_VERSION_STR; |
|
259 } |
|
260 |
|
261 void DataBaseWriter::openDatabase() |
|
262 { |
|
263 db = openDataBase(databaseFileName); |
|
264 } |
|
265 |
|
266 void DataBaseWriter::createDatabase() |
|
267 { |
|
268 db = createDataBase(databaseFileName); |
|
269 } |
|
270 |
|
271 void DataBaseWriter::beginTransaction() |
|
272 { |
|
273 if (db.transaction() == false) { |
|
274 qDebug() << db.lastError(); |
|
275 qFatal("no transaction support"); |
|
276 } |
|
277 } |
|
278 |
|
279 void DataBaseWriter::commitTransaction() |
|
280 { |
|
281 db.commit(); |
|
282 } |
|
283 |
|
284 void DataBaseWriter::rollbackTransaction() |
|
285 { |
|
286 db.rollback(); |
|
287 } |
|
288 |
|
289 void DataBaseWriter::addResult(const QString &result) |
|
290 { |
|
291 return addResult(QString(), QString(), result); |
|
292 } |
|
293 |
|
294 void DataBaseWriter::addResult(const QString &series, const QString &index, const QString &result, const QString &iterations) |
|
295 { |
|
296 if (disable) |
|
297 return; |
|
298 |
|
299 QSqlQuery query; |
|
300 |
|
301 query.prepare("INSERT INTO Results (TestName, TestCaseName, Series, Idx, Result, ChartWidth, ChartHeight, Title, TestTitle, ChartType, QtVersion, Iterations) " |
|
302 "VALUES (:TestName, :TestCaseName, :Series, :Idx, :Result, :ChartWidth, :ChartHeight, :Title, :TestTitle, :ChartType, :QtVersion, :Iterations)"); |
|
303 query.bindValue(":TestName", testName); |
|
304 query.bindValue(":TestCaseName", testCaseName); |
|
305 query.bindValue(":Series", series); |
|
306 query.bindValue(":Idx", index); |
|
307 query.bindValue(":Result", result); |
|
308 query.bindValue(":ChartWidth", chartSize.width()); |
|
309 query.bindValue(":ChartHeight", chartSize.height()); |
|
310 query.bindValue(":Title", chartTitle); |
|
311 query.bindValue(":TestTitle", testTitle); |
|
312 query.bindValue(":QtVersion", qtVersion); |
|
313 query.bindValue(":Iterations", iterations); |
|
314 |
|
315 |
|
316 if (chartType == LineChart) |
|
317 query.bindValue(":ChartType", "LineChart"); |
|
318 else |
|
319 query.bindValue(":ChartType", "BarChart"); |
|
320 execQuery(query); |
|
321 } |