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

feat(web-analytics): HogQL sessions where extractor #20986

Merged
merged 20 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions posthog/hogql/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,17 @@ def resolve_constant_type(self, context: HogQLContext):
def resolve_database_field(self, context: HogQLContext):
if isinstance(self.type, FieldType):
return self.type.resolve_database_field(context)
if isinstance(self.type, PropertyType):
return self.type.field_type.resolve_database_field(context)
raise NotImplementedException("FieldAliasType.resolve_database_field not implemented")

def resolve_table_type(self, context: HogQLContext):
if isinstance(self.type, FieldType):
return self.type.table_type
if isinstance(self.type, PropertyType):
return self.type.field_type.table_type
raise NotImplementedException("FieldAliasType.resolve_table_type not implemented")


@dataclass(kw_only=True)
class BaseTableType(Type):
Expand Down Expand Up @@ -339,6 +348,9 @@ def get_child(self, name: str | int, context: HogQLContext) -> Type:
f'Can not access property "{name}" on field "{self.name}" of type: {type(database_field).__name__}'
)

def resolve_table_type(self, context: HogQLContext):
return self.table_type


@dataclass(kw_only=True)
class PropertyType(Type):
Expand Down
2 changes: 1 addition & 1 deletion posthog/hogql/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def accept(self, visitor):
return visit(self)
if hasattr(visitor, "visit_unknown"):
return visitor.visit_unknown(self)
raise NotImplementedException(f"Visitor has no method {method_name}")
raise NotImplementedException(f"{visitor.__class__.__name__} has no method {method_name}")


@dataclass(kw_only=True)
Expand Down
Empty file.
7 changes: 4 additions & 3 deletions posthog/hogql/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from posthog.hogql.base import Expr
from posthog.hogql.errors import HogQLException, NotImplementedException
from posthog.schema import HogQLQueryModifiers

if TYPE_CHECKING:
from posthog.hogql.context import HogQLContext
Expand Down Expand Up @@ -126,12 +125,14 @@ def resolve_table(self, context: "HogQLContext") -> Table:

class LazyTable(Table):
"""
A table that is replaced with a subquery returned from `lazy_select(requested_fields: Dict[name, chain], modifiers: HogQLQueryModifiers)`
A table that is replaced with a subquery returned from `lazy_select(requested_fields: Dict[name, chain], modifiers: HogQLQueryModifiers, node: SelectQuery)`
"""

model_config = ConfigDict(extra="forbid")

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers) -> Any:
def lazy_select(
self, requested_fields: Dict[str, List[str | int]], context: "HogQLContext", node: "SelectQuery"
) -> Any:
raise NotImplementedException("LazyTable.lazy_select not overridden")


Expand Down
Empty file.
3 changes: 1 addition & 2 deletions posthog/hogql/database/schema/cohort_people.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
FieldOrTable,
)
from posthog.hogql.database.schema.persons import join_with_persons_table
from posthog.schema import HogQLQueryModifiers

COHORT_PEOPLE_FIELDS = {
"person_id": StringDatabaseField(name="person_id"),
Expand Down Expand Up @@ -67,7 +66,7 @@ def to_printed_hogql(self):
class CohortPeople(LazyTable):
fields: Dict[str, FieldOrTable] = COHORT_PEOPLE_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return select_from_cohort_people_table(requested_fields)

def to_printed_clickhouse(self, context):
Expand Down
3 changes: 1 addition & 2 deletions posthog/hogql/database/schema/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
FieldOrTable,
)
from posthog.hogql.errors import HogQLException
from posthog.schema import HogQLQueryModifiers

GROUPS_TABLE_FIELDS = {
"index": IntegerDatabaseField(name="group_type_index"),
Expand Down Expand Up @@ -83,7 +82,7 @@ def to_printed_hogql(self):
class GroupsTable(LazyTable):
fields: Dict[str, FieldOrTable] = GROUPS_TABLE_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return select_from_groups_table(requested_fields)

def to_printed_clickhouse(self, context):
Expand Down
5 changes: 2 additions & 3 deletions posthog/hogql/database/schema/log_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
LazyTable,
FieldOrTable,
)
from posthog.schema import HogQLQueryModifiers

LOG_ENTRIES_FIELDS: Dict[str, FieldOrTable] = {
"team_id": IntegerDatabaseField(name="team_id"),
Expand All @@ -35,7 +34,7 @@ def to_printed_hogql(self):
class ReplayConsoleLogsLogEntriesTable(LazyTable):
fields: Dict[str, FieldOrTable] = LOG_ENTRIES_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
fields: List[ast.Expr] = [ast.Field(chain=["log_entries"] + chain) for name, chain in requested_fields.items()]

return ast.SelectQuery(
Expand All @@ -58,7 +57,7 @@ def to_printed_hogql(self):
class BatchExportLogEntriesTable(LazyTable):
fields: Dict[str, FieldOrTable] = LOG_ENTRIES_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
fields: List[ast.Expr] = [ast.Field(chain=["log_entries"] + chain) for name, chain in requested_fields.items()]

return ast.SelectQuery(
Expand Down
3 changes: 1 addition & 2 deletions posthog/hogql/database/schema/person_distinct_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
)
from posthog.hogql.database.schema.persons import join_with_persons_table
from posthog.hogql.errors import HogQLException
from posthog.schema import HogQLQueryModifiers

PERSON_DISTINCT_IDS_FIELDS = {
"team_id": IntegerDatabaseField(name="team_id"),
Expand Down Expand Up @@ -82,7 +81,7 @@ def to_printed_hogql(self):
class PersonDistinctIdsTable(LazyTable):
fields: Dict[str, FieldOrTable] = PERSON_DISTINCT_IDS_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return select_from_person_distinct_ids_table(requested_fields)

def to_printed_clickhouse(self, context):
Expand Down
4 changes: 2 additions & 2 deletions posthog/hogql/database/schema/persons.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ def to_printed_hogql(self):
class PersonsTable(LazyTable):
fields: Dict[str, FieldOrTable] = PERSONS_FIELDS

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
return select_from_persons_table(requested_fields, modifiers)
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return select_from_persons_table(requested_fields, context.modifiers)

def to_printed_clickhouse(self, context):
return "person"
Expand Down
3 changes: 1 addition & 2 deletions posthog/hogql/database/schema/persons_pdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
FieldOrTable,
)
from posthog.hogql.errors import HogQLException
from posthog.schema import HogQLQueryModifiers


# :NOTE: We already have person_distinct_ids.py, which most tables link to. This persons_pdi.py is a hack to
Expand Down Expand Up @@ -63,7 +62,7 @@ class PersonsPDITable(LazyTable):
"person_id": StringDatabaseField(name="person_id"),
}

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return persons_pdi_select(requested_fields)

def to_printed_clickhouse(self, context):
Expand Down
3 changes: 1 addition & 2 deletions posthog/hogql/database/schema/session_replay_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
PersonDistinctIdsTable,
join_with_person_distinct_ids_table,
)
from posthog.schema import HogQLQueryModifiers

RAW_ONLY_FIELDS = ["min_first_timestamp", "max_last_timestamp"]

Expand Down Expand Up @@ -115,7 +114,7 @@ class SessionReplayEventsTable(LazyTable):
"first_url": StringDatabaseField(name="first_url"),
}

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node):
return select_from_session_replay_events_table(requested_fields)

def to_printed_clickhouse(self, context):
Expand Down
15 changes: 11 additions & 4 deletions posthog/hogql/database/schema/sessions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Dict, List, cast

from posthog.hogql import ast
from posthog.hogql.context import HogQLContext
from posthog.hogql.database.models import (
StringDatabaseField,
DateTimeDatabaseField,
Expand All @@ -11,7 +13,7 @@
LazyTable,
)
from posthog.hogql.database.schema.channel_type import create_channel_type_expr
from posthog.schema import HogQLQueryModifiers
from posthog.hogql.database.schema.util.session_where_clause_extractor import SessionMinTimestampWhereClauseExtractor


SESSIONS_COMMON_FIELDS: Dict[str, FieldOrTable] = {
Expand Down Expand Up @@ -62,7 +64,9 @@ def avoid_asterisk_fields(self) -> List[str]:
]


def select_from_sessions_table(requested_fields: Dict[str, List[str | int]]):
def select_from_sessions_table(
requested_fields: Dict[str, List[str | int]], node: ast.SelectQuery, context: HogQLContext
):
from posthog.hogql import ast

table_name = "raw_sessions"
Expand Down Expand Up @@ -134,10 +138,13 @@ def select_from_sessions_table(requested_fields: Dict[str, List[str | int]]):
)
group_by_fields.append(ast.Field(chain=cast(list[str | int], [table_name]) + chain))

where = SessionMinTimestampWhereClauseExtractor(context).get_inner_where(node)

return ast.SelectQuery(
select=select_fields,
select_from=ast.JoinExpr(table=ast.Field(chain=[table_name])),
group_by=group_by_fields,
where=where,
)


Expand All @@ -148,8 +155,8 @@ class SessionsTable(LazyTable):
"channel_type": StringDatabaseField(name="channel_type"),
}

def lazy_select(self, requested_fields: Dict[str, List[str | int]], modifiers: HogQLQueryModifiers):
return select_from_sessions_table(requested_fields)
def lazy_select(self, requested_fields: Dict[str, List[str | int]], context, node: ast.SelectQuery):
return select_from_sessions_table(requested_fields, node, context)

def to_printed_clickhouse(self, context):
return "sessions"
Expand Down
Empty file.
Loading
Loading