Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(hogql): Allow chaining for lazy tables #28253

Merged
merged 10 commits into from
Feb 4, 2025
113 changes: 113 additions & 0 deletions posthog/hogql/test/test_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
from posthog.hogql.test.utils import pretty_dataclasses
from posthog.hogql.visitor import clone_expr
from posthog.test.base import BaseTest
from posthog.warehouse.models.credential import DataWarehouseCredential
from posthog.warehouse.models.join import DataWarehouseJoin
from posthog.warehouse.models.table import DataWarehouseTable


class TestResolver(BaseTest):
Expand Down Expand Up @@ -694,3 +697,113 @@ def test_property_access_with_tuples_zero_index_error(self):
):
node: ast.SelectQuery = self._select(query)
resolve_types(node, context, dialect="clickhouse")

def test_resolve_field_through_linear_joins(self):
credential = DataWarehouseCredential.objects.create(
team=self.team, access_key="_accesskey", access_secret="_secret"
)

DataWarehouseTable.objects.create(
team=self.team,
name="subscriptions",
columns={
"id": "String",
"customer_id": "String",
},
credential=credential,
url_pattern="",
)

DataWarehouseTable.objects.create(
team=self.team,
name="customers",
columns={
"id": "String",
"email": "String",
},
credential=credential,
url_pattern="",
)

DataWarehouseJoin.objects.create(
team=self.team,
source_table_name="subscriptions",
source_table_key="customer_id",
joining_table_name="customers",
joining_table_key="id",
field_name="customer",
)

DataWarehouseJoin.objects.create(
team=self.team,
source_table_name="customers",
source_table_key="email",
joining_table_name="events",
joining_table_key="person.properties.$email",
field_name="events",
)

self.database = create_hogql_database(self.team.pk)
self.context = HogQLContext(database=self.database, team_id=self.team.pk, enable_select_queries=True)

node = self._select("""
SELECT
customer.events.distinct_id
FROM subscriptions
""")
node = cast(ast.SelectQuery, resolve_types(node, self.context, dialect="clickhouse"))

def test_resolve_field_through_nested_joins(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gilbert09 I'd expect this test to fail but it passes for some reason. Do you see anything obviously wrong with it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parsing the HogQL will work fine - you need to actually run it against clickhouse for it to fail I believe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that was it:

db = create_hogql_database(team_id=self.team.pk)
context = HogQLContext(
team_id=self.team.pk,
enable_select_queries=True,
database=db,
)
print_ast(parse_select("SELECT events.distinct_id FROM subscriptions"), context, dialect="clickhouse")
Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this sufficient? print_ast won't run the query

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EDsCODE Yes: the test fails without 8e2dd3c and passes with.

I added an ExperimentTrendsQuery test too: 2d10c40

credential = DataWarehouseCredential.objects.create(
team=self.team, access_key="_accesskey", access_secret="_secret"
)

DataWarehouseTable.objects.create(
team=self.team,
name="subscriptions",
columns={
"id": "String",
"customer_id": "String",
},
credential=credential,
url_pattern="",
)

DataWarehouseTable.objects.create(
team=self.team,
name="customers",
columns={
"id": "String",
"email": "String",
},
credential=credential,
url_pattern="",
)

DataWarehouseJoin.objects.create(
team=self.team,
source_table_name="subscriptions",
source_table_key="customer_id",
joining_table_name="customers",
joining_table_key="id",
field_name="customer",
)

DataWarehouseJoin.objects.create(
team=self.team,
source_table_name="subscriptions",
source_table_key="customer.email",
joining_table_name="events",
joining_table_key="person.properties.$email",
field_name="events",
)

self.database = create_hogql_database(self.team.pk)
self.context = HogQLContext(database=self.database, team_id=self.team.pk, enable_select_queries=True)

node = self._select("""
SELECT
events.distinct_id
FROM subscriptions
""")
node = cast(ast.SelectQuery, resolve_types(node, self.context, dialect="clickhouse"))
Loading