Skip to content

Commit

Permalink
Escaping to like expressions. (#1469) / Proper escaping of paired spe…
Browse files Browse the repository at this point in the history
…cial chars
  • Loading branch information
Tapac committed Jul 18, 2022
1 parent fd2aecf commit e926b0c
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,27 @@ data class LikePattern(
companion object {
fun ofLiteral(text: String, escapeChar: Char = '\\'): LikePattern {
val likePatternSpecialChars = currentDialect.likePatternSpecialChars
val nextExpectedPatternQueue = arrayListOf<Char>()
var nextCharToEscape: Char? = null
val escapedPattern = buildString {
text.forEach {
if (it in likePatternSpecialChars || it == escapeChar){
val shouldEscape = when (it) {
escapeChar -> true
in likePatternSpecialChars -> {
likePatternSpecialChars[it]?.let { nextChar ->
nextExpectedPatternQueue.add(nextChar)
nextCharToEscape = nextChar
}
true
}
nextCharToEscape -> {
nextExpectedPatternQueue.removeLast()
nextCharToEscape = nextExpectedPatternQueue.lastOrNull()
true
}
else -> false
}
if (shouldEscape){
append(escapeChar)
}
append(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ interface DatabaseDialect {

val supportsOrderByNullsFirstLast: Boolean get() = false

val likePatternSpecialChars: String get() = "%_"
val likePatternSpecialChars: Map<Char, Char?> get() = defaultLikePatternSpecialChars

/** Returns the name of the current database. */
fun getDatabase(): String
Expand Down Expand Up @@ -634,6 +634,10 @@ interface DatabaseDialect {
append(" CASCADE")
}
}

companion object {
private val defaultLikePatternSpecialChars = mapOf('%' to null, '_' to null)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,11 @@ open class SQLServerDialect : VendorDialect(dialectName, SQLServerDataTypeProvid
}

// https://docs.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15#arguments
override val likePatternSpecialChars: String = "%_[]"
override val likePatternSpecialChars = sqlServerLikePatternSpecialChars

companion object {
/** SQLServer dialect name */
const val dialectName: String = "sqlserver"
private val sqlServerLikePatternSpecialChars = mapOf('%' to null, '_' to null, '[' to ']')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class LikeTests : DatabaseTestsBase() {
withTables(t) {
// Lets assume there are no special chars outside this range
val escapeChar = '+'
val charRange = ('A'..'Z').toSet() + db.dialect.likePatternSpecialChars.toList()
val dialectSpecialChars = db.dialect.likePatternSpecialChars
val charRange = ('A'..'Z').toSet() + dialectSpecialChars.keys + dialectSpecialChars.values.filterNotNull()

charRange.forEach { chr ->
t.insert {
Expand All @@ -37,7 +38,7 @@ class LikeTests : DatabaseTestsBase() {
val specialChars = charRange.filter {
t.select { t.char like LikePattern("" + it, escapeChar = escapeChar) }.count() != 1L
}
assertEquals(db.dialect.likePatternSpecialChars.toSet(), specialChars.toSet())
assertEquals(specialChars.toSet(), dialectSpecialChars.keys)
}
}

Expand Down

0 comments on commit e926b0c

Please sign in to comment.