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

Commit 078b00b

Browse files
trzysiektrzysiek
andauthored
[ecommerce] Fix failing panels when filtering an Array(String) (#1366)
I think code is clearer now, and of course some bugs also seem fixed. Before: 3 panels started failing when I choose any of the array filters, as I discovered and showed you on last learn. <img width="602" alt="Screenshot 2025-03-13 at 11 58 52" src="https://github.com/user-attachments/assets/2d2ba2a4-e118-4e45-b2fd-30c97ba32c1f" />. <img width="1611" alt="Screenshot 2025-03-13 at 11 58 57" src="https://github.com/user-attachments/assets/3481506d-ba31-4507-b8ce-766ead9b8f41" /> After: they all load again. <img width="1623" alt="Screenshot 2025-03-13 at 11 59 40" src="https://github.com/user-attachments/assets/ec5ebf13-3d65-420b-8545-d514d87296be" /> --------- Co-authored-by: trzysiek <[email protected]>
1 parent 56f69ae commit 078b00b

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

platform/clickhouse/type_adapter.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ func (c SchemaTypeAdapter) Convert(s string) (schema.QuesmaType, bool) {
4040
return schema.QuesmaTypeDate, true
4141
case "Point":
4242
return schema.QuesmaTypePoint, true
43-
case "Map(String, Nullable(String))", "Map(String, String)", "Map(LowCardinality(String), Nullable(String))", "Map(LowCardinality(String), String)":
43+
case "Map(String, Nullable(String))", "Map(String, String)", "Map(LowCardinality(String), Nullable(String))", "Map(LowCardinality(String), String)",
44+
"Map(String, Int)", "Map(LowCardinality(String), Int)", "Map(String, Nullable(Int))", "Map(LowCardinality(String), Nullable(Int))":
4445
return schema.QuesmaTypeMap, true
4546
default:
4647
return schema.QuesmaTypeUnknown, false

platform/frontend_connectors/schema_transformer.go

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,47 +1070,68 @@ func (s *SchemaCheckPass) applyMatchOperator(indexSchema schema.Schema, query *m
10701070

10711071
visitor.OverrideVisitInfix = func(b *model.BaseExprVisitor, e model.InfixExpr) interface{} {
10721072
var (
1073-
lhs = e.Left
1074-
rhs, okRight = e.Right.(model.LiteralExpr)
1075-
col, okLeft = e.Left.(model.ColumnRef)
1076-
lhsIsArrayAccess bool
1073+
lhs = e.Left
1074+
rhs, okRight = e.Right.(model.LiteralExpr)
1075+
lhsCol model.ColumnRef
1076+
okLeft, lhsIsArrayAccess, colIsAttributes bool
10771077
)
10781078

1079-
if !okLeft {
1080-
if arrayAccess, ok := lhs.(model.ArrayAccess); ok {
1081-
lhsIsArrayAccess = true
1082-
okLeft = true
1083-
col = arrayAccess.ColumnRef
1079+
// try to extract column from lhs
1080+
switch lhsT := lhs.(type) {
1081+
case model.ColumnRef:
1082+
lhsCol = lhsT
1083+
okLeft = true
1084+
case model.FunctionExpr:
1085+
if len(lhsT.Args) >= 1 {
1086+
if col, ok := lhsT.Args[0].(model.ColumnRef); ok {
1087+
lhsCol = col
1088+
okLeft = true
1089+
} else if f2, ok := lhsT.Args[0].(model.FunctionExpr); ok && len(f2.Args) == 1 {
1090+
if col, ok := f2.Args[0].(model.ColumnRef); ok {
1091+
lhsCol = col
1092+
okLeft = true
1093+
}
1094+
}
10841095
}
1096+
case model.ArrayAccess:
1097+
lhsIsArrayAccess = true
1098+
okLeft = true
1099+
lhsCol = lhsT.ColumnRef
1100+
default:
1101+
return model.NewInfixExpr(e.Left.Accept(b).(model.Expr), e.Op, e.Right.Accept(b).(model.Expr))
10851102
}
10861103

1087-
if okLeft && okRight && e.Op == model.MatchOperator {
1088-
if _, ok := rhs.Value.(string); !ok {
1104+
rhsValue, ok := rhs.Value.(string)
1105+
if !ok {
1106+
if e.Op == model.MatchOperator {
10891107
// only strings can be ILIKEd, everything else is a simple =
1090-
return model.NewInfixExpr(lhs, "=", rhs.Clone())
1108+
return model.NewInfixExpr(e.Left.Accept(b).(model.Expr), "=", e.Right.Accept(b).(model.Expr))
1109+
} else {
1110+
return model.NewInfixExpr(e.Left.Accept(b).(model.Expr), e.Op, e.Right.Accept(b).(model.Expr))
10911111
}
1112+
}
10921113

1093-
var colIsAttributes bool
1094-
field, found := indexSchema.ResolveFieldByInternalName(col.ColumnName)
1114+
if okLeft && okRight && e.Op == model.MatchOperator {
1115+
field, found := indexSchema.ResolveFieldByInternalName(lhsCol.ColumnName)
10951116
if !found {
10961117
// indexSchema won't find attributes columns, that's why this check
1097-
if clickhouse.IsColumnAttributes(col.ColumnName) {
1118+
if clickhouse.IsColumnAttributes(lhsCol.ColumnName) {
10981119
colIsAttributes = true
10991120
} else {
1100-
logger.Error().Msgf("Field %s not found in schema for table %s, should never happen here", col.ColumnName, query.TableName)
1121+
logger.Error().Msgf("Field %s not found in schema for table %s, should never happen here", lhsCol.ColumnName, query.TableName)
1122+
goto experimental
11011123
}
11021124
}
11031125

1104-
rhsValue := rhs.Value.(string) // checked above
11051126
rhsValue = strings.TrimPrefix(rhsValue, "'")
11061127
rhsValue = strings.TrimSuffix(rhsValue, "'")
11071128

11081129
ilike := func() model.Expr {
1109-
return model.NewInfixExpr(lhs, "ILIKE", model.NewLiteralWithEscapeType(rhsValue, rhs.EscapeType))
1130+
return model.NewInfixExpr(lhs, "ILIKE", rhs.Clone())
11101131
}
11111132
equal := func() model.Expr {
11121133
rhsValue = strings.Trim(rhsValue, "%")
1113-
return model.NewInfixExpr(lhs, "=", model.NewLiteral(rhsValue))
1134+
return model.NewInfixExpr(lhs, "=", rhs.Clone())
11141135
}
11151136

11161137
// handling case when e.Left is an array access
@@ -1132,6 +1153,7 @@ func (s *SchemaCheckPass) applyMatchOperator(indexSchema schema.Schema, query *m
11321153
}
11331154
}
11341155

1156+
experimental:
11351157
if s.isFieldMapSyntaxEnabled(query) {
11361158
// special case where left side is arrayElement,
11371159
// arrayElement comes from applyFieldEncoding function
@@ -1173,7 +1195,7 @@ func (s *SchemaCheckPass) applyMatchOperator(indexSchema schema.Schema, query *m
11731195
}
11741196

11751197
if e.Op == model.MatchOperator {
1176-
logger.Error().Msgf("Match operator is not supported for column %v", col)
1198+
logger.Error().Msgf("Match operator is not supported for column %v (expr: %v)", lhsCol, e)
11771199
}
11781200
return model.NewInfixExpr(e.Left.Accept(b).(model.Expr), e.Op, e.Right.Accept(b).(model.Expr))
11791201
}

platform/frontend_connectors/schema_transformer_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ func Test_applyMatchOperator(t *testing.T) {
12021202
WhereClause: model.NewInfixExpr(
12031203
model.NewColumnRef("count"),
12041204
"=",
1205-
model.NewLiteral("123"),
1205+
model.NewLiteral("'123'"),
12061206
),
12071207
},
12081208
},
@@ -1457,6 +1457,7 @@ func Test_checkAggOverUnsupportedType(t *testing.T) {
14571457

14581458
func Test_mapKeys(t *testing.T) {
14591459

1460+
// logger.InitSimpleLoggerForTestsWarnLevel()
14601461
indexConfig := map[string]config.IndexConfiguration{
14611462
"test": {EnableFieldMapSyntax: true},
14621463
"test2": {EnableFieldMapSyntax: false},
@@ -1509,8 +1510,8 @@ func Test_mapKeys(t *testing.T) {
15091510
Columns: []model.Expr{model.NewColumnRef("foo")},
15101511
WhereClause: model.NewInfixExpr(
15111512
model.NewFunction("arrayElement", model.NewColumnRef("foo"), model.NewLiteral("'bar'")),
1512-
"iLIKE",
1513-
model.NewLiteral("'%baz%'"),
1513+
"ILIKE",
1514+
model.NewLiteral("'baz'"),
15141515
),
15151516
},
15161517
},
@@ -1526,7 +1527,7 @@ func Test_mapKeys(t *testing.T) {
15261527
WhereClause: model.NewInfixExpr(
15271528
model.NewColumnRef("sizes.bar"),
15281529
model.MatchOperator,
1529-
model.NewLiteral("1"),
1530+
model.NewLiteralWithEscapeType("1", model.FullyEscaped),
15301531
),
15311532
},
15321533
},
@@ -1537,8 +1538,8 @@ func Test_mapKeys(t *testing.T) {
15371538
Columns: []model.Expr{model.NewColumnRef("foo")},
15381539
WhereClause: model.NewInfixExpr(
15391540
model.NewFunction("arrayElement", model.NewColumnRef("sizes"), model.NewLiteral("'bar'")),
1540-
"=",
1541-
model.NewLiteral("1"),
1541+
"ILIKE",
1542+
model.NewLiteralWithEscapeType("1", model.FullyEscaped),
15421543
),
15431544
},
15441545
},

0 commit comments

Comments
 (0)