Projekt

Obecné

Profil

Stáhnout (17.4 KB) Statistiky
| Větev: | Tag: | Revize:
1 c137512e Oto Šťáva
#include "dbaccess.h"
2
#include <QSqlQueryModel>
3
#include <QSqlQuery>
4
#include <QSqlError>
5
#include <QSqlRecord>
6
#include <QDate>
7
#include <QList>
8
#include "QsLog.h"
9
10
#include <QtDebug>
11
12
dbAccess::dbAccess(QObject *parent) : QObject(parent)
13
{
14
    db = new QSqlDatabase( QSqlDatabase::addDatabase("QPSQL") );
15
    if (!db->isValid()) {
16
        QLOG_ERROR() << "db connection err: " << db->lastError().text();
17
    }
18
    result_query = new QSqlQuery(*db);
19
}
20
21
dbAccess::~dbAccess()
22
{
23
    if (db->isOpen()) {
24
        db->close();
25
    }
26
    QString cn = db->database().connectionName();
27
    db->removeDatabase(cn);
28
}
29
30
//! Připojení k databázi
31
/*!
32
  Funkce slouží pro připojení na databázi, kterou aplikace bude využívat. Databázový server může být
33
  kdekoliv v síti, takže mezi parametry je i IP adresa a síťový port.
34
  \param server Adresa server, na kterém je databáze.
35
  \param userName Uživatelské jméno.
36
  \param password Heslo.
37
  \param port Port, na kterém naslouchá databázový server.
38
  \param dbName Jméno databáze.
39
  \return True, pokud se podaří k databázi připojit, false pokud ne.
40
*/
41
bool dbAccess::connect(QString server, QString userName, QString password, int port, QString dbName)
42
{
43
    db->setConnectOptions();
44
    db->setHostName(server);
45
    db->setPort(port);
46
    db->setDatabaseName(dbName);
47
    db->setUserName(userName);
48
    db->setPassword(password);
49
50
    if(db->open()) {
51
        return true;
52
    }
53
    else {
54
        QLOG_ERROR() << "db connect err: " << db->lastError().text();
55
        return false;
56
    }
57
}
58
59
//! Vytvoření databázového modelu tabulky pacientů
60
/*!
61
  Funkce vytvoří databázový model kompletní tabulky pacientů, tento model lze posléze zobrazit v předem připraveném dialogu
62
  \param *m Ukazatel na objekt typu QSqlQueryModel.
63
*/
64
void dbAccess::getPatientsQueryModel(QSqlQueryModel *m)
65
{
66
    m->setQuery("select name, surname, birthdate, id_number, ind_id from patient", *db);
67
    if (m->lastError().isValid())
68
        qDebug() << m->lastError();
69
    m->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));
70
    m->setHeaderData(1, Qt::Horizontal, QObject::tr("Surname"));
71
    m->setHeaderData(2, Qt::Horizontal, QObject::tr("Birthdate"));
72
    m->setHeaderData(3, Qt::Horizontal, QObject::tr("ID number"));
73
    m->setHeaderData(4, Qt::Horizontal, QObject::tr("Indication ID"));
74
}
75
76
//! Vytvoření databázového modelu tabulky indikací
77
/*!
78
  Funkce vytvoří databázový model kompletní tabulky indikací, tento model lze posléze zobrazit v předem připraveném dialogu
79
  \param *m Ukazatel na objekt typu QSqlQueryModel.
80
*/
81
void dbAccess::getIndicationsQueryModel(QSqlQueryModel *m)
82
{
83
    m->setQuery("select indication, description, curve_name, procedure_time from indications", *db);
84
    if (m->lastError().isValid())
85
        qDebug() << m->lastError();
86
    m->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));
87
    m->setHeaderData(1, Qt::Horizontal, QObject::tr("Description"));
88
    m->setHeaderData(2, Qt::Horizontal, QObject::tr("Curve name"));
89
    m->setHeaderData(3, Qt::Horizontal, QObject::tr("Procedure time"));
90
}
91
92
//! Vytvoření databázového modelu tabulky výsledků
93
/*!
94
  Funkce vytvoří databázový model tabulky výsledků, tento model lze posléze zobrazit v předem připraveném dialogu.
95
  Model nemusí vytvořit pohled na celou tabulku, ale výsledky lze filtrovat podle ID pacienta a podle ID indikace.
96
  \param *m Ukazatel na objekt typu QSqlQueryModel.
97
  \param p_id ID pacienta
98
  \param ind_id ID indikace
99
*/
100
void dbAccess::getResultsQueryModel(QSqlQueryModel *m, int p_id, int ind_id)
101
{
102
    QString queryText = "SELECT p_id, ind_id, series, res_number, date, cycles, result FROM results";
103
104
    if (p_id != 0) {
105
        queryText += " WHERE p_id=" + QString::number(p_id);
106
        if (ind_id != 0) {
107
            queryText += " AND ind_id=" + QString::number(ind_id);
108
        }
109
    } else {
110
        if (ind_id != 0) {
111
            queryText += " WHERE ind_id=" + QString::number(ind_id);
112
        }
113
    }
114
    m->setQuery(queryText, *db);
115
    if (m->lastError().isValid())
116
        qDebug() << m->lastError();
117
    m->setHeaderData(0, Qt::Horizontal, QObject::tr("Patient ID"));
118
    m->setHeaderData(1, Qt::Horizontal, QObject::tr("Indication ID"));
119
    m->setHeaderData(2, Qt::Horizontal, QObject::tr("Series number"));
120
    m->setHeaderData(3, Qt::Horizontal, QObject::tr("Result number"));
121
    m->setHeaderData(4, Qt::Horizontal, QObject::tr("Date"));
122
    m->setHeaderData(5, Qt::Horizontal, QObject::tr("Cycles"));
123
    m->setHeaderData(6, Qt::Horizontal, QObject::tr("Results"));
124
}
125
126
//! Přidání nového pacienta do databáze
127
/*!
128
  Funkce je použita pro přidání údajů o novém pacientovi do databáze.
129
  \param name Jméno
130
  \param surname Příjmení
131
  \param birthdate Datum narození
132
  \param idNo Identifikační číslo pacienta (může to být RČ, nebo pořadové číslo....)
133
  \param indNo Indikace přiřazená danému pacientovi
134
*/
135
int dbAccess::addNewPatient(QString name, QString surname, QDate birthdate, QString idNo, QString indNo)
136
{
137
    QSqlQuery query(*db);
138
139
    query.prepare("INSERT INTO patient (name, surname, birthdate, id_number, ind_id)"
140
                  "VALUES (:name, :surname, :birthdate, :id_number, :ind_id)");
141
    query.bindValue(":name", name);
142
    query.bindValue(":surname", surname);
143
    query.bindValue(":birthdate", birthdate);
144
    query.bindValue(":id_number", idNo);
145
    query.bindValue(":ind_id", indNo);
146
147
    db->transaction();
148
    if (query.exec()) {
149
        db->commit();
150
151
        return ALL_OK;
152
    } else {
153
        qDebug() << query.lastError();
154
        db->rollback();
155
        return OTHER_ERR;
156
    }
157
}
158
159
//! Přidání nové indikace do databáze
160
/*!
161
  Funkce je použita pro přidání údajů o nové indikaci do databáze.
162
  \param name Jméno
163
  \param description Popis
164
  \param curveName Jméno cvičené křivky, odpovídající indikaci
165
  \param time Čas (v minutách), pokterý se bude daná křivka cvičit
166
 */
167
int dbAccess::addNewIndication(QString name, QString description, QString curveName, int time)
168
{
169
    QSqlQuery query(*db);
170
171
    query.prepare("INSERT INTO indications (indication, description, curve_name, procedure_time)"
172
                  "VALUES (:name, :description, :curve_name, :time)");
173
    query.bindValue(":name", name);
174
    query.bindValue(":description", description);
175
    query.bindValue(":curve_name", curveName);
176
    query.bindValue(":time", time);
177
178
    db->transaction();
179
    if (query.exec()) {
180
        db->commit();
181
        return ALL_OK;
182
    } else {
183
        qDebug() << query.lastError();
184
        db->rollback();
185
        return OTHER_ERR;
186
    }
187
    return ALL_OK;
188
}
189
190
//! Získání interního id pacienta
191
/*!
192
  Funkce je použita pro získání interního id daného pacienta na základě znalosti jeho identifikačního
193
  čísla. Interní ID se používá v dalších databázových dotazech
194
  \param pid Identifikační číslo pacienta
195
  \return Interní číslo pacienta
196
*/
197
int dbAccess::getPatientId(QString pid)
198
{
199
    QSqlQuery query(*db);
200
    int p_id = 0;
201
202
    if (query.exec("SELECT id FROM patient WHERE id_number=\'" + pid + "\'"))
203
    {
204
        while (query.next()) {
205
            p_id = query.value(0).toInt();
206
        }
207
    } else {
208
        qDebug() << query.lastError();
209
    }
210
    return p_id;
211
}
212
213
//! Získání interního id indikace
214
/*!
215
  Funkce je použita pro získání interního id dané indikace na základě znalosti jejího jména.
216
  Interní ID se používá v dalších databázových dotazech
217
  \param name Jméno indikace
218
  \return Interní číslo indikace
219
*/
220
int dbAccess::getIndicationId(QString name)
221
{
222
    QSqlQuery query(*db);
223
    int ind_id = 0;
224
225
    if (query.exec("SELECT ind_id FROM indications WHERE indication=\'" + name + "\'"))
226
    {
227
        while (query.next()) {
228
            ind_id = query.value(0).toInt();
229
        }
230
    } else {
231
        qDebug() << query.lastError();
232
    }
233
    return ind_id;
234
}
235
236
//! Získání údajů o indikaci
237
/*!
238
  Funkce je použita pro získání dalších informací o indikaci na základě znalosti jejího interního ID.
239
  \param[in] indId interní ID
240
  \param[out] *pTime doba trvání cvičení
241
  \param[out] *cName Jméno křivky
242
  \return True - data se podařilo načíst, False - data nelze načíst
243
*/
244
bool dbAccess::getIndicationInfo(int indId, int *pTime, QString *cName)
245
{
246
    QSqlQuery query(*db);
247
248
    if (query.exec("SELECT curve_name, procedure_time FROM indications WHERE ind_id=\'" + QString::number(indId) + "\'"))
249
    {
250
        while (query.next()) {
251
            *cName = query.value(0).toString();
252
            *pTime = query.value(1).toInt();
253
        }
254
    } else {
255
        qDebug() << query.lastError();
256
        return false;
257
    }
258
    return true;
259
260
}
261
262
//! Získání názvů všech indikací
263
/*!
264
  Funkce je použita pro získání názvů a interních ID všech indikací uložených v databázi.
265
  \param[out] *allIndIds Výsledný seznam všech interních ID
266
  \param[out] *allNames Seznam všech jmen indikací
267
  \return True - data se podařilo načíst, False - data nelze načíst
268
*/
269
bool dbAccess::getAllIndicationsName(QList<int> *allIndIds, QStringList *allNames)
270
{
271
    QSqlQuery query(*db);
272
273
    if (query.exec("SELECT ind_id, indication FROM indications")) {
274
        while (query.next()) {
275
            allIndIds->append(query.value(0).toInt());
276
            allNames->append(query.value(1).toString());
277
        }
278
    } else {
279
        qDebug() << query.lastError();
280
        return false;
281
    }
282
    return true;
283
}
284
285
//! Získání jmen všech pacientů
286
/*!
287
  Funkce je použita pro získání jmen a příjmení a interních ID všech pacientů uložených v databázi.
288
  \param[out] *allPIds Výsledný seznam všech interních ID
289
  \param[out] *allNames Seznam všech jmen pacientů
290
  \return True - data se podařilo načíst, False - data nelze načíst
291
*/
292
bool dbAccess::getAllPatientsName(QList<int> *allPIds, QStringList *allNames)
293
{
294
    QSqlQuery query(*db);
295
296
    if (query.exec("SELECT id, name, surname  FROM patient")) {
297
        while (query.next()) {
298
            allPIds->append(query.value(0).toInt());
299
            allNames->append(query.value(1).toString() + " " + query.value(2).toString());
300
        }
301
    } else {
302
        qDebug() << query.lastError();
303
        return false;
304
    }
305
    return true;
306
}
307
308
bool dbAccess::setActualIndication(int p_id, int ind_id)
309
{
310
    QSqlQuery query(*db);
311
    bool p_id_exists = false;
312
313
    if (query.exec("SELECT * FROM actual_indication WHERE id_p=" + QString::number(p_id))) {
314
        while (query.next()) {
315
            p_id_exists = true;
316
        }
317
    } else {
318
        qDebug() << query.lastError();
319
        return false;
320
    }
321
322
    if (p_id_exists) { //update
323
        if (query.exec("UPDATE actual_indication set id_ind=" + QString::number(ind_id) + " WHERE id_p=" + QString::number(p_id)))
324
            return true;
325
        else
326
            qDebug() << query.lastError();
327
    } else { //insert
328
        if (query.exec("INSERT INTO actual_indication VALUES (" + QString::number(p_id) + "," + QString::number(ind_id) +")"))
329
            return true;
330
        else
331
            qDebug() << query.lastError();
332
    }
333
334
    return false;
335
336
}
337
338
//! Získání pořadového čísla poslední série
339
/*!
340
  Funkce je použita pro získání pořadového čísla poslední série procedur pro pacienta s daným
341
interním identifikačním číslem
342
  \param p_id Interní identifikační číslo pacienta
343
  \return Pořadové číslo poslední série procedur
344
*/
345
int dbAccess::getLastSeriesNo(int p_id)
346
{
347
    int nRet = 0;
348
    QSqlQuery query(*db);
349
    QString seriesStr = QString::number(p_id);
350
351
    if (query.exec("SELECT series FROM results WHERE p_id=" + seriesStr + "ORDER BY series DESC LIMIT 1"))
352
    {
353
        while (query.next()) {
354
            nRet = query.value(0).toInt();
355
        }
356
    }
357
    return nRet;
358
}
359
360
//! Získání pořadového čísla poslední procedury v sérii
361
/*!
362
  Funkce je použita pro získání pořadového čísla poslední procedury v zadané sérii pro pacienta s daným
363
interním identifikačním číslem
364
  \param p_id Interní identifikační číslo pacienta
365
  \param series Pořadové číslo série, ke které se má vyhledat poslední procedura
366
  \return Pořadové číslo poslední procedury v dané sérii
367
*/
368
int dbAccess::getLastSeriesResultNo(int p_id, int series)
369
{
370
    int nRet = 0;
371
    QSqlQuery query(*db);
372
    QString seriesStr = QString::number(series);
373
374
    if (query.exec("SELECT res_number FROM results WHERE p_id=" + QString::number(p_id) + "AND series=" + seriesStr + "ORDER BY res_number DESC LIMIT 1"))
375
    {
376
        while (query.next()) {
377
            nRet = query.value(0).toInt();
378
        }
379
    }
380
    return nRet;
381
}
382
383
//! Vložení výsledku procedury
384
/*!
385
  Funkce je použita pro vložení výsledku procedury v zadané sérii pro prčitého pacienta a indikaci. Pořadové číslo procedury
386
se zvýší automaticky při zadání nového výsledku.
387
  \param p_id Interní identifikační číslo pacienta
388
  \param ind_id Interní identifikační číslo indikace
389
  \param series Pořadové číslo série, ke které se ukládá výsledek
390
  \param quality Seznam kvalit jednotlivých cyklů procedury
391
  \return True - výsledek se podařilo uložit, False - chyba při ukládání výsledku
392
*/
393
bool dbAccess::addResult(int p_id, int ind_id, int series, QList<int> quality)
394
{
395
    QSqlQuery query(*db);
396
    QString queryText;
397
    int res_no = getLastSeriesResultNo(p_id, series)+1;
398
    QDateTime now = QDateTime::currentDateTime();
399
400
    queryText = "INSERT INTO results(p_id, ind_id, series, res_number, date, cycles, result) VALUES (" + QString::number(p_id) + "," + QString::number(ind_id) + ",";
401
    queryText += QString::number(series) + ",";
402
    queryText += QString::number(res_no) + ",";
403
    queryText += " TIMESTAMP \'" + now.toString("yyyy-MM-dd hh:mm:ss") + "\',";
404
    queryText += QString::number(quality.size()) + ",'{";
405
406
    for(auto &val: quality) { //C++ 11 use
407
        queryText += QString::number(val) + ",";
408
    }
409
    queryText.chop(1);
410
    queryText += "}')";
411
412
    if (!query.exec(queryText)) {
413
        qDebug() << query.lastError();
414
        return false;
415
    }
416
417
    return true;
418
}
419
420
/*! Získání jednotlivého výsledku
421
 Po volání funkce getResultsNumber lze použít tuto funkci, která při každém volání vrátí výsledky další procedury
422
 \param[out] *cycles Počet cyklů procedury
423
 \param[out] *quality Seznam kvalit cvičení pro každý cyklus procedury
424
 \return true - dotaz byl ukončen úspěšně, false - chyba při volání dotazu
425
 \sa getResultsNumber()
426
 */
427
bool dbAccess::getNextResult(int *cycles, QString *quality)
428
{
429
    if (result_query->isActive()) {
430
        if (result_query->next()) {
431
            *cycles = result_query->value(0).toInt();
432
            *quality = result_query->value(1).toString();
433
            return true;
434
        }
435
    }
436
    return false;
437
}
438
439
//! Získání průměrné hodnoty kvality cvičení pro každou proceduru v dané sérii
440
/*!
441
  Funkce je použita pro získání průměrné hodnoty kvality cvičení pro každou proceduru
442
 v dané sérii pro pacienta s požadovaným interním identifikačním číslem
443
  \param p_id Interní identifikační číslo pacienta
444
  \param series Pořadové číslo série, ke které se mají vyhledat průměry
445
  \param *avg - pole, které bude obsahovat jednotlivé průměry kvality cvičení
446
  \return Pořadové číslo poslední procedury v dané sérii
447
*/
448
bool dbAccess::getSeriesResultAvg(int p_id, int series, QList<int> *avg)
449
{
450
    QString res, queryText = "SELECT result FROM results";
451
    QStringList partQ;
452
    int quality;
453
    QSqlQuery query(*db);
454
455
    queryText += " WHERE p_id=" + QString::number(p_id);
456
    queryText += " AND series=" + QString::number(series);
457
    queryText += "ORDER BY res_number ASC";
458
459
    avg->clear();
460
461
    if (query.exec(queryText)) {
462
        while (query.next()) {
463
            res = query.value(0).toString();
464
            //remove '{' and '}' from result string
465
            if (res.contains('{'))
466
                res.remove(0,1);
467
            if (res.contains('}'))
468
                res.chop(1);
469
            partQ = res.split(",");
470
            quality = 0;
471
            for (auto &str : partQ ) {
472
                quality += str.toInt();
473
            }
474
            avg->append(quality/partQ.size());
475
        }
476
    } else {
477
        qDebug() << result_query->lastError();
478
        return false;
479
    }
480
    return true;
481
}
482
483
/*! Získání počtu výsledků
484
 *!
485
 Funkce slouží pro získání celkového počtu výsledků pro zadané číslo pacienta a procedury. Pokud je číslo pacienta, nebo procedury 0,
486
 vyhledávají se výsledky pro všechny pacienty, nebo indikace. Funkce také slouží jako start pro iteraci přes jednotlivé výsledky. Pro iteraci slouží funkce
487
 getNextResult()
488
 \param[in] p_id Interní číslo pacienta
489
 \param[in] ind_id Interní číslo indikace
490
 \param[out] *results_count počet výsledků, které odpovídají zadaným parametrům p_id a ind_id
491
 \return true - dotaz byl ukončen úspěšně, false - chyba při volání dotazu
492
 \sa getNextResult()
493
*/
494
bool dbAccess::getResultsNumber(int p_id, int ind_id, int *results_count)
495
{
496
    QString queryText = "SELECT cycles, result FROM results";
497
498
    if (p_id != 0) {
499
        queryText += " WHERE p_id=" + QString::number(p_id);
500
        if (ind_id != 0) {
501
            queryText += " AND ind_id=" + QString::number(ind_id);
502
        }
503
    } else {
504
        if (ind_id != 0) {
505
            queryText += " WHERE ind_id=" + QString::number(ind_id);
506
        }
507
    }
508
509
    if (result_query->exec(queryText)) {
510
        *results_count = result_query->size();
511
    } else {
512
        qDebug() << result_query->lastError();
513
        return false;
514
    }
515
    return true;
516
}