Skip to content

Commit 21adf13

Browse files
committed
only escape filters inside logical expressions and in lists
1 parent 1278df8 commit 21adf13

File tree

4 files changed

+30
-22
lines changed

4 files changed

+30
-22
lines changed

Postgrest/src/commonMain/kotlin/io/github/jan/supabase/postgrest/query/filter/FilterOperation.kt

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ package io.github.jan.supabase.postgrest.query.filter
1111
*/
1212
data class FilterOperation(val column: String, val operator: FilterOperator, val value: Any?)
1313

14-
fun FilterOperation.escapedValue(): String =
14+
fun FilterOperation.escapedValue(isInLogicalExpression: Boolean): String =
1515
when (operator) {
1616
FilterOperator.EQ,
1717
FilterOperator.NEQ,
@@ -23,8 +23,15 @@ fun FilterOperation.escapedValue(): String =
2323
FilterOperator.ILIKE,
2424
FilterOperator.MATCH,
2525
FilterOperator.IMATCH,
26-
FilterOperator.IS ->
27-
escapeValue(value)
26+
FilterOperator.IS,
27+
FilterOperator.FTS,
28+
FilterOperator.WFTS,
29+
FilterOperator.PHFTS,
30+
FilterOperator.PLFTS ->
31+
if (isInLogicalExpression)
32+
escapeValue(value)
33+
else
34+
value.toString()
2835
FilterOperator.IN ->
2936
if (value is List<*>) {
3037
encodeAsList(value)
@@ -35,9 +42,15 @@ fun FilterOperation.escapedValue(): String =
3542
FilterOperator.CD,
3643
FilterOperator.OV ->
3744
when (value) {
38-
is List<*> -> encodeOverlapAsArray(value)
39-
is Pair<*, *> -> encodeOverlapAsRange(value)
40-
else -> escapeValue(value)
45+
is List<*> ->
46+
encodeOverlapAsArray(value)
47+
is Pair<*, *> ->
48+
encodeOverlapAsRange(value)
49+
else ->
50+
if (isInLogicalExpression)
51+
escapeValue(value)
52+
else
53+
value.toString()
4154
}
4255
FilterOperator.SL,
4356
FilterOperator.SR,
@@ -49,35 +62,30 @@ fun FilterOperation.escapedValue(): String =
4962
is List<*> -> encodeAsRange(value)
5063
else -> escapeValue(value)
5164
}
52-
FilterOperator.FTS,
53-
FilterOperator.WFTS,
54-
FilterOperator.PHFTS,
55-
FilterOperator.PLFTS ->
56-
escapeValue(value) // Do these need special handling?
5765
}
5866

5967
private fun encodeAsList(values: List<*>): String =
6068
values.joinToString(",", prefix = "(", postfix = ")") { escapeValue(it) }
6169

6270
private fun encodeAsRange(range: Pair<*, *>): String =
63-
"(${escapeValue(range.first)},${escapeValue(range.second)})"
71+
"(${range.first},${range.second})"
6472

6573
private fun encodeAsRange(range: List<*>): String =
66-
"(${escapeValue(range[0])},${escapeValue(range[1])})"
74+
"(${range[0]},${range[1]})"
6775

6876
private fun encodeOverlapAsRange(range: Pair<*, *>): String =
69-
"[${escapeValue(range.first)},${escapeValue(range.second)}]"
77+
"[${range.first},${range.second}]"
7078

7179
private fun encodeOverlapAsArray(values: List<*>): String =
72-
values.joinToString(",", prefix = "{", postfix = "}") { escapeValue(it) }
80+
values.joinToString(",", prefix = "{", postfix = "}")
7381

7482
private val quotedCharacters = listOf(",", ".", ":", "(", ")")
7583

7684
internal fun escapeValue(value: Any?): String {
7785
val asString = value.toString()
7886
.replace("\\", "\\\\")
7987
.replace("\"", "\\\"")
80-
return if (value !is Number && quotedCharacters.any { asString.contains(it) }) {
88+
return if (quotedCharacters.any { asString.contains(it) }) {
8189
"\"$asString\""
8290
} else {
8391
asString

Postgrest/src/commonMain/kotlin/io/github/jan/supabase/postgrest/query/filter/PostgrestFilterBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class PostgrestFilterBuilder(
2828
*/
2929
fun filterNot(operation: FilterOperation) {
3030
val columnValue = params[operation.column] ?: emptyList()
31-
_params[operation.column] = columnValue + listOf("not.${operation.operator.identifier}.${operation.escapedValue()}")
31+
_params[operation.column] = columnValue + listOf("not.${operation.operator.identifier}.${operation.escapedValue(isInLogicalExpression)}")
3232
}
3333

3434
/**
@@ -43,7 +43,7 @@ class PostgrestFilterBuilder(
4343
*/
4444
fun filter(operation: FilterOperation) {
4545
val columnValue = params[operation.column] ?: emptyList()
46-
_params[operation.column] = columnValue + listOf("${operation.operator.identifier}.${operation.escapedValue()}")
46+
_params[operation.column] = columnValue + listOf("${operation.operator.identifier}.${operation.escapedValue(isInLogicalExpression)}")
4747
}
4848

4949
/**

Postgrest/src/commonTest/kotlin/PostgrestFilterBuilderTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ class PostgrestFilterBuilderTest {
3838
val filter = filterToString {
3939
eq("id", "2004-09-16T23:59:58.75")
4040
}
41-
assertEquals("id=eq.\"2004-09-16T23:59:58.75\"", filter)
41+
assertEquals("id=eq.2004-09-16T23:59:58.75", filter)
4242
}
4343

4444
@Test
4545
fun eq_quoted() {
4646
val filter = filterToString {
47-
eq("id", "Hello, \"World\"")
47+
isIn("id", listOf("Hello, \"World\"", "."))
4848
}
49-
assertEquals("id=eq.\"Hello,+\\\"World\\\"\"", filter)
49+
assertEquals("id=in.(\"Hello,+\\\"World\\\"\",\".\")", filter)
5050
}
5151

5252
@Test

Realtime/src/commonMain/kotlin/io/github/jan/supabase/realtime/PostgresChangeFilter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class PostgresChangeFilter(private val event: String, private val schema: String
3535
FilterOperator.LT,
3636
FilterOperator.LTE,
3737
FilterOperator.IN ->
38-
filter.escapedValue()
38+
filter.escapedValue(false)
3939
else -> throw UnsupportedOperationException("Unsupported filter operator: ${filter.operator}")
4040
}
4141
this.filter = "${filter.column}=${filter.operator.name.lowercase()}.$filterValue"

0 commit comments

Comments
 (0)