From 9a5c644cc7baa2e4e91c26e64b3dd625b081d437 Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Mon, 20 Nov 2023 14:34:19 +0100 Subject: [PATCH] fix(hogql): Fix query for array of values (#18742) Fixes #18651 --- posthog/hogql/property.py | 47 +++++++++++++++++------------ posthog/hogql/test/test_property.py | 4 +-- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/posthog/hogql/property.py b/posthog/hogql/property.py index 9d619c23175b6..5695a0d0be2e5 100644 --- a/posthog/hogql/property.py +++ b/posthog/hogql/property.py @@ -126,26 +126,35 @@ def property_to_expr( elif len(value) == 1: value = value[0] else: - exprs = [ - property_to_expr( - Property( - type=property.type, - key=property.key, - operator=property.operator, - value=v, - ), - team, - scope, + if operator in [PropertyOperator.exact, PropertyOperator.is_not]: + op = ( + ast.CompareOperationOp.In + if operator == PropertyOperator.exact + else ast.CompareOperationOp.NotIn ) - for v in value - ] - if ( - operator == PropertyOperator.is_not - or operator == PropertyOperator.not_icontains - or operator == PropertyOperator.not_regex - ): - return ast.And(exprs=exprs) - return ast.Or(exprs=exprs) + + return ast.CompareOperation( + op=op, + left=ast.Field(chain=["properties", property.key]), + right=ast.Tuple(exprs=[ast.Constant(value=v) for v in value]), + ) + else: + exprs = [ + property_to_expr( + Property( + type=property.type, + key=property.key, + operator=property.operator, + value=v, + ), + team, + scope, + ) + for v in value + ] + if operator == PropertyOperator.not_icontains or operator == PropertyOperator.not_regex: + return ast.And(exprs=exprs) + return ast.Or(exprs=exprs) chain = ["person", "properties"] if property.type == "person" and scope != "person" else ["properties"] field = ast.Field(chain=chain + [property.key]) diff --git a/posthog/hogql/test/test_property.py b/posthog/hogql/test/test_property.py index c0ed528ea4da9..ecdfecee28671 100644 --- a/posthog/hogql/test/test_property.py +++ b/posthog/hogql/test/test_property.py @@ -163,7 +163,7 @@ def test_property_to_expr_event_list(self): # positive self.assertEqual( self._property_to_expr({"type": "event", "key": "a", "value": ["b", "c"], "operator": "exact"}), - self._parse_expr("properties.a = 'b' or properties.a = 'c'"), + self._parse_expr("properties.a IN ('b', 'c')"), ) self.assertEqual( self._property_to_expr( @@ -183,7 +183,7 @@ def test_property_to_expr_event_list(self): # negative self.assertEqual( self._property_to_expr({"type": "event", "key": "a", "value": ["b", "c"], "operator": "is_not"}), - self._parse_expr("properties.a != 'b' and properties.a != 'c'"), + self._parse_expr("properties.a NOT IN ('b', 'c')"), ) self.assertEqual( self._property_to_expr(