~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kexi/kexidb/utils.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-04-20 21:38:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060420213853-j5lxluqvymxt2zny
Tags: 1:1.5.0-0ubuntu2
UbuntuĀ uploadĀ 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* This file is part of the KDE project
2
 
   Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
 
2
   Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
3
3
 
4
4
   This library is free software; you can redistribute it and/or
5
5
   modify it under the terms of the GNU Library General Public
13
13
 
14
14
   You should have received a copy of the GNU Library General Public License
15
15
   along with this library; see the file COPYING.LIB.  If not, write to
16
 
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
   Boston, MA 02111-1307, USA.
 
16
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
 * Boston, MA 02110-1301, USA.
18
18
*/
19
19
 
20
20
#include <kexidb/utils.h>
21
21
#include <kexidb/cursor.h>
 
22
#include <kexidb/drivermanager.h>
22
23
 
23
24
#include <qmap.h>
 
25
#include <qthread.h>
24
26
 
 
27
#include <kdebug.h>
25
28
#include <klocale.h>
26
29
#include <kstaticdeleter.h>
 
30
#include <kmessagebox.h>
 
31
 
 
32
#include "utils_p.h"
27
33
 
28
34
using namespace KexiDB;
29
35
 
109
115
                        return;
110
116
                }
111
117
        }
112
 
        if (dynamic_cast<Connection*>(obj)) {
113
 
                conn = dynamic_cast<Connection*>(obj);
114
 
        }
 
118
//      if (dynamic_cast<Connection*>(obj)) {
 
119
        //      conn = dynamic_cast<Connection*>(obj);
 
120
        //}
115
121
        if (!obj || !obj->error())
116
122
                return;
117
123
        //lower level message is added to the details, if there is alread message specified
125
131
 
126
132
        if (!obj->serverErrorMsg().isEmpty())
127
133
                details += "<p><b><nobr>" +i18n("Message from server:") + "</nobr></b><br>" + obj->serverErrorMsg();
128
 
        if (conn && !conn->recentSQLString().isEmpty())
129
 
                details += "<p><b><nobr>" +i18n("SQL statement:") + "</nobr></b><br>" + conn->recentSQLString();
 
134
        if (!obj->recentSQLString().isEmpty())
 
135
                details += "<p><b><nobr>" +i18n("SQL statement:") + QString("</nobr></b><br><tt>%1</tt>").arg(obj->recentSQLString());
130
136
        int serverResult;
131
137
        QString serverResultName;
132
138
        if (obj->serverResult()!=0) {
139
145
        }
140
146
        if (!serverResultName.isEmpty())
141
147
                details += (QString("<p><b><nobr>")+i18n("Server result name:")+"</nobr></b><br>"+serverResultName);
142
 
        if (!details.isEmpty()) {
 
148
        if (!details.isEmpty() 
 
149
                && (!obj->serverErrorMsg().isEmpty() || !obj->recentSQLString().isEmpty() || !serverResultName.isEmpty() || serverResult!=0) )
 
150
        {
143
151
                details += (QString("<p><b><nobr>")+i18n("Server result number:")+"</nobr></b><br>"+QString::number(serverResult));
144
152
        }
 
153
 
 
154
        if (!details.isEmpty() && !details.startsWith("<qt>")) {
 
155
                if (details.startsWith("<p>"))
 
156
                        details = QString::fromLatin1("<qt>")+details;
 
157
                else
 
158
                        details = QString::fromLatin1("<qt><p>")+details;
 
159
        }
145
160
}
146
161
 
147
162
void KexiDB::getHTMLErrorMesage(Object* obj, QString& msg)
157
172
int KexiDB::idForObjectName( Connection &conn, const QString& objName, int objType )
158
173
{
159
174
        RowData data;
160
 
        if (!conn.querySingleRecord(QString("select o_id from kexi__objects where lower(o_name)='%1' and o_type=%2")
 
175
        if (true!=conn.querySingleRecord(QString("select o_id from kexi__objects where lower(o_name)='%1' and o_type=%2")
161
176
                .arg(objName.lower()).arg(objType), data))
162
177
                return 0;
163
178
        bool ok;
165
180
        return ok ? id : 0;
166
181
}
167
182
 
 
183
//-----------------------------------------
 
184
 
 
185
TableOrQuerySchema::TableOrQuerySchema(Connection *conn, const QCString& name, bool table)
 
186
 : m_name(name)
 
187
 , m_table(table ? conn->tableSchema(QString(name)) : 0)
 
188
 , m_query(table ? 0 : conn->querySchema(QString(name)))
 
189
{
 
190
        if (table && !m_table)
 
191
                kdWarning() << "TableOrQuery(Connection *conn, const QCString& name, bool table) : "
 
192
                        "no table specified!" << endl;
 
193
        if (!table && !m_query)
 
194
                kdWarning() << "TableOrQuery(Connection *conn, const QCString& name, bool table) : "
 
195
                        "no query specified!" << endl;
 
196
}
 
197
 
 
198
TableOrQuerySchema::TableOrQuerySchema(FieldList &tableOrQuery)
 
199
 : m_table(dynamic_cast<TableSchema*>(&tableOrQuery))
 
200
 , m_query(dynamic_cast<QuerySchema*>(&tableOrQuery))
 
201
{
 
202
        if (!m_table && !m_query)
 
203
                kdWarning() << "TableOrQuery(FieldList &tableOrQuery) : "
 
204
                        " tableOrQuery is nether table nor query!" << endl;
 
205
}
 
206
 
 
207
TableOrQuerySchema::TableOrQuerySchema(Connection *conn, int id)
 
208
{
 
209
        m_table = conn->tableSchema(id);
 
210
        m_query = m_table ? 0 : conn->querySchema(id);
 
211
        if (!m_table && !m_query)
 
212
                kdWarning() << "TableOrQuery(Connection *conn, int id) : no table or query found for id==" 
 
213
                        << id << "!" << endl;
 
214
}
 
215
 
 
216
TableOrQuerySchema::TableOrQuerySchema(TableSchema* table)
 
217
 : m_table(table)
 
218
 , m_query(0)
 
219
{
 
220
        if (!m_table)
 
221
                kdWarning() << "TableOrQuery(TableSchema* table) : no table specified!" << endl;
 
222
}
 
223
 
 
224
TableOrQuerySchema::TableOrQuerySchema(QuerySchema* query)
 
225
 : m_table(0)
 
226
 , m_query(query)
 
227
{
 
228
        if (!m_query)
 
229
                kdWarning() << "TableOrQuery(QuerySchema* query) : no query specified!" << endl;
 
230
}
 
231
 
 
232
const QueryColumnInfo::Vector TableOrQuerySchema::columns(bool unique)
 
233
{
 
234
        if (m_table)
 
235
                return m_table->query()->fieldsExpanded();
 
236
        
 
237
        if (m_query)
 
238
                return m_query->fieldsExpanded(unique);
 
239
 
 
240
        kdWarning() << "TableOrQuery::fields() : no query or table specified!" << endl;
 
241
        return QueryColumnInfo::Vector();
 
242
}
 
243
 
 
244
QCString TableOrQuerySchema::name() const
 
245
{
 
246
        if (m_table)
 
247
                return m_table->name().latin1();
 
248
        if (m_query)
 
249
                return m_query->name().latin1();
 
250
        return m_name;
 
251
}
 
252
 
 
253
QString TableOrQuerySchema::captionOrName() const
 
254
{
 
255
        SchemaData *sdata = m_table ? static_cast<SchemaData *>(m_table) : static_cast<SchemaData *>(m_query);
 
256
        if (!sdata)
 
257
                return m_name;
 
258
        return sdata->caption().isEmpty() ? sdata->name() : sdata->caption();
 
259
}
 
260
 
 
261
Field* TableOrQuerySchema::field(const QString& name)
 
262
{
 
263
        if (m_table)
 
264
                return m_table->field(name);
 
265
        if (m_query)
 
266
                return m_query->field(name);
 
267
 
 
268
        return 0;
 
269
}
 
270
 
 
271
QueryColumnInfo* TableOrQuerySchema::columnInfo(const QString& name)
 
272
{
 
273
        if (m_table)
 
274
                return m_table->query()->columnInfo(name);
 
275
        
 
276
        if (m_query)
 
277
                return m_query->columnInfo(name);
 
278
 
 
279
        return 0;
 
280
}
 
281
 
 
282
QString TableOrQuerySchema::debugString()
 
283
{
 
284
        if (m_table)
 
285
                return m_table->debugString();
 
286
        else if (m_query)
 
287
                return m_query->debugString();
 
288
        return QString::null;
 
289
}
 
290
 
 
291
void TableOrQuerySchema::debug()
 
292
{
 
293
        if (m_table)
 
294
                return m_table->debug();
 
295
        else if (m_query)
 
296
                return m_query->debug();
 
297
}
 
298
 
 
299
Connection* TableOrQuerySchema::connection() const
 
300
{
 
301
        if (m_table)
 
302
                return m_table->connection();
 
303
        else if (m_query)
 
304
                return m_query->connection();
 
305
        return 0;
 
306
}
 
307
 
 
308
 
 
309
//------------------------------------------
 
310
 
 
311
class ConnectionTestThread : public QThread {
 
312
        public:
 
313
                ConnectionTestThread(ConnectionTestDialog *dlg, const KexiDB::ConnectionData& connData);
 
314
                virtual void run();
 
315
        protected:
 
316
                ConnectionTestDialog* m_dlg;
 
317
                KexiDB::ConnectionData m_connData;
 
318
};
 
319
 
 
320
ConnectionTestThread::ConnectionTestThread(ConnectionTestDialog* dlg, const KexiDB::ConnectionData& connData)
 
321
 : m_dlg(dlg), m_connData(connData)
 
322
{
 
323
}
 
324
 
 
325
void ConnectionTestThread::run()
 
326
{
 
327
        KexiDB::DriverManager manager;
 
328
        KexiDB::Driver* drv = manager.driver(m_connData.driverName);
 
329
//      KexiGUIMessageHandler msghdr;
 
330
        if (!drv || manager.error()) {
 
331
//move          msghdr.showErrorMessage(&Kexi::driverManager());
 
332
                m_dlg->error(&manager);
 
333
                return;
 
334
        }
 
335
        KexiDB::Connection * conn = drv->createConnection(m_connData);
 
336
        if (!conn || drv->error()) {
 
337
//move          msghdr.showErrorMessage(drv);
 
338
                delete conn;
 
339
                m_dlg->error(drv);
 
340
                return;
 
341
        }
 
342
        if (!conn->connect() || conn->error()) {
 
343
//move          msghdr.showErrorMessage(conn);
 
344
                m_dlg->error(conn);
 
345
                delete conn;
 
346
                return;
 
347
        }
 
348
        // SQL database backends like PostgreSQL require executing "USE database" 
 
349
        // if we really want to know connection to the server succeeded.
 
350
        QString tmpDbName;
 
351
        if (!conn->useTemporaryDatabaseIfNeeded( tmpDbName )) {
 
352
                m_dlg->error(conn);
 
353
                delete conn;
 
354
                return;
 
355
        }
 
356
        delete conn;
 
357
        m_dlg->error(0);
 
358
}
 
359
 
 
360
ConnectionTestDialog::ConnectionTestDialog(QWidget* parent, 
 
361
        const KexiDB::ConnectionData& data,
 
362
        KexiDB::MessageHandler& msgHandler)
 
363
 : KProgressDialog(parent, "testconn_dlg",
 
364
        i18n("Test Connection"), i18n("<qt>Testing connection to <b>%1</b> database server...</qt>")
 
365
        .arg(data.serverInfoString(true)), true /*modal*/)
 
366
 , m_thread(new ConnectionTestThread(this, data))
 
367
 , m_connData(data)
 
368
 , m_msgHandler(&msgHandler)
 
369
 , m_elapsedTime(0)
 
370
 , m_errorObj(0)
 
371
 , m_stopWaiting(false)
 
372
{
 
373
        showCancelButton(true);
 
374
        progressBar()->setPercentageVisible(false);
 
375
        progressBar()->setTotalSteps(0);
 
376
        connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
 
377
        adjustSize();
 
378
        resize(250, height());
 
379
}
 
380
 
 
381
ConnectionTestDialog::~ConnectionTestDialog()
 
382
{
 
383
        m_wait.wakeAll();
 
384
        m_thread->terminate();
 
385
        delete m_thread;
 
386
}
 
387
 
 
388
int ConnectionTestDialog::exec()
 
389
{
 
390
        m_timer.start(20);
 
391
        m_thread->start();
 
392
        const int res = KProgressDialog::exec();
 
393
        m_thread->wait();
 
394
        m_timer.stop();
 
395
        return res;
 
396
}
 
397
 
 
398
void ConnectionTestDialog::slotTimeout()
 
399
{
 
400
//      KexiDBDbg << "ConnectionTestDialog::slotTimeout() " << m_errorObj << endl;
 
401
        bool notResponding = false;
 
402
        if (m_elapsedTime >= 1000*5) {//5 seconds
 
403
                m_stopWaiting = true;
 
404
                notResponding = true;
 
405
        }
 
406
        if (m_stopWaiting) {
 
407
                m_timer.disconnect(this);
 
408
                m_timer.stop();
 
409
                slotCancel();
 
410
//              reject();
 
411
//              close();
 
412
                if (m_errorObj) {
 
413
                        m_msgHandler->showErrorMessage(m_errorObj);
 
414
                        m_errorObj = 0;
 
415
                }
 
416
                else if (notResponding) {
 
417
                        KMessageBox::sorry(0, 
 
418
                                i18n("<qt>Test connection to <b>%1</b> database server failed. The server is not responding.</qt>")
 
419
                                        .arg(m_connData.serverInfoString(true)),
 
420
                                i18n("Test Connection"));
 
421
                }
 
422
                else {
 
423
                        KMessageBox::information(0, 
 
424
                                i18n("<qt>Test connection to <b>%1</b> database server established successfully.</qt>")
 
425
                                        .arg(m_connData.serverInfoString(true)),
 
426
                                i18n("Test Connection"));
 
427
                }
 
428
//              slotCancel();
 
429
//              reject();
 
430
                m_wait.wakeAll();
 
431
                return;
 
432
        }
 
433
        m_elapsedTime += 20;
 
434
        progressBar()->setProgress( m_elapsedTime );
 
435
}
 
436
 
 
437
void ConnectionTestDialog::error(KexiDB::Object *obj)
 
438
{
 
439
        KexiDBDbg << "ConnectionTestDialog::error()" << endl;
 
440
        m_stopWaiting = true;
 
441
        m_errorObj = obj;
 
442
/*              reject();
 
443
                m_msgHandler->showErrorMessage(obj);
 
444
        if (obj) {
 
445
        }
 
446
        else {
 
447
                accept();
 
448
        }*/
 
449
        m_wait.wait();
 
450
}
 
451
 
 
452
void ConnectionTestDialog::slotCancel()
 
453
{
 
454
//      m_wait.wakeAll();
 
455
        m_thread->terminate();
 
456
        m_timer.disconnect(this);
 
457
        m_timer.stop();
 
458
        KProgressDialog::slotCancel();
 
459
}
 
460
 
 
461
void KexiDB::connectionTestDialog(QWidget* parent, const KexiDB::ConnectionData& data, 
 
462
        KexiDB::MessageHandler& msgHandler)
 
463
{
 
464
        ConnectionTestDialog dlg(parent, data, msgHandler);
 
465
        dlg.exec();
 
466
}
 
467
 
 
468
int KexiDB::rowCount(const KexiDB::TableSchema& tableSchema)
 
469
{
 
470
//! @todo does not work with non-SQL data sources
 
471
        if (!tableSchema.connection()) {
 
472
                KexiDBWarn << "KexiDB::rowsCount(const KexiDB::TableSchema&): no tableSchema.connection() !" << endl;
 
473
                return -1;
 
474
        }
 
475
        int count = -1; //will be changed only on success of querySingleNumber()
 
476
        tableSchema.connection()->querySingleNumber(
 
477
                QString::fromLatin1("SELECT COUNT() FROM ") 
 
478
                + tableSchema.connection()->driver()->escapeIdentifier(tableSchema.name()), 
 
479
                count
 
480
        );
 
481
        return count;
 
482
}
 
483
 
 
484
int KexiDB::rowCount(KexiDB::QuerySchema& querySchema)
 
485
{
 
486
//! @todo does not work with non-SQL data sources
 
487
        if (!querySchema.connection()) {
 
488
                KexiDBWarn << "KexiDB::rowsCount(const KexiDB::QuerySchema&): no querySchema.connection() !" << endl;
 
489
                return -1;
 
490
        }
 
491
        int count = -1; //will be changed only on success of querySingleNumber()
 
492
        querySchema.connection()->querySingleNumber(
 
493
                QString::fromLatin1("SELECT COUNT() FROM (") 
 
494
                + querySchema.connection()->selectStatement(querySchema) + ")",
 
495
                count
 
496
        );
 
497
        return count;
 
498
}
 
499
 
 
500
int KexiDB::rowCount(KexiDB::TableOrQuerySchema& tableOrQuery)
 
501
{
 
502
        if (tableOrQuery.table())
 
503
                return rowCount( *tableOrQuery.table() );
 
504
        if (tableOrQuery.query())
 
505
                return rowCount( *tableOrQuery.query() );
 
506
        return -1;
 
507
}
 
508
 
 
509
int KexiDB::fieldCount(KexiDB::TableOrQuerySchema& tableOrQuery)
 
510
{
 
511
        if (tableOrQuery.table())
 
512
                return tableOrQuery.table()->fieldCount();
 
513
        if (tableOrQuery.query())
 
514
                return tableOrQuery.query()->fieldsExpanded().count();
 
515
        return -1;
 
516
}
 
517
 
 
518
QMap<QString,QString> KexiDB::toMap( const ConnectionData& data )
 
519
{
 
520
        QMap<QString,QString> m;
 
521
        m["caption"] = data.caption;
 
522
        m["description"] = data.description;
 
523
        m["driverName"] = data.driverName;
 
524
        m["hostName"] = data.hostName;
 
525
        m["port"] = QString::number(data.port);
 
526
        m["useLocalSocketFile"] = QString::number((int)data.useLocalSocketFile);
 
527
        m["localSocketFileName"] = data.localSocketFileName;
 
528
        m["password"] = data.password;
 
529
        m["savePassword"] = QString::number((int)data.savePassword);
 
530
        m["userName"] = data.userName;
 
531
        m["fileName"] = data.fileName();
 
532
        return m;
 
533
}
 
534
 
 
535
void KexiDB::fromMap( const QMap<QString,QString>& map, ConnectionData& data )
 
536
{
 
537
        data.caption = map["caption"];
 
538
        data.description = map["description"];
 
539
        data.driverName = map["driverName"];
 
540
        data.hostName = map["hostName"];
 
541
        data.port = map["port"].toInt();
 
542
        data.useLocalSocketFile = map["useLocalSocketFile"].toInt()==1;
 
543
        data.localSocketFileName = map["localSocketFileName"];
 
544
        data.password = map["password"];
 
545
        data.savePassword = map["savePassword"].toInt()==1;
 
546
        data.userName = map["userName"];
 
547
        data.setFileName(map["fileName"]);
 
548
}
 
549
 
 
550
bool KexiDB::splitToTableAndFieldParts(const QString& string, 
 
551
        QString& tableName, QString& fieldName,
 
552
        SetFieldNameIfNoTableNameOptions option)
 
553
{
 
554
        const int id = string.find('.');
 
555
        if (option & SetFieldNameIfNoTableName && id==-1) {
 
556
                tableName = QString::null;
 
557
                fieldName = string;
 
558
                return true;
 
559
        }
 
560
        if (id<=0 || id==int(string.length()-1))
 
561
                return false;
 
562
        tableName = string.left(id);
 
563
        fieldName = string.mid(id+1);
 
564
        return true;
 
565
}
 
566
 
 
567
#include "utils_p.moc"