QSqlQuery

Alles rund um die Programmierung mit Qt
Antworten
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

QSqlQuery

Beitrag von DBGTMaster »

Hallo,

hätte paar Fragen zu der Klasse QSqlQuery:

1.) Kann ich irgendwie die fehlgeschlagene SQL ermitteln (für Debugging zwecke)? Ich finde nur Methoden, um die zuletzt erfolgreiche SQL zu erhalten.

2.) Muss ich bei jeder SQL nun per Hand überprüfen, ob diese auch erfolgreich war?

zB.:

Code: Alles auswählen

QSqlQuery query;
// ...
if (!query.exec()) throw SqlException(...);
Kann ich diesen Vorgang irgendwie automatisieren, so dass das überprüfen der SQL, ob erfolgreich automatisch geschieht und eventuell eine Exception geworfen wird?

Danke!
strige
Beiträge: 36
Registriert: 27. Dezember 2009 19:37

Beitrag von strige »

Hi,

Code: Alles auswählen

QSqlQuery query;
query.exec("blabla");
QSqlError err = query.lastError();
qDebug() << err.text();
meintest du sowas?
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Beitrag von DBGTMaster »

strige hat geschrieben:Hi,

Code: Alles auswählen

QSqlQuery query;
query.exec("blabla");
QSqlError err = query.lastError();
qDebug() << err.text();
meintest du sowas?
Wie ich den letzten SQL Fehler ausgebe, ist mir auch soweit klar... Mir geht es eher um die Fehlerbehandlung.

Beispiel:

Code: Alles auswählen

    QSqlQuery insert;
    insert.prepare("INSERT INTO address (vorname, nachname, adresse, plz, ort, phone) VALUES (:vorname, :nachname, :adresse, :plz, :ort, :phone)");
    insert.bindValue(":vorname", _surname);
    insert.bindValue(":nachname", _lastname);
    insert.bindValue(":adresse", _address);
    insert.bindValue(":plz", _plz);
    insert.bindValue(":city", _city);
    insert.bindValue(":phone", _phone);

    if (!insert.exec()) {
        QMessageBox::critical(0, "Sql Fehler",
                              QString("Sql Fehler ist aufgetreten!<br><b>Zeile:</b> %1<br/><b>Datei:</b> %2<br><b>Error:</b> %3")
                              .arg(QString::number(__LINE__), __FILE__, insert.lastError().text() ) );
        
    }
Nach absetzen der SQL überprüfe ich, ob ein Fehler aufgetreten ist, wenn ja, teile ich es dem User mit...

Mir geht es um diesen Abschnitt:

Code: Alles auswählen

if (!insert.exec()) {
        QMessageBox::critical(0, "Sql Fehler",
                              QString("Sql Fehler ist aufgetreten!<br><b>Zeile:</b> %1<br/><b>Datei:</b> %2<br><b>Error:</b> %3")
                              .arg(QString::number(__LINE__), __FILE__, insert.lastError().text() ) );
        
    }
Diesen Code müsste ich nun bei jeder einzelnen SQL Query einbauen, was ich aber verhindern möchte...

Daher meine Frage, kann ich die Überprüfung der SQL und gegeben falls Fehler- Erzeugung automatisieren, so dass ich diese nach der Abfrage nicht immer wieder diese Abfrage durchführen muss?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Die Frage ist - was willst Du erreichen? Reicht einfach ein 'return false' oder eine Logausgabe oder was? Irgendwo muss man den User ja benachrichtigen... Man kann auch um QSqlQuery.exec() eine Funktion drum rumbauen oder was auch immer. Hat aber alles nichts wirklich mit QSqlQuery sondern mit allgemeiner Fehlerbehandlung zu tun.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Beitrag von DBGTMaster »

Christian81 hat geschrieben:Die Frage ist - was willst Du erreichen? Reicht einfach ein 'return false' oder eine Logausgabe oder was? Irgendwo muss man den User ja benachrichtigen... Man kann auch um QSqlQuery.exec() eine Funktion drum rumbauen oder was auch immer. Hat aber alles nichts wirklich mit QSqlQuery sondern mit allgemeiner Fehlerbehandlung zu tun.
Ich will eben den User benachrichten, dass etwas schief gelaufen ist...

Wenn meine Anwendung nun zB. 1000 SQL Abfragen beinhaltet, dann muss ich ja 1000 mal mein Konstrukt reinbauen, ob die SQL erfolgreich war, wenn nicht, dass benachrichtigen... Und genau das hier will ich verhindern...
Aber eine Funktion rumherum bauen klingt nicht schlecht...

bzw. andere frage:

gibt es eine etwas größere opensource anwendung mit datenbank- Anbindung, damit ich mir da mal ein bisschen ab schauen kann, wie das hier gelöst wurde?

lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

phpmyadmin, amarok, akonadi, nepomuk, joomla, ...
Die verwenden halt teilweise direkt die Schnittstelle ohne QtSql, bzw. sind php.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Glaub Teamspeak 3 verwendet Qt4 ... sogar im server (Pfui !).
die Einstellungen werden entweder in ner "richtigen DB" oder per default in ner SQLite DB abgelegt. DIe Chance dass die QtSQL verwenden iss sehr hoch ....
Ups, vergass, iss alles closed source, nix mit nachgucken ... :evil:

Aber vielleicht bei KMail, sollten aehnliche Dinge verwenden ...

Ciao ...
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Hatte ein ähnliches Problem in einer App die Zwingend eine DB-Connection brauchte, habe ich dort so gelöst:

Code: Alles auswählen

namespace SqlRelated {

    bool ensureConnection()
    {
        QSqlDatabase db;

        // if NO named connection present
        if (! QSqlDatabase::contains("myconnectionname"))
        {
            // create named database connection and get a handle on it
            db = QSqlDatabase::addDatabase("QMYSQL","myconnectionname");
        }
        else
        {
            db = QSqlDatabase::database("myconnectionname",false);
        }

        if (! db.isOpen())
        {
            // set up parameters
            db.setHostName("myhost");
            db.setPort(1234);
            db.setDatabaseName("mytablename");

            db.setUserName("myusername");
            db.setPassword("myuserpass");

            // try to open connection
            forever {
                if (! db.open()) // not able to open connection
                {
                    QMessageBox::StandardButton but;

                    but = QMessageBox::warning(0, "Error connecting to database",
                                               db.lastError().text().append("\n")
                                               .append("\nHOST:\t")
                                               .append(db.hostName())
                                               .append("\nPORT:\t")
                                               .append(QString::number(db.port()))
                                               .append("\nUSER:\t")
                                               .append(db.userName())
                                               .append("\nPASS:\t")
                                               .append(QString(db.password().size(),'*')),
                                               QMessageBox::Retry|QMessageBox::Cancel,
                                               QMessageBox::Retry);

                    // possible result buttons (retry through "forever")
                    if ( but == QMessageBox::Cancel)
                    {
                        QMessageBox::critical(0, "Critical Error:",
                                              "Unable to connect to database.\n\n"
                                              "No data == no functionality => "
                                              "Aborting program.",
                                              QMessageBox::Abort) ;
                        qApp->exit(-1);
                    }
                }
                // OPEN
                else
                {
                    break; // break forever statement
                }
            }
        }
        return true;
    }


    void debugSqlError(const QSqlQuery & sqlQuery)
    {
        debugSqlError(sqlQuery.lastError());
    }

    void debugSqlError(const QSqlError & sqlError)
    {
        QString text = sqlError.text()
                       .append("\n\n\n\n")
                       .append("Error #\t").append(QString::number(sqlError.number()))
                       .append("\nType   \t");

        switch (sqlError.type())
        {
        case 0: text.append("No error."); break;
        case 1: text.append("Connection error."); break;
        case 2: text.append("SQL statement syntax error."); break;
        case 3: text.append("Transaction failed error."); break;
        case 4: text.append("Unknown error."); break;
        }

        QMessageBox::warning(0,"DEBUG Sql-Error", text,QMessageBox::Ok,QMessageBox::Ok);
    }
};

using SqlRelated::debugSqlError;
using SqlRelated::ensureConnection;

Code: Alles auswählen

    // irgendwo im Konstruktor meiner DB-Benutzenden Klasse:
    static bool ensuredConnect = SqlRelated::ensureConnection();
    if (! ensuredConnect) { qDebug() << "rausoptimierung verhindern, hier kommet man aber nie hin ...";}

Code: Alles auswählen

    // irgendwo beim Querying:
    QSqlQuery queryChildData = db.exec(mChildQuery);
    // query was successfull ?
    if (! queryChildData.isActive())
    {
        // output the error and stop querying
        debugSqlError(queryChildData);
        return;
    }
Du solltest bei 1000 SqlQueries vielleicht sicherstellen das der User eine Möglichkeit zum Abbruch hat ... ich hasse es 1000 Query-Fehler wegdrücken zu müssen bevor der "query" Teil des Codes zuende ist ...
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
Antworten