Can use the parameter list in the query window now.
Still requires extensive testing for all possible types.
This commit is contained in:
parent
aefc9eb7ba
commit
3af26d915e
14 changed files with 461 additions and 242 deletions
|
|
@ -51,6 +51,16 @@ bool ASyncDBConnection::send(const std::string &command, on_result_callback on_r
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASyncDBConnection::send(const std::string &command, Pgsql::Params params, on_result_callback on_result)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lg(m_threadData.m_commandQueue.m_mutex);
|
||||||
|
m_threadData.m_commandQueue.m_queue.emplace(command, std::move(params), on_result);
|
||||||
|
m_threadData.m_commandQueue.m_newEvent.set();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ASyncDBConnection::cancel()
|
bool ASyncDBConnection::cancel()
|
||||||
{
|
{
|
||||||
return m_threadData.cancel();
|
return m_threadData.cancel();
|
||||||
|
|
@ -243,14 +253,18 @@ void ASyncDBConnection::Thread::doNewCommand()
|
||||||
{
|
{
|
||||||
// todo: send command
|
// todo: send command
|
||||||
// get command from top of queue (but leave it in the queue, we need the callback)
|
// get command from top of queue (but leave it in the queue, we need the callback)
|
||||||
std::string command;
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lg(m_commandQueue.m_mutex);
|
std::lock_guard<std::mutex> lg(m_commandQueue.m_mutex);
|
||||||
if (! m_commandQueue.m_queue.empty()) {
|
if (! m_commandQueue.m_queue.empty()) {
|
||||||
command = m_commandQueue.m_queue.front().command;
|
const Command &command = m_commandQueue.m_queue.front();
|
||||||
}
|
if (!command.command.empty()) {
|
||||||
}
|
bool query_send = false;
|
||||||
if (!command.empty() && m_connection.sendQuery(command)) {
|
if (command.params.empty())
|
||||||
|
query_send = m_connection.sendQuery(command.command.c_str());
|
||||||
|
else
|
||||||
|
query_send = m_connection.sendQueryParams(command.command.c_str(), command.params);
|
||||||
|
|
||||||
|
if (query_send) {
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
doStateCallback(State::QuerySend);
|
doStateCallback(State::QuerySend);
|
||||||
}
|
}
|
||||||
|
|
@ -259,6 +273,10 @@ void ASyncDBConnection::Thread::doNewCommand()
|
||||||
// todo: need to report the error
|
// todo: need to report the error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ASyncDBConnection::Thread::waitForResult()
|
void ASyncDBConnection::Thread::waitForResult()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define ASYNCDBCONNECTION_H
|
#define ASYNCDBCONNECTION_H
|
||||||
|
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
|
#include "Pgsql_Params.h"
|
||||||
#include "win32event.h"
|
#include "win32event.h"
|
||||||
#include "connectionconfig.h"
|
#include "connectionconfig.h"
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
|
@ -48,6 +49,7 @@ public:
|
||||||
If the command gives multiple results on_result will be called for each result.
|
If the command gives multiple results on_result will be called for each result.
|
||||||
*/
|
*/
|
||||||
bool send(const std::string &command, on_result_callback on_result);
|
bool send(const std::string &command, on_result_callback on_result);
|
||||||
|
bool send(const std::string &command, Pgsql::Params params, on_result_callback on_result);
|
||||||
|
|
||||||
bool cancel();
|
bool cancel();
|
||||||
|
|
||||||
|
|
@ -56,12 +58,16 @@ private:
|
||||||
class Command {
|
class Command {
|
||||||
public:
|
public:
|
||||||
std::string command;
|
std::string command;
|
||||||
|
Pgsql::Params params;
|
||||||
on_result_callback on_result;
|
on_result_callback on_result;
|
||||||
|
|
||||||
Command() = default;
|
Command() = default;
|
||||||
Command(const std::string &cmd, on_result_callback cb)
|
Command(const std::string &cmd, on_result_callback cb)
|
||||||
: command(cmd), on_result(cb)
|
: command(cmd), on_result(cb)
|
||||||
{}
|
{}
|
||||||
|
Command(const std::string &cmd, Pgsql::Params &&p, on_result_callback cb)
|
||||||
|
: command(cmd), params(p), on_result(cb)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains all the members accessed by the thread
|
/// Contains all the members accessed by the thread
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ QVariant ParamListModel::headerData(int section, Qt::Orientation orientation, in
|
||||||
QVariant result;
|
QVariant result;
|
||||||
if (orientation == Qt::Horizontal) {
|
if (orientation == Qt::Horizontal) {
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
if (section == 0) {
|
switch (section) {
|
||||||
// result = tr("$n");
|
case ColValue:
|
||||||
result = tr("Value");
|
result = tr("Value");
|
||||||
}
|
break;
|
||||||
else if (section == 1) {
|
case ColType:
|
||||||
result = tr("Type");
|
result = tr("Type");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,20 +40,14 @@ QVariant ParamListModel::headerData(int section, Qt::Orientation orientation, in
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
int ParamListModel::rowCount(const QModelIndex &parent) const
|
int ParamListModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
//if (parent.isValid())
|
return m_paramList.size();
|
||||||
return 2;
|
|
||||||
|
|
||||||
// FIXME: Implement me!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParamListModel::columnCount(const QModelIndex &parent) const
|
int ParamListModel::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
//if (parent.isValid())
|
return ColumnCount;
|
||||||
return 2;
|
|
||||||
|
|
||||||
// FIXME: Implement me!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ParamListModel::data(const QModelIndex &index, int role) const
|
QVariant ParamListModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
@ -62,29 +57,41 @@ QVariant ParamListModel::data(const QModelIndex &index, int role) const
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
int col = index.column();
|
int col = index.column();
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
|
const auto& record = m_paramList[row];
|
||||||
switch (col) {
|
switch (col) {
|
||||||
case 0: // value column
|
case ColValue: // value column
|
||||||
result = tr("val, %1").arg(row);
|
result = record.value; // tr("val, %1").arg(row);
|
||||||
break;
|
break;
|
||||||
case 1: // type column
|
case ColType: // type column
|
||||||
result = tr("type, %1").arg(row);
|
result = record.type; // tr("type, %1").arg(row);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement me!
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParamListModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
bool ParamListModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
{
|
{
|
||||||
if (data(index, role) != value) {
|
if (data(index, role) != value) {
|
||||||
// // FIXME: Implement me!
|
if (role == Qt::EditRole) {
|
||||||
|
int row = index.row();
|
||||||
|
int col = index.column();
|
||||||
|
auto& record = m_paramList[row];
|
||||||
|
switch (col) {
|
||||||
|
case ColValue:
|
||||||
|
record.value = value.toString();
|
||||||
|
break;
|
||||||
|
case ColType:
|
||||||
|
record.type = value.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QVector<int>() << role);
|
emit dataChanged(index, index, QVector<int>() << role);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,16 +100,18 @@ Qt::ItemFlags ParamListModel::flags(const QModelIndex &index) const
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
return Qt::ItemIsEnabled | Qt::ItemIsEditable; // FIXME: Implement me!
|
return Qt::ItemIsEnabled | Qt::ItemIsEditable;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool ParamListModel::insertRows(int row, int count, const QModelIndex &parent)
|
bool ParamListModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||||
//{
|
{
|
||||||
// beginInsertRows(parent, row, row + count - 1);
|
beginInsertRows(parent, row, row + count - 1);
|
||||||
// // FIXME: Implement me!
|
// FIXME: Implement me!
|
||||||
// endInsertRows();
|
auto iter = m_paramList.begin() + row;
|
||||||
// return false;
|
m_paramList.insert(iter, count, Param());
|
||||||
//}
|
endInsertRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//bool ParamListModel::insertColumns(int column, int count, const QModelIndex &parent)
|
//bool ParamListModel::insertColumns(int column, int count, const QModelIndex &parent)
|
||||||
//{
|
//{
|
||||||
|
|
@ -111,13 +120,14 @@ Qt::ItemFlags ParamListModel::flags(const QModelIndex &index) const
|
||||||
// endInsertColumns();
|
// endInsertColumns();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//bool ParamListModel::removeRows(int row, int count, const QModelIndex &parent)
|
bool ParamListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||||
//{
|
{
|
||||||
// beginRemoveRows(parent, row, row + count - 1);
|
beginRemoveRows(parent, row, row + count - 1);
|
||||||
// // FIXME: Implement me!
|
auto iter = m_paramList.begin() + row;
|
||||||
// endRemoveRows();
|
m_paramList.erase(iter, iter + count);
|
||||||
// return false;
|
endRemoveRows();
|
||||||
//}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//bool ParamListModel::removeColumns(int column, int count, const QModelIndex &parent)
|
//bool ParamListModel::removeColumns(int column, int count, const QModelIndex &parent)
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,29 @@
|
||||||
#define PARAMLISTMODEL_H
|
#define PARAMLISTMODEL_H
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
#include <vector>
|
||||||
|
#include "Pgsql_declare.h"
|
||||||
|
|
||||||
class ParamListModel : public QAbstractTableModel
|
class ParamListModel : public QAbstractTableModel {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
class Param {
|
||||||
|
public:
|
||||||
|
QString value; ///< the value of the parameter (currently this is passed directly)
|
||||||
|
QString type = InvalidOid; ///< the type of the parameter
|
||||||
|
|
||||||
|
Param() = default;
|
||||||
|
Param(const QString &v, const QString t)
|
||||||
|
: value(v), type(t)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum e_Column {
|
||||||
|
ColValue = 0,
|
||||||
|
ColType,
|
||||||
|
ColumnCount // Keep last not a column just the count
|
||||||
|
};
|
||||||
|
|
||||||
explicit ParamListModel(QObject *parent = 0);
|
explicit ParamListModel(QObject *parent = 0);
|
||||||
|
|
||||||
// Header:
|
// Header:
|
||||||
|
|
@ -26,16 +43,15 @@ public:
|
||||||
int role = Qt::EditRole) override;
|
int role = Qt::EditRole) override;
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
|
||||||
// Add data:
|
auto begin() const { return m_paramList.begin(); }
|
||||||
// bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
auto end() const { return m_paramList.end(); }
|
||||||
//bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
|
|
||||||
|
|
||||||
// Remove data:
|
|
||||||
// bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
|
||||||
//bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
using t_ParamList = std::vector<Param>;
|
||||||
|
t_ParamList m_paramList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PARAMLISTMODEL_H
|
#endif // PARAMLISTMODEL_H
|
||||||
|
|
|
||||||
|
|
@ -33,3 +33,67 @@ QWidget *ParamTypeDelegate::createEditor(QWidget *parent,
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParamTypeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
// if (index.data().canConvert<StarRating>()) {
|
||||||
|
// StarRating starRating = qvariant_cast<StarRating>(index.data());
|
||||||
|
// StarEditor *starEditor = qobject_cast<StarEditor *>(editor);
|
||||||
|
// starEditor->setStarRating(starRating);
|
||||||
|
// } else {
|
||||||
|
// QStyledItemDelegate::setEditorData(editor, index);
|
||||||
|
// }
|
||||||
|
if (index.column() == 1) {
|
||||||
|
QComboBox *cmbbx = dynamic_cast<QComboBox*>(editor);
|
||||||
|
if (cmbbx) {
|
||||||
|
auto data = index.data();
|
||||||
|
if (data.canConvert<QString>()) {
|
||||||
|
QModelIndexList indexes = m_typeSelectionModel->match(
|
||||||
|
m_typeSelectionModel->index(0, 1), Qt::DisplayRole, data, 1, Qt::MatchFlags( Qt::MatchExactly ));
|
||||||
|
if (!indexes.empty()) {
|
||||||
|
cmbbx->setCurrentIndex(indexes.at(0).row());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmbbx->setCurrentIndex(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QStyledItemDelegate::setEditorData(editor, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParamTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
// if (index.data().canConvert<StarRating>()) {
|
||||||
|
// StarEditor *starEditor = qobject_cast<StarEditor *>(editor);
|
||||||
|
// model->setData(index, QVariant::fromValue(starEditor->starRating()));
|
||||||
|
// } else {
|
||||||
|
// QStyledItemDelegate::setModelData(editor, model, index);
|
||||||
|
// }
|
||||||
|
if (index.column() == 1) {
|
||||||
|
QComboBox *cmbbx = dynamic_cast<QComboBox*>(editor);
|
||||||
|
if (cmbbx) {
|
||||||
|
auto data = index.data();
|
||||||
|
if (data.canConvert<QString>()) {
|
||||||
|
QVariant d = m_typeSelectionModel->data(
|
||||||
|
m_typeSelectionModel->index(cmbbx->currentIndex(), 0));
|
||||||
|
model->setData(index, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QStyledItemDelegate::setModelData(editor, model, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// triggered by editing finished from editor
|
||||||
|
void ParamTypeDelegate::commitAndCloseEditor()
|
||||||
|
{
|
||||||
|
// StarEditor *editor = qobject_cast<StarEditor *>(sender());
|
||||||
|
// emit commitData(editor);
|
||||||
|
// emit closeEditor(editor);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ class TypeSelectionItemModel;
|
||||||
/** Item delegate for supplying a combobox for selected the parameter type in
|
/** Item delegate for supplying a combobox for selected the parameter type in
|
||||||
* the parameter list.
|
* the parameter list.
|
||||||
*/
|
*/
|
||||||
class ParamTypeDelegate : public QStyledItemDelegate
|
class ParamTypeDelegate : public QStyledItemDelegate {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ParamTypeDelegate();
|
ParamTypeDelegate();
|
||||||
|
|
@ -18,8 +17,14 @@ public:
|
||||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||||
const QModelIndex &index) const override;
|
const QModelIndex &index) const override;
|
||||||
void setTypeSelectionModel(TypeSelectionItemModel* model);
|
void setTypeSelectionModel(TypeSelectionItemModel* model);
|
||||||
|
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||||
|
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||||
|
const QModelIndex &index) const override;
|
||||||
private:
|
private:
|
||||||
TypeSelectionItemModel* m_typeSelectionModel = nullptr;
|
TypeSelectionItemModel* m_typeSelectionModel = nullptr;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void commitAndCloseEditor();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PARAMTYPEDELEGATE_H
|
#endif // PARAMTYPEDELEGATE_H
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
#include "Pgsql_declare.h"
|
#include "Pgsql_declare.h"
|
||||||
|
#include "Pgsql_Params.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -158,6 +159,15 @@ bool Connection::sendQuery(const char *query)
|
||||||
return res == 1;
|
return res == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Connection::sendQueryParams(const char * command, const Params ¶ms)
|
||||||
|
{
|
||||||
|
int res = PQsendQueryParams(conn, command, params.size(), params.types(),
|
||||||
|
params.values(), params.lengths(), params.formats(),
|
||||||
|
0); // text format
|
||||||
|
|
||||||
|
return res == 1;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Result> Connection::getResult()
|
std::shared_ptr<Result> Connection::getResult()
|
||||||
{
|
{
|
||||||
PGresult *r = PQgetResult(conn);
|
PGresult *r = PQgetResult(conn);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ namespace Pgsql {
|
||||||
|
|
||||||
|
|
||||||
class Result;
|
class Result;
|
||||||
|
class Params;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -126,6 +127,8 @@ namespace Pgsql {
|
||||||
return sendQuery(command.toUtf8().data());
|
return sendQuery(command.toUtf8().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sendQueryParams(const char * command, const Params ¶ms);
|
||||||
|
|
||||||
std::shared_ptr<Result> getResult();
|
std::shared_ptr<Result> getResult();
|
||||||
|
|
||||||
bool consumeInput();
|
bool consumeInput();
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,26 @@ Params& Params::operator=(const Params& rhs)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Params::Params(const Params&& rhs)
|
Params::Params(Params&& rhs)
|
||||||
: m_paramTypes(std::move(rhs.m_paramTypes))
|
: m_paramTypes(std::move(rhs.m_paramTypes))
|
||||||
, m_paramValues(std::move(rhs.m_paramValues))
|
, m_paramValues(std::move(rhs.m_paramValues))
|
||||||
, m_paramLengths(std::move(rhs.m_paramLengths))
|
, m_paramLengths(std::move(rhs.m_paramLengths))
|
||||||
, m_paramFormats(std::move(rhs.m_paramFormats))
|
, m_paramFormats(std::move(rhs.m_paramFormats))
|
||||||
{}
|
{
|
||||||
|
//rhs.m_paramValues.clear(); // make sure origin is empty, to prevent double deletion
|
||||||
|
}
|
||||||
|
|
||||||
|
Params& Params::operator=(Params&& rhs)
|
||||||
|
{
|
||||||
|
if (&rhs != this) {
|
||||||
|
m_paramTypes = std::move(rhs.m_paramTypes);
|
||||||
|
m_paramValues = std::move(rhs.m_paramValues);
|
||||||
|
//rhs.m_paramValues.clear(); // make sure origin is empty, to prevent double deletion
|
||||||
|
m_paramLengths = std::move(rhs.m_paramLengths);
|
||||||
|
m_paramFormats = std::move(rhs.m_paramFormats);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Params::~Params()
|
Params::~Params()
|
||||||
{
|
{
|
||||||
|
|
@ -49,8 +63,9 @@ void Params::add(const QString &s, Oid oid)
|
||||||
{
|
{
|
||||||
auto ba = s.toUtf8();
|
auto ba = s.toUtf8();
|
||||||
const int len = ba.size();
|
const int len = ba.size();
|
||||||
char * p = new char[len];
|
char * p = new char[len+1];
|
||||||
std::memcpy(p, ba.data(), len);
|
std::memcpy(p, ba.data(), len);
|
||||||
|
p[len] = 0;
|
||||||
addText(p, oid);
|
addText(p, oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ namespace Pgsql {
|
||||||
Params();
|
Params();
|
||||||
Params(const Params& rhs);
|
Params(const Params& rhs);
|
||||||
Params& operator=(const Params& rhs);
|
Params& operator=(const Params& rhs);
|
||||||
Params(const Params&& rhs);
|
Params(Params&& rhs);
|
||||||
|
Params& operator=(Params&& rhs);
|
||||||
~Params();
|
~Params();
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -26,6 +27,14 @@ namespace Pgsql {
|
||||||
void addBinary(const char *data, int length, Oid oid);
|
void addBinary(const char *data, int length, Oid oid);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
bool empty() const { return m_paramTypes.empty(); }
|
||||||
|
int size() const { return m_paramTypes.size(); }
|
||||||
|
|
||||||
|
const Oid* types() const { return m_paramTypes.data(); }
|
||||||
|
const char* const* values() const { return m_paramValues.data(); }
|
||||||
|
const int* lengths() const { return m_paramLengths.data(); }
|
||||||
|
const int* formats() const { return m_paramFormats.data(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using t_paramValues = std::vector<const char *>;
|
using t_paramValues = std::vector<const char *>;
|
||||||
|
|
||||||
|
|
|
||||||
118
src/QueryTab.cpp
118
src/QueryTab.cpp
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SqlSyntaxHighlighter.h"
|
#include "SqlSyntaxHighlighter.h"
|
||||||
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
|
|
@ -19,6 +20,44 @@
|
||||||
#include "pgsqldatabasecatalogue.h"
|
#include "pgsqldatabasecatalogue.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
QueryParamListController::QueryParamListController(QTableView *tv,
|
||||||
|
OpenDatabase *opendb, QWidget *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, paramTableView(tv)
|
||||||
|
, m_openDatabase(opendb)
|
||||||
|
{
|
||||||
|
m_typeDelegate.setTypeSelectionModel(opendb->typeSelectionModel());
|
||||||
|
|
||||||
|
paramTableView->setModel(&m_paramList);
|
||||||
|
paramTableView->setItemDelegateForColumn(1, &m_typeDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pgsql::Params QueryParamListController::params() const
|
||||||
|
{
|
||||||
|
Pgsql::Params params;
|
||||||
|
auto types = m_openDatabase->catalogue()->types();
|
||||||
|
for (auto e : m_paramList) {
|
||||||
|
Oid oid = types->getByName(e.type).oid;
|
||||||
|
params.add(e.value, oid);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryParamListController::on_addParam()
|
||||||
|
{
|
||||||
|
m_paramList.insertRows(m_paramList.rowCount(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryParamListController::on_removeParam()
|
||||||
|
{
|
||||||
|
auto rc = m_paramList.rowCount();
|
||||||
|
if (rc > 0)
|
||||||
|
m_paramList.removeRows(rc-1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::QueryTab),
|
ui(new Ui::QueryTab),
|
||||||
|
|
@ -43,20 +82,16 @@ QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
|
||||||
ui->queryEdit->setFont(font);
|
ui->queryEdit->setFont(font);
|
||||||
|
|
||||||
OpenDatabase* open_database = m_win->getDatabase();
|
OpenDatabase* open_database = m_win->getDatabase();
|
||||||
m_typeDelegate.setTypeSelectionModel(open_database->typeSelectionModel());
|
|
||||||
|
|
||||||
auto cat = open_database->catalogue();
|
auto cat = open_database->catalogue();
|
||||||
|
|
||||||
highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document());
|
highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document());
|
||||||
highlighter->setTypes(cat->types());
|
highlighter->setTypes(cat->types());
|
||||||
|
|
||||||
ui->paramTableView->setModel(&m_paramList);
|
|
||||||
ui->paramTableView->setItemDelegateForColumn(1, &m_typeDelegate);
|
|
||||||
|
|
||||||
connect(ui->queryEdit, &QPlainTextEdit::textChanged, this, &QueryTab::queryTextChanged);
|
connect(ui->queryEdit, &QPlainTextEdit::textChanged, this, &QueryTab::queryTextChanged);
|
||||||
// m_stopwatch.setOutputLabel(ui->lblElapsedTime);
|
|
||||||
// ui->lblElapsedTime->clear();
|
m_queryParamListController = new QueryParamListController(ui->paramTableView, open_database, this);
|
||||||
// ui->lblRowCount->clear();
|
connect(ui->addButton, &QPushButton::clicked, m_queryParamListController, &QueryParamListController::on_addParam);
|
||||||
|
connect(ui->removeButton, &QPushButton::clicked, m_queryParamListController, &QueryParamListController::on_removeParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryTab::~QueryTab()
|
QueryTab::~QueryTab()
|
||||||
|
|
@ -64,16 +99,12 @@ QueryTab::~QueryTab()
|
||||||
m_dbConnection.closeConnection();
|
m_dbConnection.closeConnection();
|
||||||
m_dbConnection.setStateCallback(nullptr);
|
m_dbConnection.setStateCallback(nullptr);
|
||||||
|
|
||||||
// delete m_pgTypes;
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryTab::setConfig(const ConnectionConfig &config)
|
void QueryTab::setConfig(const ConnectionConfig &config)
|
||||||
{
|
{
|
||||||
m_config = config;
|
m_config = config;
|
||||||
// QString title = "pglab - ";
|
|
||||||
// title += m_config.name().c_str();
|
|
||||||
// setWindowTitle(title);
|
|
||||||
m_win->QueueTask([this]() { startConnect(); });
|
m_win->QueueTask([this]() { startConnect(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,30 +120,6 @@ bool QueryTab::canClose()
|
||||||
return can_close;
|
return can_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
//void QueryTab::open()
|
|
||||||
//{
|
|
||||||
// if (m_queryTextChanged && !continueWithoutSavingWarning()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory);
|
|
||||||
// QString file_name = QFileDialog::getOpenFileName(this,
|
|
||||||
// tr("Open sql query"), home_dir, tr("SQL files (*.sql *.txt)"));
|
|
||||||
// if ( ! file_name.isEmpty()) {
|
|
||||||
// QFile file(file_name);
|
|
||||||
// if (file.open(QIODevice::ReadWrite)) {
|
|
||||||
// QTextStream stream(&file);
|
|
||||||
// ui->queryEdit->clear();
|
|
||||||
// while (!stream.atEnd()){
|
|
||||||
// QString line = stream.readLine();
|
|
||||||
// ui->queryEdit->appendPlainText(line);
|
|
||||||
// }
|
|
||||||
// m_queryTextChanged = false;
|
|
||||||
// setFileName(file_name);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
void QueryTab::newdoc()
|
void QueryTab::newdoc()
|
||||||
{
|
{
|
||||||
ui->queryEdit->clear();
|
ui->queryEdit->clear();
|
||||||
|
|
@ -183,6 +190,7 @@ void QueryTab::execute()
|
||||||
std::string cmd = getCommand();
|
std::string cmd = getCommand();
|
||||||
m_stopwatch.start();
|
m_stopwatch.start();
|
||||||
m_dbConnection.send(cmd,
|
m_dbConnection.send(cmd,
|
||||||
|
m_queryParamListController->params(),
|
||||||
[this](std::shared_ptr<Pgsql::Result> res, qint64 elapsedms)
|
[this](std::shared_ptr<Pgsql::Result> res, qint64 elapsedms)
|
||||||
{
|
{
|
||||||
m_win->QueueTask([this, res, elapsedms]() { query_ready(res, elapsedms); });
|
m_win->QueueTask([this, res, elapsedms]() { query_ready(res, elapsedms); });
|
||||||
|
|
@ -295,26 +303,6 @@ void QueryTab::queryTextChanged()
|
||||||
|
|
||||||
void QueryTab::connectionStateChanged(ASyncDBConnection::State state)
|
void QueryTab::connectionStateChanged(ASyncDBConnection::State state)
|
||||||
{
|
{
|
||||||
// QString status_str;
|
|
||||||
// switch (state) {
|
|
||||||
// case ASyncDBConnection::State::NotConnected:
|
|
||||||
// status_str = tr("Geen verbinding");
|
|
||||||
// break;
|
|
||||||
// case ASyncDBConnection::State::Connecting:
|
|
||||||
// status_str = tr("Verbinden");
|
|
||||||
// break;
|
|
||||||
// case ASyncDBConnection::State::Connected:
|
|
||||||
// status_str = tr("Verbonden");
|
|
||||||
// break;
|
|
||||||
// case ASyncDBConnection::State::QuerySend:
|
|
||||||
// status_str = tr("Query verstuurd");
|
|
||||||
// break;
|
|
||||||
// case ASyncDBConnection::State::CancelSend:
|
|
||||||
// status_str = tr("Query geannuleerd");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// addLog(status_str);
|
|
||||||
|
|
||||||
QTabWidget *tabwidget = getTabWidget();
|
QTabWidget *tabwidget = getTabWidget();
|
||||||
if (tabwidget) {
|
if (tabwidget) {
|
||||||
int i = tabwidget->indexOf(this);
|
int i = tabwidget->indexOf(this);
|
||||||
|
|
@ -334,13 +322,6 @@ void QueryTab::connectionStateChanged(ASyncDBConnection::State state)
|
||||||
}
|
}
|
||||||
tabwidget->setTabIcon(i, QIcon(iconname));
|
tabwidget->setTabIcon(i, QIcon(iconname));
|
||||||
}
|
}
|
||||||
|
|
||||||
// statusBar()->showMessage(status_str);
|
|
||||||
|
|
||||||
// bool connected = ASyncDBConnection::State::Connected == state;
|
|
||||||
// ui->actionExecute_SQL->setEnabled(connected);
|
|
||||||
// ui->actionExplain_Analyze->setEnabled(connected);
|
|
||||||
// ui->actionCancel->setEnabled(ASyncDBConnection::State::QuerySend == state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -488,16 +469,9 @@ void QueryTab::query_ready(std::shared_ptr<Pgsql::Result> dbres, qint64 elapsedm
|
||||||
if (resultList.size() == 1)
|
if (resultList.size() == 1)
|
||||||
ui->tabWidget->setCurrentWidget(trw);
|
ui->tabWidget->setCurrentWidget(trw);
|
||||||
|
|
||||||
|
|
||||||
// ui->lblRowCount->setText(rowcount_str);
|
|
||||||
// resultModel.reset(new QueryResultModel(nullptr , dbres));
|
|
||||||
// ui->ResultView->setModel(resultModel.get());
|
|
||||||
// ui->tabWidget->setCurrentWidget(ui->dataTab);
|
|
||||||
//statusBar()->showMessage(tr("Query ready."));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (st == PGRES_COMMAND_OK) {
|
if (st == PGRES_COMMAND_OK) {
|
||||||
// statusBar()->showMessage(tr("Command OK."));
|
|
||||||
int tuples_affected = dbres->tuplesAffected();
|
int tuples_affected = dbres->tuplesAffected();
|
||||||
QString msg;
|
QString msg;
|
||||||
if (tuples_affected >= 0)
|
if (tuples_affected >= 0)
|
||||||
|
|
@ -548,18 +522,14 @@ void QueryTab::query_ready(std::shared_ptr<Pgsql::Result> dbres, qint64 elapsedm
|
||||||
else {
|
else {
|
||||||
m_stopwatch.stop();
|
m_stopwatch.stop();
|
||||||
addLog("query_ready with NO result");
|
addLog("query_ready with NO result");
|
||||||
// statusBar()->showMessage(tr("Query cancelled."));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryTab::clearResult()
|
void QueryTab::clearResult()
|
||||||
{
|
{
|
||||||
// ui->ResultView->setModel(nullptr);
|
|
||||||
// resultModel.reset();
|
|
||||||
for (auto e : resultList)
|
for (auto e : resultList)
|
||||||
delete e;
|
delete e;
|
||||||
resultList.clear();
|
resultList.clear();
|
||||||
// ui->lblRowCount->clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryTab::copyQueryAsCString()
|
void QueryTab::copyQueryAsCString()
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ namespace Ui {
|
||||||
class QueryTab;
|
class QueryTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class SqlSyntaxHighlighter;
|
class SqlSyntaxHighlighter;
|
||||||
|
|
@ -23,14 +25,29 @@ class ExplainRoot;
|
||||||
class QueryResultModel;
|
class QueryResultModel;
|
||||||
class QueryExplainModel;
|
class QueryExplainModel;
|
||||||
class PgTypeContainer;
|
class PgTypeContainer;
|
||||||
|
class OpenDatabase;
|
||||||
|
|
||||||
|
class QueryParamListController : public QObject {
|
||||||
class QueryTab : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QueryTab(MainWindow *win, QWidget *parent = 0);
|
QueryParamListController(QTableView *tv, OpenDatabase *opendb, QWidget *parent);
|
||||||
|
|
||||||
|
Pgsql::Params params() const;
|
||||||
|
public slots:
|
||||||
|
void on_addParam();
|
||||||
|
void on_removeParam();
|
||||||
|
private:
|
||||||
|
QTableView *paramTableView;
|
||||||
|
OpenDatabase *m_openDatabase;
|
||||||
|
ParamListModel m_paramList;
|
||||||
|
ParamTypeDelegate m_typeDelegate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class QueryTab : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QueryTab(MainWindow *win, QWidget *parent = nullptr);
|
||||||
~QueryTab();
|
~QueryTab();
|
||||||
|
|
||||||
void setConfig(const ConnectionConfig &config);
|
void setConfig(const ConnectionConfig &config);
|
||||||
|
|
@ -70,8 +87,8 @@ private:
|
||||||
SqlSyntaxHighlighter* highlighter;
|
SqlSyntaxHighlighter* highlighter;
|
||||||
ConnectionConfig m_config;
|
ConnectionConfig m_config;
|
||||||
StopWatch m_stopwatch;
|
StopWatch m_stopwatch;
|
||||||
ParamListModel m_paramList;
|
|
||||||
ParamTypeDelegate m_typeDelegate;
|
QueryParamListController *m_queryParamListController = nullptr;
|
||||||
|
|
||||||
QString m_fileName; ///< use setFileName function to set
|
QString m_fileName; ///< use setFileName function to set
|
||||||
bool m_queryTextChanged = false;
|
bool m_queryTextChanged = false;
|
||||||
|
|
|
||||||
|
|
@ -13,23 +13,100 @@
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="orientation">
|
<item>
|
||||||
<enum>Qt::Vertical</enum>
|
<widget class="QPlainTextEdit" name="queryEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QSplitter" name="splitter">
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_2">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="addButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QPlainTextEdit" name="queryEdit"/>
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QTableView" name="paramTableView">
|
<widget class="QTableView" name="paramTableView">
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
|
|
@ -131,7 +208,6 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ QVariant TypeSelectionItemModel::data(const QModelIndex &index, int role) const
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
int column = index.column();
|
int column = index.column();
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
if (column == 0) {
|
|
||||||
const PgType &tp = m_types->getByIdx(row);
|
const PgType &tp = m_types->getByIdx(row);
|
||||||
|
if (column == 0) {
|
||||||
result = tp.typname;
|
result = tp.typname;
|
||||||
|
|
||||||
// switch (row) {
|
// switch (row) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue