Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Version counting is based on semantic versioning (Major.Feature.Patch)
* Fix comics info export/import and covers package import/export error handling.
* Fix grid comic cells info height so the title doesn't overlap the other fields.
* Add funtion to open the library root location.
* Add a help dialog for the search engine. Use the drop down menu in the search field.
* Add quick search presets. Use the drop down menu in the search field.

### YACReaderLibraryServer
* Add the `repair-library` command to restore missing covers and rescan files that previously failed to be added.
Expand Down
4 changes: 4 additions & 0 deletions YACReaderLibrary/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ add_library(db_helper STATIC
db/reading_list.cpp
db/query_lexer.h
db/query_lexer.cpp
db/search_field_registry.h
db/search_field_registry.cpp
db/query_parser.h
db/query_parser.cpp
db/search_query.h
Expand Down Expand Up @@ -94,6 +96,8 @@ qt_add_executable(YACReaderLibrary WIN32
properties_dialog.cpp
options_dialog.h
options_dialog.cpp
search_syntax_dialog.h
search_syntax_dialog.cpp
export_library_dialog.h
export_library_dialog.cpp
import_library_dialog.h
Expand Down
45 changes: 13 additions & 32 deletions YACReaderLibrary/db/query_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,6 @@
#include <numeric>
#include <stdexcept>

const std::map<QueryParser::FieldType, std::vector<std::string>> QueryParser::fieldNames {
{ FieldType::numeric, { "numpages", "count", "arccount", "alternateCount", "rating" } },
{ FieldType::text, { "date", "number", "arcnumber", "title", "volume", "storyarc", "genere", "writer", "penciller", "inker", "colorist", "letterer", "coverartist", "publisher", "format", "agerating", "synopsis", "characters", "notes", "editor", "imprint", "teams", "locations", "series", "alternateSeries", "alternateNumber", "languageISO", "seriesGroup", "mainCharacterOrTeam", "review", "tags" } },
{ FieldType::boolean, { "color", "read", "edited", "hasBeenOpened" } },
{ FieldType::date, { "added", "lastTimeOpened" } },
{ FieldType::dateFolder, { "added", "updated" } },
{ FieldType::filename, { "filename" } },
{ FieldType::folder, { "folder" } },
{ FieldType::booleanFolder, { "completed", "finished" } },
{ FieldType::enumField, { "type" } },
{ FieldType::enumFieldFolder, { "foldertype" } }
};

std::string operatorToSQLOperator(const std::string &expOperator)
{
if (expOperator == ":" || expOperator == "=" || expOperator == "==") {
Expand All @@ -45,24 +32,24 @@ int QueryParser::TreeNode::buildSqlString(std::string &sqlString, int bindPositi
++bindPosition;
if (toLower(children[0].t) == "all") {
sqlString += "(";
for (const auto &field : fieldNames.at(FieldType::text)) {
for (const auto &field : searchFieldNames().at(FieldType::Text)) {
sqlString += "UPPER(ci." + field + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR ";
}
sqlString += "UPPER(c.filename) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ") OR ";
sqlString += "UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
} else if (isIn(fieldType(children[0].t), { FieldType::numeric, FieldType::date })) {
} else if (isIn(fieldType(children[0].t), { FieldType::Numeric, FieldType::Date })) {
sqlString += "ci." + children[0].t + " " + operatorToSQLOperator(expOperator) + " :bindPosition" + std::to_string(bindPosition) + " ";
} else if (isIn(fieldType(children[0].t), { FieldType::dateFolder })) {
} else if (isIn(fieldType(children[0].t), { FieldType::DateFolder })) {
sqlString += "f." + children[0].t + " " + operatorToSQLOperator(expOperator) + " :bindPosition" + std::to_string(bindPosition) + " ";
} else if (isIn(fieldType(children[0].t), { FieldType::boolean, FieldType::enumField })) {
} else if (isIn(fieldType(children[0].t), { FieldType::Boolean, FieldType::EnumField })) {
sqlString += "ci." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
} else if (fieldType(children[0].t) == FieldType::filename) {
} else if (fieldType(children[0].t) == FieldType::Filename) {
sqlString += "(UPPER(c." + children[0].t + ") LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
} else if (fieldType(children[0].t) == FieldType::folder) {
} else if (fieldType(children[0].t) == FieldType::Folder) {
sqlString += "(UPPER(f.name) LIKE UPPER(:bindPosition" + std::to_string(bindPosition) + ")) ";
} else if (fieldType(children[0].t) == FieldType::booleanFolder) {
} else if (fieldType(children[0].t) == FieldType::BooleanFolder) {
sqlString += "f." + children[0].t + " = :bindPosition" + std::to_string(bindPosition) + " ";
} else if (fieldType(children[0].t) == FieldType::enumFieldFolder) {
} else if (fieldType(children[0].t) == FieldType::EnumFieldFolder) {
if (children[0].t == "foldertype") {
sqlString += "f.type = :bindPosition" + std::to_string(bindPosition) + " ";
} else {
Expand Down Expand Up @@ -99,9 +86,9 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
{
if (t == "expression") {
std::string bind_string(":bindPosition" + std::to_string(++bindPosition));
if (isIn(fieldType(children[0].t), { FieldType::numeric })) {
if (isIn(fieldType(children[0].t), { FieldType::Numeric })) {
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
} else if (isIn(fieldType(children[0].t), { FieldType::boolean, FieldType::booleanFolder })) {
} else if (isIn(fieldType(children[0].t), { FieldType::Boolean, FieldType::BooleanFolder })) {
auto value = toLower(children[1].t);
if (value == "true") {
selectQuery.bindValue(QString::fromStdString(bind_string), 1);
Expand All @@ -110,7 +97,7 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
} else {
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(value));
}
} else if ((isIn(fieldType(children[0].t), { FieldType::enumField, FieldType::enumFieldFolder }))) {
} else if ((isIn(fieldType(children[0].t), { FieldType::EnumField, FieldType::EnumFieldFolder }))) {
auto enumType = children[0].t;
auto value = toLower(children[1].t);
if (enumType == "type" || enumType == "foldertype") {
Expand All @@ -128,7 +115,7 @@ int QueryParser::TreeNode::bindValues(QSqlQuery &selectQuery, int bindPosition)
} else {
selectQuery.bindValue(QString::fromStdString(bind_string), std::stoi(children[1].t));
}
} else if ((isIn(fieldType(children[0].t), { FieldType::date, FieldType::dateFolder }))) {
} else if ((isIn(fieldType(children[0].t), { FieldType::Date, FieldType::DateFolder }))) {
selectQuery.bindValue(QString::fromStdString(bind_string), QString::fromStdString(parseDate(children[1].t, expOperator)));
} else {
if (expOperator == "=" || expOperator == ":" || expOperator == "") {
Expand Down Expand Up @@ -230,13 +217,7 @@ bool QueryParser::isOperatorToken(Token::Type type)

QueryParser::FieldType QueryParser::fieldType(const std::string &str)
{
for (const auto &names : fieldNames) {
if (std::find(names.second.begin(), names.second.end(), toLower(str)) != names.second.end()) {
return names.first;
}
}

return FieldType::unknown;
return searchFieldType(str);
}

std::string QueryParser::join(const QStringList &strings, const std::string &delim)
Expand Down
15 changes: 2 additions & 13 deletions YACReaderLibrary/db/query_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define QUERY_PARSER_H

#include "query_lexer.h"
#include "search_field_registry.h"

#include <QSqlQuery>

Expand Down Expand Up @@ -84,17 +85,7 @@ class QueryParser

bool isOperatorToken(Token::Type type);

enum class FieldType { unknown,
numeric,
text,
boolean,
date,
dateFolder,
folder,
booleanFolder,
filename,
enumField,
enumFieldFolder };
using FieldType = SearchFieldType;
static FieldType fieldType(const std::string &str);

static std::string join(const QStringList &strings, const std::string &delim);
Expand All @@ -106,8 +97,6 @@ class QueryParser
TreeNode locationExpression();
TreeNode expression();
TreeNode baseToken();

static const std::map<FieldType, std::vector<std::string>> fieldNames;
};

#endif // QUERY_PARSER_H
Loading
Loading