diff --git a/posthog/hogql/constants.py b/posthog/hogql/constants.py index 09c3158a89aaf..34cc0a094c053 100644 --- a/posthog/hogql/constants.py +++ b/posthog/hogql/constants.py @@ -107,7 +107,7 @@ "parseDateTime": ("parseDateTimeOrNull", 2, 2), "parseDateTimeBestEffort": ("parseDateTimeBestEffortOrNull", 2, 2), # dates and times - "toTimezone": ("toTimezone", 2, 2), + "toTimeZone": ("toTimeZone", 2, 2), "timeZoneOf": ("timeZoneOf", 1, 1), "timeZoneOffset": ("timeZoneOffset", 1, 1), "toYear": ("toYear", 1, 1), diff --git a/posthog/hogql/test/test_printer.py b/posthog/hogql/test/test_printer.py index 68da472ad368a..277489459b510 100644 --- a/posthog/hogql/test/test_printer.py +++ b/posthog/hogql/test/test_printer.py @@ -245,7 +245,7 @@ def test_expr_syntax_errors(self): def test_logic(self): self.assertEqual( self._expr("event or timestamp"), - "or(events.event, toTimezone(events.timestamp, %(hogql_val_0)s))", + "or(events.event, toTimeZone(events.timestamp, %(hogql_val_0)s))", ) self.assertEqual( self._expr("properties.bla and properties.bla2"), @@ -253,11 +253,11 @@ def test_logic(self): ) self.assertEqual( self._expr("event or timestamp or true or count()"), - "or(events.event, toTimezone(events.timestamp, %(hogql_val_0)s), true, count())", + "or(events.event, toTimeZone(events.timestamp, %(hogql_val_0)s), true, count())", ) self.assertEqual( self._expr("event or not timestamp"), - "or(events.event, not(toTimezone(events.timestamp, %(hogql_val_0)s)))", + "or(events.event, not(toTimeZone(events.timestamp, %(hogql_val_0)s)))", ) def test_comparisons(self): @@ -357,7 +357,7 @@ def test_select_order_by(self): ) self.assertEqual( self._select("select event from events order by event desc, timestamp"), - f"SELECT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) ORDER BY events.event DESC, toTimezone(events.timestamp, %(hogql_val_0)s) ASC LIMIT 65535", + f"SELECT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) ORDER BY events.event DESC, toTimeZone(events.timestamp, %(hogql_val_0)s) ASC LIMIT 65535", ) def test_select_limit(self): @@ -402,23 +402,23 @@ def test_select_limit_by(self): def test_select_group_by(self): self.assertEqual( self._select("select event from events group by event, timestamp"), - f"SELECT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimezone(events.timestamp, %(hogql_val_0)s) LIMIT 65535", + f"SELECT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimeZone(events.timestamp, %(hogql_val_0)s) LIMIT 65535", ) def test_select_distinct(self): self.assertEqual( self._select("select distinct event from events group by event, timestamp"), - f"SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimezone(events.timestamp, %(hogql_val_0)s) LIMIT 65535", + f"SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimeZone(events.timestamp, %(hogql_val_0)s) LIMIT 65535", ) def test_select_subquery(self): self.assertEqual( self._select("SELECT event from (select distinct event from events group by event, timestamp)"), - f"SELECT event FROM (SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimezone(events.timestamp, %(hogql_val_0)s)) LIMIT 65535", + f"SELECT event FROM (SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimeZone(events.timestamp, %(hogql_val_0)s)) LIMIT 65535", ) self.assertEqual( self._select("SELECT event from (select distinct event from events group by event, timestamp) e"), - f"SELECT e.event FROM (SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimezone(events.timestamp, %(hogql_val_0)s)) AS e LIMIT 65535", + f"SELECT e.event FROM (SELECT DISTINCT events.event FROM events WHERE equals(events.team_id, {self.team.pk}) GROUP BY events.event, toTimeZone(events.timestamp, %(hogql_val_0)s)) AS e LIMIT 65535", ) def test_select_union_all(self): @@ -515,7 +515,7 @@ def test_print_timezone(self): context = HogQLContext(team_id=self.team.pk, enable_select_queries=True) self.assertEqual( self._select("SELECT now(), toDateTime(timestamp), toDateTime('2020-02-02') FROM events", context), - f"SELECT now(%(hogql_val_0)s), toDateTimeOrNull(toTimezone(events.timestamp, %(hogql_val_1)s), %(hogql_val_2)s), toDateTimeOrNull(%(hogql_val_3)s, %(hogql_val_4)s) FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 65535", + f"SELECT now(%(hogql_val_0)s), toDateTimeOrNull(toTimeZone(events.timestamp, %(hogql_val_1)s), %(hogql_val_2)s), toDateTimeOrNull(%(hogql_val_3)s, %(hogql_val_4)s) FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 65535", ) self.assertEqual( context.values, @@ -534,7 +534,7 @@ def test_print_timezone_custom(self): context = HogQLContext(team_id=self.team.pk, enable_select_queries=True) self.assertEqual( self._select("SELECT now(), toDateTime(timestamp), toDateTime('2020-02-02') FROM events", context), - f"SELECT now(%(hogql_val_0)s), toDateTimeOrNull(toTimezone(events.timestamp, %(hogql_val_1)s), %(hogql_val_2)s), toDateTimeOrNull(%(hogql_val_3)s, %(hogql_val_4)s) FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 65535", + f"SELECT now(%(hogql_val_0)s), toDateTimeOrNull(toTimeZone(events.timestamp, %(hogql_val_1)s), %(hogql_val_2)s), toDateTimeOrNull(%(hogql_val_3)s, %(hogql_val_4)s) FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 65535", ) self.assertEqual( context.values, diff --git a/posthog/hogql/test/test_query.py b/posthog/hogql/test/test_query.py index 830be6cddeeeb..1e160e8cd95fe 100644 --- a/posthog/hogql/test/test_query.py +++ b/posthog/hogql/test/test_query.py @@ -130,7 +130,7 @@ def test_query_joins_simple(self): ) self.assertEqual( response.clickhouse, - f"SELECT e.event, toTimezone(e.timestamp, %(hogql_val_0)s), pdi.distinct_id, p.id, replaceRegexpAll(JSONExtractRaw(p.properties, %(hogql_val_1)s), '^\"|\"$', '') FROM events AS e LEFT JOIN person_distinct_id2 AS pdi ON equals(pdi.distinct_id, e.distinct_id) LEFT JOIN person AS p ON equals(p.id, pdi.person_id) WHERE and(equals(p.team_id, {self.team.id}), equals(pdi.team_id, {self.team.id}), equals(e.team_id, {self.team.id})) LIMIT 100 SETTINGS readonly=1, max_execution_time=60", + f"SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s), pdi.distinct_id, p.id, replaceRegexpAll(JSONExtractRaw(p.properties, %(hogql_val_1)s), '^\"|\"$', '') FROM events AS e LEFT JOIN person_distinct_id2 AS pdi ON equals(pdi.distinct_id, e.distinct_id) LEFT JOIN person AS p ON equals(p.id, pdi.person_id) WHERE and(equals(p.team_id, {self.team.id}), equals(pdi.team_id, {self.team.id}), equals(e.team_id, {self.team.id})) LIMIT 100 SETTINGS readonly=1, max_execution_time=60", ) self.assertEqual( response.hogql, @@ -161,7 +161,7 @@ def test_query_joins_pdi(self): self.assertEqual( response.clickhouse, - f"SELECT e.event, toTimezone(e.timestamp, %(hogql_val_0)s), pdi.person_id FROM events AS e INNER JOIN (SELECT person_distinct_id2.distinct_id, " + f"SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s), pdi.person_id FROM events AS e INNER JOIN (SELECT person_distinct_id2.distinct_id, " f"argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id FROM person_distinct_id2 WHERE " f"equals(person_distinct_id2.team_id, {self.team.id}) GROUP BY person_distinct_id2.distinct_id HAVING " f"equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS pdi ON " @@ -183,7 +183,7 @@ def test_query_joins_events_pdi(self): ) self.assertEqual( response.clickhouse, - f"SELECT events.event, toTimezone(events.timestamp, %(hogql_val_0)s), events__pdi.distinct_id, events__pdi.person_id FROM events INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS events__pdi ON equals(events.distinct_id, events__pdi.distinct_id) WHERE equals(events.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", + f"SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s), events__pdi.distinct_id, events__pdi.person_id FROM events INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS events__pdi ON equals(events.distinct_id, events__pdi.distinct_id) WHERE equals(events.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", ) self.assertEqual( response.hogql, @@ -207,7 +207,7 @@ def test_query_joins_events_e_pdi(self): ) self.assertEqual( response.clickhouse, - f"SELECT e.event, toTimezone(e.timestamp, %(hogql_val_0)s), e__pdi.distinct_id, e__pdi.person_id FROM events AS e INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) WHERE equals(e.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", + f"SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s), e__pdi.distinct_id, e__pdi.person_id FROM events AS e INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) WHERE equals(e.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", ) self.assertEqual(response.results[0][0], "random event") self.assertEqual(response.results[0][2], "bla") @@ -227,7 +227,7 @@ def test_query_joins_pdi_persons(self): ) self.assertEqual( response.clickhouse, - f"SELECT pdi.distinct_id, toTimezone(pdi__person.created_at, %(hogql_val_0)s) FROM person_distinct_id2 AS pdi INNER JOIN (SELECT " + f"SELECT pdi.distinct_id, toTimeZone(pdi__person.created_at, %(hogql_val_0)s) FROM person_distinct_id2 AS pdi INNER JOIN (SELECT " f"argMax(person.created_at, person.version) AS created_at, person.id FROM person WHERE " f"equals(person.team_id, {self.team.pk}) GROUP BY person.id HAVING equals(argMax(person.is_deleted, " f"person.version), 0)) AS pdi__person ON equals(pdi.person_id, pdi__person.id) WHERE " @@ -269,7 +269,7 @@ def test_query_joins_events_pdi_person(self): ) self.assertEqual( response.clickhouse, - f"SELECT events.event, toTimezone(events.timestamp, %(hogql_val_0)s), events__pdi.distinct_id, events__pdi__person.id FROM events " + f"SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s), events__pdi.distinct_id, events__pdi__person.id FROM events " f"INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, " f"person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) " f"GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, " @@ -298,7 +298,7 @@ def test_query_joins_events_pdi_person_properties(self): ) self.assertEqual( response.clickhouse, - f"SELECT events.event, toTimezone(events.timestamp, %(hogql_val_1)s), events__pdi.distinct_id, events__pdi__person.properties___sneaky_mail FROM events " + f"SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_1)s), events__pdi.distinct_id, events__pdi__person.properties___sneaky_mail FROM events " f"INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, " f"person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) " f"GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) " @@ -326,7 +326,7 @@ def test_query_joins_events_pdi_e_person_properties(self): ) self.assertEqual( response.clickhouse, - f"SELECT e.event, toTimezone(e.timestamp, %(hogql_val_1)s), e__pdi.distinct_id, e__pdi__person.properties___sneaky_mail FROM events AS e " + f"SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_1)s), e__pdi.distinct_id, e__pdi__person.properties___sneaky_mail FROM events AS e " f"INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, " f"person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) " f"GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, " @@ -355,7 +355,7 @@ def test_query_joins_events_person_properties(self): ) self.assertEqual( response.clickhouse, - f"SELECT e.event, toTimezone(e.timestamp, %(hogql_val_1)s), e__pdi__person.properties___sneaky_mail FROM events AS e INNER JOIN (SELECT " + f"SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_1)s), e__pdi__person.properties___sneaky_mail FROM events AS e INNER JOIN (SELECT " f"argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id " f"FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) GROUP BY person_distinct_id2.distinct_id " f"HAVING equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0)) AS e__pdi ON equals(e.distinct_id, " @@ -428,7 +428,7 @@ def test_query_select_person_with_joins_without_poe(self): ) self.assertEqual( response.clickhouse, - f"SELECT events.event, toTimezone(events.timestamp, %(hogql_val_1)s), events__pdi__person.id, events__pdi__person.properties___sneaky_mail " + f"SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_1)s), events__pdi__person.id, events__pdi__person.properties___sneaky_mail " f"FROM events INNER JOIN (SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, " f"person_distinct_id2.distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, {self.team.pk}) " f"GROUP BY person_distinct_id2.distinct_id HAVING equals(argMax(person_distinct_id2.is_deleted, " @@ -458,7 +458,7 @@ def test_query_select_person_with_poe_without_joins(self): ) self.assertEqual( response.clickhouse, - f"SELECT events.event, toTimezone(events.timestamp, %(hogql_val_0)s), events.person_id, replaceRegexpAll(JSONExtractRaw(events.person_properties, %(hogql_val_1)s), '^\"|\"$', '') FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", + f"SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s), events.person_id, replaceRegexpAll(JSONExtractRaw(events.person_properties, %(hogql_val_1)s), '^\"|\"$', '') FROM events WHERE equals(events.team_id, {self.team.pk}) LIMIT 10 SETTINGS readonly=1, max_execution_time=60", ) self.assertEqual( response.hogql, diff --git a/posthog/hogql/transforms/property_types.py b/posthog/hogql/transforms/property_types.py index 62e4e43bfbcd6..c3c3194803a52 100644 --- a/posthog/hogql/transforms/property_types.py +++ b/posthog/hogql/transforms/property_types.py @@ -82,7 +82,7 @@ def __init__(self, timezone: str, event_properties: Dict[str, str], person_prope def visit_field(self, node: ast.Field): if isinstance(node.type, ast.FieldType): if isinstance(node.type.resolve_database_field(), DateTimeDatabaseField): - return ast.Call(name="toTimezone", args=[node, ast.Constant(value=self.timezone)]) + return ast.Call(name="toTimeZone", args=[node, ast.Constant(value=self.timezone)]) type = node.type if isinstance(type, ast.PropertyType) and type.field_type.name == "properties" and len(type.chain) == 1: