Multiple search support and SQL optimization
This commit is contained in:
@@ -31,6 +31,7 @@ bool Database::init()
|
|||||||
m_database.exec("CREATE TABLE IF NOT EXISTS fits_headers (id INTEGER PRIMARY KEY AUTOINCREMENT, id_file INTEGER,"
|
m_database.exec("CREATE TABLE IF NOT EXISTS fits_headers (id INTEGER PRIMARY KEY AUTOINCREMENT, id_file INTEGER,"
|
||||||
"key VARCHAR(81), value VARCHAR(81), comment VARCHAR(81), FOREIGN KEY(id_file) REFERENCES fits_files(id) ON DELETE CASCADE)");
|
"key VARCHAR(81), value VARCHAR(81), comment VARCHAR(81), FOREIGN KEY(id_file) REFERENCES fits_files(id) ON DELETE CASCADE)");
|
||||||
m_database.exec("CREATE INDEX IF NOT EXISTS key_value ON fits_headers(key, value)");
|
m_database.exec("CREATE INDEX IF NOT EXISTS key_value ON fits_headers(key, value)");
|
||||||
|
m_database.exec("CREATE INDEX IF NOT EXISTS id_file ON fits_headers(id_file)");
|
||||||
QSqlError error = m_database.lastError();
|
QSqlError error = m_database.lastError();
|
||||||
|
|
||||||
if(error.type() == QSqlError::NoError)
|
if(error.type() == QSqlError::NoError)
|
||||||
|
|||||||
+59
-22
@@ -6,6 +6,7 @@
|
|||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QSqlError>
|
#include <QSqlError>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
const QStringList DEFAULT_COLUMNS = {"EXPTIME", "OBJECT", "RA", "DEC"};
|
const QStringList DEFAULT_COLUMNS = {"EXPTIME", "OBJECT", "RA", "DEC"};
|
||||||
|
|
||||||
@@ -57,8 +58,8 @@ void FITSFileModel::sort(int column, Qt::SortOrder order)
|
|||||||
m_sort.clear();
|
m_sort.clear();
|
||||||
else if(column <= m_columns.size())
|
else if(column <= m_columns.size())
|
||||||
{
|
{
|
||||||
if(column == 0)m_sort = " ORDER BY file ";
|
if(column == 0)m_sort = " ORDER BY f.file ";
|
||||||
else m_sort = QString(" ORDER BY \"%1\" ").arg(m_columns.at(column-1));
|
else m_sort = QString(" ORDER BY \"h%1_value\" ").arg(column-1);
|
||||||
m_sort += order == Qt::AscendingOrder ? "ASC" : "DESC";
|
m_sort += order == Qt::AscendingOrder ? "ASC" : "DESC";
|
||||||
prepareQuery();
|
prepareQuery();
|
||||||
}
|
}
|
||||||
@@ -70,31 +71,55 @@ void FITSFileModel::setColumns(const QStringList &columns)
|
|||||||
prepareQuery();
|
prepareQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FITSFileModel::setFilter(const QString &key, const QString &value)
|
void FITSFileModel::setFilter(const QStringList &key, const QStringList &value)
|
||||||
{
|
{
|
||||||
if(value.isEmpty())
|
if(value.isEmpty())
|
||||||
{
|
{
|
||||||
m_having.clear();
|
m_key.clear();
|
||||||
|
m_value.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(!m_columns.contains(key) && key != "file")m_columns.append(key);
|
m_key = key;
|
||||||
m_having = QString(" HAVING \"%1\" LIKE \"%2\"").arg(key).arg(value);
|
m_value = value;
|
||||||
}
|
}
|
||||||
prepareQuery();
|
prepareQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FITSFileModel::prepareQuery()
|
void FITSFileModel::prepareQuery()
|
||||||
{
|
{
|
||||||
QString sql = "SELECT file,";
|
QString cols;
|
||||||
|
QString join;
|
||||||
|
QString where;
|
||||||
|
QString sql = "SELECT f.file,";
|
||||||
|
for(int i=0; i<m_value.size(); i++)
|
||||||
|
{
|
||||||
|
if(m_key[i] == "file")
|
||||||
|
where = QString(" WHERE f.file LIKE '%1'").arg(m_value[i]);
|
||||||
|
else
|
||||||
|
join += QString(" JOIN fits_headers AS s%1 ON f.id=s%1.id_file AND s%1.key='%2' AND s%1.value LIKE '%3'").arg(i).arg(m_key[i]).arg(m_value[i]);
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
for(auto &column : m_columns)
|
for(auto &column : m_columns)
|
||||||
{
|
{
|
||||||
sql += QString("GROUP_CONCAT(CASE WHEN key=\"%1\" THEN value END) AS \"%1\",").arg(column);
|
cols += QString("GROUP_CONCAT(h%1.value) AS h%1_value,").arg(i);
|
||||||
|
join += QString(" LEFT JOIN fits_headers AS h%1 ON f.id=h%1.id_file AND h%1.key='%2'").arg(i).arg(column);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
sql.chop(1);
|
cols.chop(1);
|
||||||
sql += " FROM fits_files LEFT JOIN fits_headers ON fits_files.id=id_file GROUP BY fits_files.id" + m_having + m_sort;
|
sql += cols;
|
||||||
|
sql += " FROM fits_files AS f";
|
||||||
|
sql += join;
|
||||||
|
sql += where;
|
||||||
|
sql += " GROUP BY f.id" + m_sort;
|
||||||
setQuery(sql);
|
setQuery(sql);
|
||||||
qDebug() << sql;
|
setHeaderData(0, Qt::Horizontal, tr("File name"));
|
||||||
|
i = 1;
|
||||||
|
for(auto &column : m_columns)
|
||||||
|
{
|
||||||
|
setHeaderData(i++, Qt::Horizontal, column);
|
||||||
|
}
|
||||||
|
std::cout << sql.toStdString() << std::endl;
|
||||||
if(lastError().type() != QSqlError::NoError)
|
if(lastError().type() != QSqlError::NoError)
|
||||||
qDebug() << lastError();
|
qDebug() << lastError();
|
||||||
}
|
}
|
||||||
@@ -126,19 +151,20 @@ DataBaseView::DataBaseView(Database *database, QWidget *parent) : QWidget(parent
|
|||||||
hlayout->addWidget(selectColumnsButton);
|
hlayout->addWidget(selectColumnsButton);
|
||||||
connect(selectColumnsButton, &QPushButton::pressed, this, &DataBaseView::selectColumns);
|
connect(selectColumnsButton, &QPushButton::pressed, this, &DataBaseView::selectColumns);
|
||||||
|
|
||||||
m_filterKeyword = new QComboBox(this);
|
for(int i=0; i<3; i++)
|
||||||
m_filterKeyword->addItem("file");
|
{
|
||||||
m_filterKeyword->addItems(m_database->getFitsKeywords());
|
m_filterKeyword[i] = new QComboBox(this);
|
||||||
|
m_filterKeyword[i]->addItem("file");
|
||||||
m_search = new QLineEdit(this);
|
m_filterKeyword[i]->addItems(m_database->getFitsKeywords());
|
||||||
m_search->setPlaceholderText(tr("Text to search, you can % as wildcard"));
|
m_search[i] = new QLineEdit(this);
|
||||||
connect(m_search, &QLineEdit::returnPressed, this, &DataBaseView::applyFilter);
|
m_search[i]->setPlaceholderText(tr("Text to search, you can % as wildcard"));
|
||||||
|
connect(m_search[i], &QLineEdit::returnPressed, this, &DataBaseView::applyFilter);
|
||||||
|
hlayout->addWidget(m_filterKeyword[i]);
|
||||||
|
hlayout->addWidget(m_search[i]);
|
||||||
|
}
|
||||||
|
|
||||||
QPushButton *filterButton = new QPushButton(tr("Filter"), this);
|
QPushButton *filterButton = new QPushButton(tr("Filter"), this);
|
||||||
connect(filterButton, SIGNAL(pressed()), this, SLOT(applyFilter()));
|
connect(filterButton, SIGNAL(pressed()), this, SLOT(applyFilter()));
|
||||||
|
|
||||||
hlayout->addWidget(m_filterKeyword);
|
|
||||||
hlayout->addWidget(m_search);
|
|
||||||
hlayout->addWidget(filterButton);
|
hlayout->addWidget(filterButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +201,17 @@ void DataBaseView::itemActivated(const QModelIndex &index)
|
|||||||
|
|
||||||
void DataBaseView::applyFilter()
|
void DataBaseView::applyFilter()
|
||||||
{
|
{
|
||||||
m_model->setFilter(m_filterKeyword->currentText(), m_search->text());
|
QStringList keys;
|
||||||
|
QStringList values;
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
QString key = m_filterKeyword[i]->currentText();
|
||||||
|
if(!m_search[i]->text().isEmpty() && !keys.contains(key))
|
||||||
|
{
|
||||||
|
keys.append(key);
|
||||||
|
values.append(m_search[i]->text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_model->setFilter(keys, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -25,12 +25,13 @@ class FITSFileModel : public QSqlQueryModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QStringList m_columns;
|
QStringList m_columns;
|
||||||
QString m_sort;
|
QString m_sort;
|
||||||
QString m_having;
|
QStringList m_key;
|
||||||
|
QStringList m_value;
|
||||||
public:
|
public:
|
||||||
FITSFileModel(QObject *parent = nullptr);
|
FITSFileModel(QObject *parent = nullptr);
|
||||||
void sort(int column, Qt::SortOrder order);
|
void sort(int column, Qt::SortOrder order);
|
||||||
void setColumns(const QStringList &columns);
|
void setColumns(const QStringList &columns);
|
||||||
void setFilter(const QString &key, const QString &value);
|
void setFilter(const QStringList &key, const QStringList &value);
|
||||||
protected:
|
protected:
|
||||||
void prepareQuery();
|
void prepareQuery();
|
||||||
};
|
};
|
||||||
@@ -41,8 +42,8 @@ class DataBaseView : public QWidget
|
|||||||
Database *m_database;
|
Database *m_database;
|
||||||
QTableView *m_tableView;
|
QTableView *m_tableView;
|
||||||
FITSFileModel *m_model;
|
FITSFileModel *m_model;
|
||||||
QComboBox *m_filterKeyword;
|
QComboBox *m_filterKeyword[3];
|
||||||
QLineEdit *m_search;
|
QLineEdit *m_search[3];
|
||||||
public:
|
public:
|
||||||
explicit DataBaseView(Database *database, QWidget *parent = nullptr);
|
explicit DataBaseView(Database *database, QWidget *parent = nullptr);
|
||||||
~DataBaseView();
|
~DataBaseView();
|
||||||
|
|||||||
Reference in New Issue
Block a user