Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 1456ed5

Browse files
authored
Transform ILIKE '%%' to IS NOT NULL (#1417)
`ILIKE '%%'` has terrible performance, as it semantically means `is not null` we could transform that part of `WHERE` statement for decent speed up.
1 parent cac2672 commit 1456ed5

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

platform/frontend_connectors/schema_transformer.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,10 @@ func (s *SchemaCheckPass) applyMatchOperator(indexSchema schema.Schema, query *m
11341134
rhs.EscapeType = model.NormalNotEscaped
11351135
return equal()
11361136
default:
1137+
// ILIKE '%%' has terrible performance, but semantically means "is not null", hence this transformation
1138+
if rhsValue == "%%" {
1139+
return model.NewInfixExpr(lhs, "IS", model.NewLiteral("NOT NULL"))
1140+
}
11371141
return ilike()
11381142
}
11391143
}

platform/frontend_connectors/schema_transformer_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,33 @@ func Test_applyMatchOperator(t *testing.T) {
14301430
},
14311431
},
14321432
},
1433+
{
1434+
name: "match operator should change `ILIKE '%%'` TO `IS NOT NULL`",
1435+
query: &model.Query{
1436+
TableName: "test",
1437+
SelectCommand: model.SelectCommand{
1438+
FromClause: model.NewTableRef("test"),
1439+
Columns: []model.Expr{model.NewColumnRef("message")},
1440+
WhereClause: model.NewInfixExpr(
1441+
model.NewColumnRef("message"),
1442+
model.MatchOperator,
1443+
model.NewLiteralWithEscapeType("'%%'", model.NotEscapedLikeFull),
1444+
),
1445+
},
1446+
},
1447+
expected: &model.Query{
1448+
TableName: "test",
1449+
SelectCommand: model.SelectCommand{
1450+
FromClause: model.NewTableRef("test"),
1451+
Columns: []model.Expr{model.NewColumnRef("message")},
1452+
WhereClause: model.NewInfixExpr(
1453+
model.NewColumnRef("message"),
1454+
"IS",
1455+
model.NewLiteral("NOT NULL"),
1456+
),
1457+
},
1458+
},
1459+
},
14331460
}
14341461

14351462
for i, tt := range tests {

platform/testdata/pipeline_aggregation_requests.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,14 @@ var PipelineAggregationTests = []AggregationTestCase{}
176176
ExpectedSQLs: []string{
177177
`SELECT count() FROM ` + QuotedTableName + ` `,
178178
"SELECT toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000), count() " +
179-
"FROM " + QuotedTableName + ` WHERE "message" ILIKE '%' ` +
179+
"FROM " + QuotedTableName + ` WHERE "message" ILIKE '%' ` + // TODO: when uncommenting, investigate whether this shouldn't be "message" IS NOT NULL
180180
"GROUP BY (toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000)) " +
181181
"ORDER BY (toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000))",
182182
"SELECT toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000), count() " +
183-
"FROM " + QuotedTableName + ` WHERE "message" ILIKE '%' ` +
183+
"FROM " + QuotedTableName + ` WHERE "message" ILIKE '%' ` + // TODO: when uncommenting, investigate whether this shouldn't be "message" IS NOT NULL
184184
"GROUP BY (toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000)) " +
185185
"ORDER BY (toInt64(toUnixTimestamp64Milli(`@timestamp`)/3600000))",
186-
`SELECT count() FROM ` + QuotedTableName + ` WHERE "message" ILIKE '%' `,
186+
`SELECT count() FROM ` + QuotedTableName + ` WHERE "message" ILIKE '%' `, // TODO: when uncommenting, investigate whether this shouldn't be "message" IS NOT NULL
187187
},
188188
},
189189
/*

0 commit comments

Comments
 (0)