sqlitesearch: improve tokenizer and fix sort handling
This commit is contained in:
parent
6bb53b8c31
commit
4a8d994358
@ -20,10 +20,11 @@ QVector<SqliteSearch::Token> SqliteSearch::tokenize(QString expression)
|
|||||||
}
|
}
|
||||||
// TODO: merge lonewords
|
// TODO: merge lonewords
|
||||||
QVector<SqliteSearch::Token> result;
|
QVector<SqliteSearch::Token> result;
|
||||||
QRegularExpression rx("((?<filtername>(\\.|\\w)+):(?<args>\\((?<innerargs>[^\\)]+)\\)|(\\w)+)|(?<boolean>AND|OR|!)|"
|
QRegularExpression rx("((?<filtername>(\\.|\\w)+):(?<args>\\((?<innerargs>[^\\)]+)\\)|([\\w,])+)|(?<boolean>AND|OR|"
|
||||||
"(?<bracket>\\(|\\))|(?<loneword>\\w+))");
|
"!)|(?<bracket>\\(|\\))|(?<loneword>\\w+))");
|
||||||
QRegularExpressionMatchIterator i = rx.globalMatch(expression);
|
QRegularExpressionMatchIterator i = rx.globalMatch(expression);
|
||||||
bool wasbool = true;
|
auto isSort = [](QString &key) { return key == "sort"; };
|
||||||
|
auto isBool = [](QString &key) { return key == "AND" || key == "OR" || key == "!"; };
|
||||||
while(i.hasNext())
|
while(i.hasNext())
|
||||||
{
|
{
|
||||||
QRegularExpressionMatch m = i.next();
|
QRegularExpressionMatch m = i.next();
|
||||||
@ -34,39 +35,34 @@ QVector<SqliteSearch::Token> SqliteSearch::tokenize(QString expression)
|
|||||||
|
|
||||||
if(boolean != "")
|
if(boolean != "")
|
||||||
{
|
{
|
||||||
wasbool = true;
|
|
||||||
result.append(Token(boolean));
|
result.append(Token(boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!result.empty())
|
||||||
|
{
|
||||||
|
QString &lastKey = result.last().key;
|
||||||
|
if(!isBool(lastKey) && !isSort(lastKey) && !isSort(filtername))
|
||||||
|
{
|
||||||
|
result.append(Token("AND"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(bracket != "")
|
if(bracket != "")
|
||||||
{
|
{
|
||||||
if(!wasbool)
|
if(bracket == "(")
|
||||||
{
|
{
|
||||||
if(bracket == "(")
|
result.append(Token("AND"));
|
||||||
{
|
|
||||||
result.append(Token("AND"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.append(Token(bracket));
|
result.append(Token(bracket));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(loneword != "")
|
if(loneword != "")
|
||||||
{
|
{
|
||||||
if(!wasbool)
|
|
||||||
{
|
|
||||||
result.append(Token("AND"));
|
|
||||||
}
|
|
||||||
wasbool = false;
|
|
||||||
result.append(Token("path.contains", loneword));
|
result.append(Token("path.contains", loneword));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(filtername != "")
|
if(filtername != "")
|
||||||
{
|
{
|
||||||
if(!wasbool)
|
|
||||||
{
|
|
||||||
result.append(Token("AND"));
|
|
||||||
}
|
|
||||||
wasbool = false;
|
|
||||||
QString value = m.captured("innerargs");
|
QString value = m.captured("innerargs");
|
||||||
if(value == "")
|
if(value == "")
|
||||||
{
|
{
|
||||||
@ -109,15 +105,27 @@ QString SqliteSearch::createSortSql(const SqliteSearch::Token &token)
|
|||||||
for(int i = 0; i < splitted_inner.length(); i++)
|
for(int i = 0; i < splitted_inner.length(); i++)
|
||||||
{
|
{
|
||||||
QStringList splitted = splitted_inner[i].split(" ");
|
QStringList splitted = splitted_inner[i].split(" ");
|
||||||
|
if(splitted.length() < 1 || splitted.length() > 2)
|
||||||
|
{
|
||||||
|
throw QSSGeneralException("sort specifier must have format [field] (asc|desc)");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString field = splitted[0];
|
||||||
|
field = fieldToColumn(field);
|
||||||
|
if(field == "")
|
||||||
|
{
|
||||||
|
throw QSSGeneralException("Unknown sort field supplied");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString order;
|
||||||
if(splitted.length() == 2)
|
if(splitted.length() == 2)
|
||||||
{
|
{
|
||||||
QString field = splitted[0];
|
order = splitted[1];
|
||||||
QString order = splitted[1];
|
if(order.compare("asc", Qt::CaseInsensitive) == 0)
|
||||||
if(order.compare("asc", Qt::CaseInsensitive))
|
|
||||||
{
|
{
|
||||||
order = "ASC";
|
order = "ASC";
|
||||||
}
|
}
|
||||||
else if(order.compare("desc", Qt::CaseInsensitive))
|
else if(order.compare("desc", Qt::CaseInsensitive) == 0)
|
||||||
{
|
{
|
||||||
order = "DESC";
|
order = "DESC";
|
||||||
}
|
}
|
||||||
@ -125,29 +133,19 @@ QString SqliteSearch::createSortSql(const SqliteSearch::Token &token)
|
|||||||
{
|
{
|
||||||
throw QSSGeneralException("Unknown order specifier: " + order);
|
throw QSSGeneralException("Unknown order specifier: " + order);
|
||||||
}
|
}
|
||||||
|
|
||||||
field = fieldToColumn(field);
|
|
||||||
if(field == "")
|
|
||||||
{
|
|
||||||
throw QSSGeneralException("Unknown field:" + field);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortsql += field + " " + order;
|
|
||||||
if(splitted_inner.length() - i > 1)
|
|
||||||
{
|
|
||||||
sortsql += ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(splitted.length() == 1)
|
|
||||||
{
|
|
||||||
sortsql += splitted[0] + " ASC ";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw QSSGeneralException("sort specifier must have format [field] (asc|desc)");
|
order = "ASC";
|
||||||
|
}
|
||||||
|
|
||||||
|
sortsql += field + " " + order;
|
||||||
|
if(splitted_inner.length() - i > 1)
|
||||||
|
{
|
||||||
|
sortsql += ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sortsql;
|
return " ORDER BY " + sortsql;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -221,6 +219,10 @@ QSqlQuery SqliteSearch::makeSqlQuery(const QVector<SqliteSearch::Token> &tokens)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString prepSql;
|
QString prepSql;
|
||||||
|
if(whereSql.isEmpty())
|
||||||
|
{
|
||||||
|
throw QSSGeneralException("Nothing to search for supplied");
|
||||||
|
}
|
||||||
if(isContentSearch)
|
if(isContentSearch)
|
||||||
{
|
{
|
||||||
if(sortSql.isEmpty())
|
if(sortSql.isEmpty())
|
||||||
@ -238,6 +240,11 @@ QSqlQuery SqliteSearch::makeSqlQuery(const QVector<SqliteSearch::Token> &tokens)
|
|||||||
{
|
{
|
||||||
sortSql = "ORDER BY file.mtime DESC";
|
sortSql = "ORDER BY file.mtime DESC";
|
||||||
}
|
}
|
||||||
|
if(sortSql.contains("content."))
|
||||||
|
{
|
||||||
|
throw QSSGeneralException("Cannot sort for content fields when not doing a content search");
|
||||||
|
}
|
||||||
|
|
||||||
prepSql = "SELECT file.path AS path, '0' as pages, file.mtime AS mtime, file.size AS size, file.filetype AS "
|
prepSql = "SELECT file.path AS path, '0' as pages, file.mtime AS mtime, file.size AS size, file.filetype AS "
|
||||||
"filetype FROM file WHERE 1=1 AND " +
|
"filetype FROM file WHERE 1=1 AND " +
|
||||||
whereSql + " " + sortSql;
|
whereSql + " " + sortSql;
|
||||||
|
Loading…
Reference in New Issue
Block a user