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:
parent
e4840b4d75
commit
20ed3e6dc5
@ -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 = ? ";
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user