Skip to content
This repository has been archived by the owner on May 10, 2018. It is now read-only.

Commit

Permalink
Fix performance when querying icons from database
Browse files Browse the repository at this point in the history
Make use of the index on icons column by using GLOB
instead of LIKE and handle the escaping ourselves.

Closes #1679
  • Loading branch information
nowrep committed Dec 20, 2016
1 parent 3a9e050 commit 8a2fc08
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 17 deletions.
5 changes: 2 additions & 3 deletions src/lib/other/iconchooser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ void IconChooser::searchIcon(const QString &string)
ui->iconList->clear();

QSqlQuery query;
query.prepare(QSL("SELECT icon FROM icons WHERE url LIKE ? ESCAPE ? LIMIT 20"));
query.bindValue(0, QString(QL1S("%%1%")).arg(QzTools::escapeSqlString(string)));
query.bindValue(1, QL1S("!"));
query.prepare(QSL("SELECT icon FROM icons WHERE url GLOB ? LIMIT 20"));
query.addBindValue(QString(QL1S("*%1*")).arg(QzTools::escapeSqlGlobString(string)));
query.exec();

while (query.next()) {
Expand Down
11 changes: 4 additions & 7 deletions src/lib/tools/iconprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,8 @@ QImage IconProvider::imageForUrl(const QUrl &url, bool allowEmpty)
}

QSqlQuery query;
query.prepare(QSL("SELECT icon FROM icons WHERE url LIKE ? ESCAPE ? LIMIT 1"));

query.addBindValue(QString("%1%").arg(QzTools::escapeSqlString(QString::fromUtf8(url.toEncoded(QUrl::RemoveFragment)))));
query.addBindValue(QL1S("!"));
query.prepare(QSL("SELECT icon FROM icons WHERE url GLOB ? LIMIT 1"));
query.addBindValue(QString("%1*").arg(QzTools::escapeSqlGlobString(QString::fromUtf8(url.toEncoded(QUrl::RemoveFragment)))));
SqlDatabase::instance()->exec(query);

if (query.next()) {
Expand Down Expand Up @@ -216,10 +214,9 @@ QImage IconProvider::imageForDomain(const QUrl &url, bool allowEmpty)
}

QSqlQuery query;
query.prepare(QSL("SELECT icon FROM icons WHERE url LIKE ? ESCAPE ? LIMIT 1"));
query.prepare(QSL("SELECT icon FROM icons WHERE url GLOB ? LIMIT 1"));

query.addBindValue(QString("%%1%").arg(QzTools::escapeSqlString(url.host())));
query.addBindValue(QL1S("!"));
query.addBindValue(QString("*%1*").arg(QzTools::escapeSqlGlobString(url.host())));
query.exec();

if (query.next()) {
Expand Down
12 changes: 6 additions & 6 deletions src/lib/tools/qztools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,13 @@ QString QzTools::fromPunycode(const QString &str)
return decoded.left(decoded.size() - 4);
}

QString QzTools::escapeSqlString(QString urlString)
QString QzTools::escapeSqlGlobString(QString urlString)
{
const static QString &escapeString = QL1S("!");
urlString.replace(escapeString, escapeString + escapeString);
urlString.replace(QL1S("_"), escapeString + QL1S("_"));
urlString.replace(QL1S("%"), escapeString + QL1S("%"));

urlString.replace(QL1C('['), QStringLiteral("[["));
urlString.replace(QL1C(']'), QStringLiteral("[]]"));
urlString.replace(QStringLiteral("[["), QStringLiteral("[[]"));
urlString.replace(QL1C('*'), QStringLiteral("[*]"));
urlString.replace(QL1C('?'), QStringLiteral("[?]"));
return urlString;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/tools/qztools.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class QUPZILLA_EXPORT QzTools
static QString samePartOfStrings(const QString &one, const QString &other);
static QString urlEncodeQueryString(const QUrl &url);
static QString fromPunycode(const QString &str);
static QString escapeSqlString(QString urlString);
static QString escapeSqlGlobString(QString urlString);

static QString ensureUniqueFilename(const QString &name, const QString &appendFormat = QString("(%1)"));
static QString getFileNameFromUrl(const QUrl &url);
Expand Down
27 changes: 27 additions & 0 deletions tests/autotests/qztoolstest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,33 @@ void QzToolsTest::splitCommandArguments()
QCOMPARE(QzTools::splitCommandArguments(command), result);
}

void QzToolsTest::escapeSqlGlobString_data()
{
QTest::addColumn<QString>("input");
QTest::addColumn<QString>("result");

QTest::newRow("NothingToEscape") << "http://test" << "http://test";
QTest::newRow("Escape *") << "http://test*/heh" << "http://test[*]/heh";
QTest::newRow("Escape **") << "http://test**/he*h" << "http://test[*][*]/he[*]h";
QTest::newRow("Escape ?") << "http://test?/heh" << "http://test[?]/heh";
QTest::newRow("Escape ??") << "http://t??est?/heh" << "http://t[?][?]est[?]/heh";
QTest::newRow("Escape [") << "http://[test/heh" << "http://[[]test/heh";
QTest::newRow("Escape [[") << "http://[[te[st/heh" << "http://[[][[]te[[]st/heh";
QTest::newRow("Escape ]") << "http://]test/heh" << "http://[]]test/heh";
QTest::newRow("Escape ]]") << "http://]]te]st/heh" << "http://[]][]]te[]]st/heh";
QTest::newRow("Escape []") << "http://[]test/heh" << "http://[[][]]test/heh";
QTest::newRow("Escape [][[]][]") << "http://t[][[]][]est/heh" << "http://t[[][]][[][[][]][]][[][]]est/heh";
QTest::newRow("Escape [?]][[*]") << "http://t[?]][[*]est/heh" << "http://t[[][?][]][]][[][[][*][]]est/heh";
}

void QzToolsTest::escapeSqlGlobString()
{
QFETCH(QString, input);
QFETCH(QString, result);

QCOMPARE(QzTools::escapeSqlGlobString(input), result);
}

class TempFile
{
QString name;
Expand Down
3 changes: 3 additions & 0 deletions tests/autotests/qztoolstest.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ private slots:
void splitCommandArguments_data();
void splitCommandArguments();

void escapeSqlGlobString_data();
void escapeSqlGlobString();

void ensureUniqueFilename();

private:
Expand Down

0 comments on commit 8a2fc08

Please sign in to comment.