sqlite: Escape '%' and '_' in search queries. (#4487)

I picked '@' arbitrarily, it doesn't matter much.
I just don't like '\' because it needs to be escaped itself in the JS code,
which is annoying.
This commit is contained in:
Val Lorentz 2022-04-12 02:49:13 +02:00 committed by GitHub
parent e4840b4d75
commit 20ed3e6dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 2 deletions

View File

@ -205,9 +205,12 @@ class MessageStorage {
return Promise.resolve([]);
}
// Using the '@' character to escape '%' and '_' in patterns.
const escapedSearchTerm = query.searchTerm.replace(/([%_@])/g, "@$1");
let select =
'SELECT msg, type, time, network, channel FROM messages WHERE type = "message" AND json_extract(msg, "$.text") LIKE ?';
const params = [`%${query.searchTerm}%`];
'SELECT msg, type, time, network, channel FROM messages WHERE type = "message" AND json_extract(msg, "$.text") LIKE ? ESCAPE \'@\'';
const params = [`%${escapedSearchTerm}%`];
if (query.networkUuid) {
select += " AND network = ? ";

View File

@ -181,6 +181,68 @@ describe("SQLite Message Storage", function () {
}
});
it("should search messages with escaped wildcards", function () {
function assertResults(query, expected) {
return store
.search({
searchTerm: query,
networkUuid: "this-is-a-network-guid2",
})
.then((messages) => {
expect(messages.results.map((i) => i.text)).to.deep.equal(expected);
});
}
const originalMaxHistory = Helper.config.maxHistory;
try {
Helper.config.maxHistory = 3;
store.index(
{uuid: "this-is-a-network-guid2"},
{name: "#channel"},
new Msg({
time: 123456790,
text: `foo % bar _ baz`,
})
);
store.index(
{uuid: "this-is-a-network-guid2"},
{name: "#channel"},
new Msg({
time: 123456791,
text: `foo bar x baz`,
})
);
store.index(
{uuid: "this-is-a-network-guid2"},
{name: "#channel"},
new Msg({
time: 123456792,
text: `bar @ baz`,
})
);
return (
store
.getMessages({uuid: "this-is-a-network-guid2"}, {name: "#channel"})
// .getMessages() waits for store.index() transactions to commit
.then(() => assertResults("foo", ["foo % bar _ baz", "foo bar x baz"]))
.then(() => assertResults("%", ["foo % bar _ baz"]))
.then(() => assertResults("foo % bar ", ["foo % bar _ baz"]))
.then(() => assertResults("_", ["foo % bar _ baz"]))
.then(() => assertResults("bar _ baz", ["foo % bar _ baz"]))
.then(() => assertResults("%%", []))
.then(() => assertResults("@%", []))
.then(() => assertResults("@", ["bar @ baz"]))
);
} finally {
Helper.config.maxHistory = originalMaxHistory;
}
});
it("should close database", function (done) {
store.close((err) => {
expect(err).to.be.null;