2026-10-18 17:40:59 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
|
|
#include "DbTest.h"
|
|
|
|
|
#include "ConnectionConfig.h"
|
|
|
|
|
#include "OpenDatabase.h"
|
|
|
|
|
#include "crud/CrudModel.h"
|
|
|
|
|
#include "crud/DataGridWidget.h"
|
|
|
|
|
#include "Pgsql_Connection.h"
|
|
|
|
|
|
2026-10-18 17:55:26 +02:00
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDeadlineTimer>
|
2026-10-18 17:40:59 +02:00
|
|
|
#include <QSortFilterProxyModel>
|
2026-10-18 17:55:26 +02:00
|
|
|
#include "catalog/PgClassContainer.h"
|
|
|
|
|
#include "catalog/PgDatabaseCatalog.h"
|
2026-10-18 17:40:59 +02:00
|
|
|
#include <QUrl>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
class DataGridTest : public pgtest::DbTest {
|
|
|
|
|
protected:
|
|
|
|
|
std::shared_ptr<OpenDatabase> openDb()
|
|
|
|
|
{
|
|
|
|
|
QUrl url(dbUrl());
|
|
|
|
|
ConnectionConfig cfg;
|
|
|
|
|
cfg.setHost(url.host());
|
|
|
|
|
cfg.setPort(static_cast<unsigned short>(url.port(5432)));
|
|
|
|
|
cfg.setUser(url.userName());
|
|
|
|
|
cfg.setPassword(url.password());
|
|
|
|
|
cfg.setDbname(url.path().mid(1));
|
|
|
|
|
return OpenDatabase::createOpenDatabase(cfg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Runs the query and shows its result in a grid
|
|
|
|
|
void showQuery(const char *sql)
|
|
|
|
|
{
|
|
|
|
|
db = openDb();
|
|
|
|
|
auto result = std::make_shared<Pgsql::Result>(conn().query(sql));
|
|
|
|
|
model = std::make_unique<CrudModel>();
|
|
|
|
|
widget = std::make_unique<DataGridWidget>();
|
|
|
|
|
widget->setSourceModel(model.get());
|
|
|
|
|
model->setResult(db, result);
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-18 17:55:26 +02:00
|
|
|
/// Shows a whole table (CRUD mode) and waits for the asynchronous load to finish
|
|
|
|
|
bool showTable(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
db = openDb();
|
|
|
|
|
auto table = db->catalog()->classes()->findIf([&name](const PgClass &c)
|
|
|
|
|
{ return c.fullyQualifiedQuotedObjectName().endsWith("." + name); });
|
|
|
|
|
if (!table)
|
|
|
|
|
return false;
|
|
|
|
|
model = std::make_unique<CrudModel>();
|
|
|
|
|
widget = std::make_unique<DataGridWidget>();
|
|
|
|
|
widget->setSourceModel(model.get());
|
|
|
|
|
bool reset = false;
|
|
|
|
|
QObject::connect(model.get(), &QAbstractItemModel::modelReset, model.get(), [&reset] { reset = true; });
|
|
|
|
|
model->setConfig(db, *table);
|
|
|
|
|
QDeadlineTimer deadline(10000);
|
|
|
|
|
while (!reset && !deadline.hasExpired())
|
|
|
|
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
|
|
|
|
|
return reset;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-18 17:40:59 +02:00
|
|
|
/// Editable flag of every result column, as seen through the widget's proxy
|
|
|
|
|
std::vector<bool> editableColumns()
|
|
|
|
|
{
|
|
|
|
|
auto proxy = widget->proxy();
|
|
|
|
|
std::vector<bool> r;
|
|
|
|
|
for (int c = 1; c < proxy->columnCount(); ++c)
|
|
|
|
|
r.push_back(proxy->flags(proxy->index(0, c)) & Qt::ItemIsEditable);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString columnName(int resultCol)
|
|
|
|
|
{
|
|
|
|
|
return widget->proxy()->headerData(resultCol + 1, Qt::Horizontal).toString().section('\n', 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Reads a single cell with the test's own connection
|
|
|
|
|
std::optional<std::string> dbValue(const char *sql)
|
|
|
|
|
{
|
|
|
|
|
auto res = conn().query(sql);
|
|
|
|
|
auto v = res.get(0, 0);
|
|
|
|
|
if (v.null())
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
return std::string(v.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<OpenDatabase> db;
|
|
|
|
|
std::unique_ptr<CrudModel> model;
|
|
|
|
|
std::unique_ptr<DataGridWidget> widget;
|
|
|
|
|
};
|