We have a piece of code where we try to match a pattern against the data in the database.
We use ServiceStack.OrmLite against our SQLite DB.
So for example, given the below records:
ColA ColB
----- ---------
ABC ABC_Long
GHI GHI_Long
GHIP GHIP_Long
We use a predicate as:
var result = db.Select(x => x.ColA.StartsWith("GHI_"));
Everything works fine until we have a search pattern that includes an SQL special character such as '%' or '_' so for example given the search pattern of "GHI_":
The expected row should be:
GHI GHI_Long
However we get:
GHI GHI_Long
GHIP GHIP_Long
Which is due to ORMLite not escaping the special character and generating the below SQL:
SELECT * FROM myTable WHERE UPPER(colA) LIKE 'GHI_%' OR UPPER(colB) LIKE 'GHI_%';
Instead of the correctly escaped version which should be:
SELECT * FROM myTable WHERE UPPER(colA) LIKE 'GHI\_%' OR UPPER(colB) LIKE 'GHI\_%' ESCAPE '\';
Can you think of a way to address this issue?
I've just added implicit support for escaping wildcards in this commit which will now escape wildcards in the typed expressions that make use of LIKE
, namely StartsWith
, EndsWith
and Contains
, e.g:
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<Poco>();
db.Insert(new Poco { Name = "a" });
db.Insert(new Poco { Name = "ab" });
db.Insert(new Poco { Name = "a_c" });
db.Insert(new Poco { Name = "a_cd" });
db.Insert(new Poco { Name = "abcd" });
db.Insert(new Poco { Name = "a%" });
db.Insert(new Poco { Name = "a%b" });
db.Insert(new Poco { Name = "a%bc" });
db.Insert(new Poco { Name = "a\\" });
db.Insert(new Poco { Name = "a\\b" });
db.Insert(new Poco { Name = "a\\bc" });
Assert.That(db.Count<Poco>(q => q.Name == "a_"), Is.EqualTo(0));
Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a_")), Is.EqualTo(2));
Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a%")), Is.EqualTo(3));
Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a_c")), Is.EqualTo(2));
Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a\\")), Is.EqualTo(3));
Assert.That(db.Count<Poco>(q => q.Name.StartsWith("a\\b")), Is.EqualTo(2));
}
This will be available in v4.0.19 which is now available on MyGet.