diff --git a/posthog/api/test/__snapshots__/test_query.ambr b/posthog/api/test/__snapshots__/test_query.ambr index d467a08e15b7a..38ee1f19a66b2 100644 --- a/posthog/api/test/__snapshots__/test_query.ambr +++ b/posthog/api/test/__snapshots__/test_query.ambr @@ -3,7 +3,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -20,7 +20,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -37,7 +37,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -54,7 +54,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -71,7 +71,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -88,7 +88,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -144,7 +144,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key FROM events WHERE equals(events.team_id, 2) ORDER BY toTimeZone(events.timestamp, 'UTC') ASC @@ -158,7 +158,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null') + nullIf(nullIf(events.mat_key, ''), 'null') AS key FROM events WHERE equals(events.team_id, 2) ORDER BY toTimeZone(events.timestamp, 'UTC') ASC @@ -204,7 +204,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -221,7 +221,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -238,7 +238,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -255,7 +255,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -272,7 +272,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -289,7 +289,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -306,7 +306,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -323,7 +323,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -340,7 +340,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) FROM events @@ -374,7 +374,7 @@ /* user_id:0 request:_snapshot_ */ SELECT events.event, events.distinct_id, - nullIf(nullIf(events.mat_key, ''), 'null'), + nullIf(nullIf(events.mat_key, ''), 'null') AS key, 'a%sd', concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(nullIf(nullIf(events.mat_key, ''), 'null')), '')) FROM events @@ -406,7 +406,7 @@ # name: TestQuery.test_property_filter_aggregations ' /* user_id:0 request:_snapshot_ */ - SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, count() FROM events WHERE and(equals(events.team_id, 2), less(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-10 12:14:05.000000', 6, 'UTC')), greater(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-09 12:14:00.000000', 6, 'UTC'))) @@ -421,7 +421,7 @@ # name: TestQuery.test_property_filter_aggregations.1 ' /* user_id:0 request:_snapshot_ */ - SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, count() FROM events WHERE and(equals(events.team_id, 2), less(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-10 12:14:05.000000', 6, 'UTC')), greater(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-09 12:14:00.000000', 6, 'UTC'))) @@ -437,7 +437,7 @@ # name: TestQuery.test_property_filter_aggregations_materialized ' /* user_id:0 request:_snapshot_ */ - SELECT nullIf(nullIf(events.mat_key, ''), 'null'), + SELECT nullIf(nullIf(events.mat_key, ''), 'null') AS key, count() FROM events WHERE and(equals(events.team_id, 2), less(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-10 12:14:05.000000', 6, 'UTC')), greater(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-09 12:14:00.000000', 6, 'UTC'))) @@ -452,7 +452,7 @@ # name: TestQuery.test_property_filter_aggregations_materialized.1 ' /* user_id:0 request:_snapshot_ */ - SELECT nullIf(nullIf(events.mat_key, ''), 'null'), + SELECT nullIf(nullIf(events.mat_key, ''), 'null') AS key, count() FROM events WHERE and(equals(events.team_id, 2), less(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-10 12:14:05.000000', 6, 'UTC')), greater(toTimeZone(events.timestamp, 'UTC'), toDateTime64('2020-01-09 12:14:00.000000', 6, 'UTC'))) @@ -483,7 +483,7 @@ # name: TestQuery.test_select_hogql_expressions ' /* user_id:0 request:_snapshot_ */ - SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', ''), + SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '') AS key, events.event, events.distinct_id, concat(ifNull(toString(events.event), ''), ' ', ifNull(toString(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, 'key'), ''), 'null'), '^"|"$', '')), '')) diff --git a/posthog/hogql/ast.py b/posthog/hogql/ast.py index 09cf32186ac30..19d8837d8efce 100644 --- a/posthog/hogql/ast.py +++ b/posthog/hogql/ast.py @@ -39,6 +39,14 @@ def get_child(self, name: str) -> Type: def has_child(self, name: str) -> bool: return self.type.has_child(name) + def resolve_constant_type(self): + return self.type.resolve_constant_type() + + def resolve_database_field(self): + if isinstance(self.type, FieldType): + return self.type.resolve_database_field() + raise NotImplementedException("FieldAliasType.resolve_database_field not implemented") + @dataclass(kw_only=True) class BaseTableType(Type): @@ -358,9 +366,11 @@ class LambdaArgumentType(Type): class Alias(Expr): alias: str expr: Expr - # Hidden aliases are created when HogQL invisibly renames fields, e.g "events.timestamp" gets turned into a - # "toDateTime(...) as timestamp". Unlike normal aliases, hidden aliases can be overriden. Visible aliases will throw - # if overridden, hidden ones will noop. Hidden aliases are shown if used as select columns in a subquery. + """ + Aliases are "hidden" if they're automatically created by HogQL when abstracting fields. + E.g. "events.timestamp" gets turned into a "toTimeZone(events.timestamp, 'UTC') AS timestamp". + Hidden aliases are printed only when printing the columns of a SELECT query in the ClickHouse dialect. + """ hidden: bool = False diff --git a/posthog/hogql/database/schema/test/test_event_sessions.py b/posthog/hogql/database/schema/test/test_event_sessions.py index 268180a773e6c..95752668f3a2f 100644 --- a/posthog/hogql/database/schema/test/test_event_sessions.py +++ b/posthog/hogql/database/schema/test/test_event_sessions.py @@ -38,7 +38,7 @@ def test_with_simple_equality_clause(self): assert len(compare_operators) == 1 assert compare_operators[0] == ast.CompareOperation( - left=ast.Field(chain=["event"]), + left=ast.Alias(alias="event", hidden=True, expr=ast.Field(chain=["event"])), op=ast.CompareOperationOp.Eq, right=ast.Constant(value="$pageview"), ) @@ -56,7 +56,7 @@ def test_with_timestamps(self): assert len(compare_operators) == 1 assert compare_operators[0] == ast.CompareOperation( - left=ast.Field(chain=["timestamp"]), + left=ast.Alias(alias="timestamp", hidden=True, expr=ast.Field(chain=["timestamp"])), op=ast.CompareOperationOp.Gt, right=ast.Constant(value="2023-01-01"), ) @@ -74,7 +74,7 @@ def test_with_alias_table(self): assert len(compare_operators) == 1 assert compare_operators[0] == ast.CompareOperation( - left=ast.Field(chain=["event"]), + left=ast.Alias(alias="event", hidden=True, expr=ast.Field(chain=["event"])), op=ast.CompareOperationOp.Eq, right=ast.Constant(value="$pageview"), ) @@ -92,12 +92,12 @@ def test_with_multiple_clauses(self): assert len(compare_operators) == 2 assert compare_operators[0] == ast.CompareOperation( - left=ast.Field(chain=["event"]), + left=ast.Alias(alias="event", hidden=True, expr=ast.Field(chain=["event"])), op=ast.CompareOperationOp.Eq, right=ast.Constant(value="$pageview"), ) assert compare_operators[1] == ast.CompareOperation( - left=ast.Field(chain=["timestamp"]), + left=ast.Alias(alias="timestamp", hidden=True, expr=ast.Field(chain=["timestamp"])), op=ast.CompareOperationOp.Gt, right=ast.Constant(value="2023-01-01"), ) @@ -117,7 +117,7 @@ def test_with_join(self): assert len(compare_operators) == 1 assert compare_operators[0] == ast.CompareOperation( - left=ast.Field(chain=["event"]), + left=ast.Alias(alias="event", hidden=True, expr=ast.Field(chain=["event"])), op=ast.CompareOperationOp.Eq, right=ast.Constant(value="$pageview"), ) diff --git a/posthog/hogql/printer.py b/posthog/hogql/printer.py index 17c8f4118f01a..ab588239b012d 100644 --- a/posthog/hogql/printer.py +++ b/posthog/hogql/printer.py @@ -229,11 +229,52 @@ def visit_select_query(self, node: ast.SelectQuery): else: where = ast.And(exprs=[extra_where, where]) else: - raise HogQLException(f"Invalid where of type {type(extra_where).__name__} returned by join_expr") + raise HogQLException( + f"Invalid where of type {type(extra_where).__name__} returned by join_expr", node=visited_join.where + ) next_join = next_join.next_join - columns = [self.visit(column) for column in node.select] if node.select else ["1"] + if node.select: + # Only for ClickHouse: Gather all visible aliases, and/or the last hidden alias for + # each unique alias name. Then make the last hidden aliases visible. + if self.dialect == "clickhouse": + visible_aliases = {} + for alias in reversed(node.select): + if isinstance(alias, ast.Alias): + if not visible_aliases.get(alias.alias, None) or not alias.hidden: + visible_aliases[alias.alias] = alias + + columns = [] + for column in node.select: + if isinstance(column, ast.Alias): + # It's either a visible alias, or the last hidden alias for this name. + if visible_aliases.get(column.alias) == column: + if column.hidden: + if ( + isinstance(column.expr, ast.Field) + and isinstance(column.expr.type, ast.FieldType) + and column.expr.type.name == column.alias + ): + # Hide the hidden alias only if it's a simple field, + # and we're using the same name for the field and the alias + # E.g. events.event AS event --> events.evnet. + column = column.expr + else: + # Make the hidden alias visible + column = cast(ast.Alias, clone_expr(column)) + column.hidden = False + else: + # Always print visible aliases. + pass + else: + # This is not the alias for this unique alias name. Skip it. + column = column.expr + columns.append(self.visit(column)) + else: + columns = [self.visit(column) for column in node.select] + else: + columns = ["1"] window = ( ", ".join( [f"{self._print_identifier(name)} AS ({self.visit(expr)})" for name, expr in node.window_exprs.items()] @@ -810,6 +851,7 @@ def visit_placeholder(self, node: ast.Placeholder): raise HogQLException(f"Placeholders, such as {{{node.field}}}, are not supported in this context") def visit_alias(self, node: ast.Alias): + # Skip hidden aliases completely. if node.hidden: return self.visit(node.expr) expr = node.expr @@ -1102,6 +1144,8 @@ def _is_nullable(self, node: ast.Expr) -> bool: return True elif isinstance(node.type, ast.FieldType): return node.type.is_nullable() + elif isinstance(node, ast.Alias): + return self._is_nullable(node.expr) # we don't know if it's nullable, so we assume it can be return True diff --git a/posthog/hogql/resolver.py b/posthog/hogql/resolver.py index b230225179fca..7e276948db540 100644 --- a/posthog/hogql/resolver.py +++ b/posthog/hogql/resolver.py @@ -118,42 +118,39 @@ def visit_select_query(self, node: ast.SelectQuery): new_node.array_join_list = [self.visit(expr) for expr in node.array_join_list] # Visit all the "SELECT a,b,c" columns. Mark each for export in "columns". - hidden_aliases = {} + select_nodes = [] for expr in node.select or []: new_expr = self.visit(expr) - - # if it's an asterisk, carry on in a subroutine if isinstance(new_expr.type, ast.AsteriskType): - self._expand_asterisk_columns(new_node, new_expr.type) - continue + columns = self._asterisk_columns(new_expr.type) + select_nodes.extend([self.visit(expr) for expr in columns]) + else: + select_nodes.append(new_expr) - # Any alias we can use to refer to this field? - alias = None + columns_with_visible_alias = {} + for new_expr in select_nodes: if isinstance(new_expr.type, ast.FieldAliasType): alias = new_expr.type.alias elif isinstance(new_expr.type, ast.FieldType): alias = new_expr.type.name elif isinstance(new_expr, ast.Alias): alias = new_expr.alias + else: + alias = None if alias: + # Make a reference of the first visible or last hidden expr for each unique alias name. if isinstance(new_expr, ast.Alias) and new_expr.hidden: - hidden_aliases[alias] = new_expr + if alias not in node_type.columns or not columns_with_visible_alias.get(alias, False): + node_type.columns[alias] = new_expr.type + columns_with_visible_alias[alias] = False else: node_type.columns[alias] = new_expr.type + columns_with_visible_alias[alias] = True # add the column to the new select query new_node.select.append(new_expr) - # this dict will contain the last used hidden alias with this name - for key, hidden_alias in hidden_aliases.items(): - # if no column took this alias, unhide it - if key not in node_type.columns: - node_type.columns[key] = hidden_alias.type - hidden_alias.hidden = False - if isinstance(hidden_alias.type, ast.FieldAliasType): - hidden_alias.type.hidden = False - # :TRICKY: Make sure to clone and visit _all_ SelectQuery nodes. new_node.where = self.visit(node.where) new_node.prewhere = self.visit(node.prewhere) @@ -177,15 +174,12 @@ def visit_select_query(self, node: ast.SelectQuery): return new_node - def _expand_asterisk_columns(self, select_query: ast.SelectQuery, asterisk: ast.AsteriskType): + def _asterisk_columns(self, asterisk: ast.AsteriskType) -> List[ast.Expr]: """Expand an asterisk. Mutates `select_query.select` and `select_query.type.columns` with the new fields""" if isinstance(asterisk.table_type, ast.BaseTableType): table = asterisk.table_type.resolve_database_table() database_fields = table.get_asterisk() - for key in database_fields.keys(): - type = ast.FieldType(name=key, table_type=asterisk.table_type) - select_query.select.append(ast.Field(chain=[key], type=type)) - select_query.type.columns[key] = type + return [ast.Field(chain=[key]) for key in database_fields.keys()] elif ( isinstance(asterisk.table_type, ast.SelectUnionQueryType) or isinstance(asterisk.table_type, ast.SelectQueryType) @@ -197,10 +191,7 @@ def _expand_asterisk_columns(self, select_query: ast.SelectQuery, asterisk: ast. if isinstance(select, ast.SelectUnionQueryType): select = select.types[0] if isinstance(select, ast.SelectQueryType): - for name in select.columns.keys(): - type = ast.FieldType(name=name, table_type=asterisk.table_type) - select_query.select.append(ast.Field(chain=[name], type=type)) - select_query.type.columns[name] = type + return [ast.Field(chain=[key]) for key in select.columns.keys()] else: raise ResolverException("Can't expand asterisk (*) on subquery") else: @@ -485,11 +476,12 @@ def visit_field(self, node: ast.Field): type=ast.FieldAliasType(alias=node.type.name, type=node.type), ) elif isinstance(node.type, ast.PropertyType): + property_alias = "__".join(node.type.chain) return ast.Alias( - alias=node.type.chain[-1], + alias=property_alias, expr=node, hidden=True, - type=ast.FieldAliasType(alias=node.type.chain[-1], type=node.type), + type=ast.FieldAliasType(alias=property_alias, type=node.type), ) return node @@ -497,40 +489,48 @@ def visit_field(self, node: ast.Field): def visit_array_access(self, node: ast.ArrayAccess): node = super().visit_array_access(node) + array = node.array + while isinstance(array, ast.Alias): + array = array.expr + if ( - isinstance(node.array, ast.Field) + isinstance(array, ast.Field) and isinstance(node.property, ast.Constant) and (isinstance(node.property.value, str) or isinstance(node.property.value, int)) and ( - (isinstance(node.array.type, ast.PropertyType)) + (isinstance(array.type, ast.PropertyType)) or ( - isinstance(node.array.type, ast.FieldType) + isinstance(array.type, ast.FieldType) and isinstance( - node.array.type.resolve_database_field(), + array.type.resolve_database_field(), StringJSONDatabaseField, ) ) ) ): - node.array.chain.append(node.property.value) - node.array.type = node.array.type.get_child(node.property.value) - return node.array + array.chain.append(node.property.value) + array.type = array.type.get_child(node.property.value) + return array return node def visit_tuple_access(self, node: ast.TupleAccess): node = super().visit_tuple_access(node) - if isinstance(node.tuple, ast.Field) and ( - (isinstance(node.tuple.type, ast.PropertyType)) + tuple = node.tuple + while isinstance(tuple, ast.Alias): + tuple = tuple.expr + + if isinstance(tuple, ast.Field) and ( + (isinstance(tuple.type, ast.PropertyType)) or ( - isinstance(node.tuple.type, ast.FieldType) - and isinstance(node.tuple.type.resolve_database_field(), StringJSONDatabaseField) + isinstance(tuple.type, ast.FieldType) + and isinstance(tuple.type.resolve_database_field(), StringJSONDatabaseField) ) ): - node.tuple.chain.append(node.index) - node.tuple.type = node.tuple.type.get_child(node.index) - return node.tuple + tuple.chain.append(node.index) + tuple.type = tuple.type.get_child(node.index) + return tuple return node @@ -593,6 +593,8 @@ def visit_compare_operation(self, node: ast.CompareOperation): return node def _is_events_table(self, node: ast.Expr) -> bool: + while isinstance(node, ast.Alias): + node = node.expr if isinstance(node, ast.Field) and isinstance(node.type, ast.FieldType): if isinstance(node.type.table_type, ast.TableAliasType): return isinstance(node.type.table_type.table_type.table, EventsTable) @@ -601,6 +603,8 @@ def _is_events_table(self, node: ast.Expr) -> bool: return False def _is_s3_cluster(self, node: ast.Expr) -> bool: + while isinstance(node, ast.Alias): + node = node.expr if ( isinstance(node, ast.SelectQuery) and node.select_from diff --git a/posthog/hogql/test/__snapshots__/test_printer.ambr b/posthog/hogql/test/__snapshots__/test_printer.ambr index d05f67f387345..c59af7ed313bd 100644 --- a/posthog/hogql/test/__snapshots__/test_printer.ambr +++ b/posthog/hogql/test/__snapshots__/test_printer.ambr @@ -3,17 +3,17 @@ SELECT groupArray(start_of_period) AS date, groupArray(counts) AS total, - status AS status + status FROM (SELECT if(equals(status, 'dormant'), negate(sum(counts)), negate(negate(sum(counts)))) AS counts, - start_of_period AS start_of_period, - status AS status + start_of_period, + status FROM (SELECT periods.start_of_period AS start_of_period, 0 AS counts, - status AS status + status FROM (SELECT minus(dateTrunc('day', assumeNotNull(toDateTime('2023-10-19 23:59:59'))), toIntervalDay(number)) AS start_of_period @@ -29,9 +29,9 @@ start_of_period ASC UNION ALL SELECT - start_of_period AS start_of_period, + start_of_period, count(DISTINCT person_id) AS counts, - status AS status + status FROM (SELECT events.person.id AS person_id, diff --git a/posthog/hogql/test/__snapshots__/test_query.ambr b/posthog/hogql/test/__snapshots__/test_query.ambr index e9c12b28402c6..d656bc1eec6b2 100644 --- a/posthog/hogql/test/__snapshots__/test_query.ambr +++ b/posthog/hogql/test/__snapshots__/test_query.ambr @@ -14,10 +14,34 @@ SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 ' --- +# name: TestQuery.test_hogql_query_filters_alias + ' + + SELECT e.event, e.distinct_id + FROM events AS e + WHERE and(equals(e.team_id, 420), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', ''), %(hogql_val_1)s), 0)) + LIMIT 100 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- +# name: TestQuery.test_hogql_union_all_limits + ' + + SELECT events.event + FROM events + WHERE equals(events.team_id, 420) + LIMIT 100 UNION ALL + SELECT events.event + FROM events + WHERE equals(events.team_id, 420) + LIMIT 100 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- # name: TestQuery.test_query ' - SELECT count(), events.event AS event + SELECT count(), events.event FROM events WHERE and(equals(events.team_id, 420), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', ''), %(hogql_val_1)s), 0)) GROUP BY events.event @@ -30,10 +54,10 @@ SELECT DISTINCT persons.properties___sneaky_mail AS sneaky_mail FROM ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS properties___random_uuid + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS properties___random_uuid FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -44,10 +68,25 @@ SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 ' --- +# name: TestQuery.test_query_joins_events_e_pdi + ' + + SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s) AS timestamp, 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 AS distinct_id + FROM person_distinct_id2 + WHERE equals(person_distinct_id2.team_id, 420) + GROUP BY person_distinct_id2.distinct_id + HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) + WHERE equals(e.team_id, 420) + LIMIT 10 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- # name: TestQuery.test_query_joins_events_pdi ' - SELECT events.event AS event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, events__pdi.distinct_id AS distinct_id, events__pdi.person_id AS person_id + SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, 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 AS distinct_id FROM person_distinct_id2 @@ -62,17 +101,17 @@ # name: TestQuery.test_query_joins_events_pdi_e_person_properties ' - SELECT e.event AS event, toTimeZone(e.timestamp, %(hogql_val_1)s) AS timestamp, e__pdi.distinct_id AS distinct_id, e__pdi__person.properties___sneaky_mail AS sneaky_mail + SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_1)s) AS timestamp, e__pdi.distinct_id, e__pdi__person.properties___sneaky_mail AS sneaky_mail 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 AS distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) INNER JOIN ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -86,7 +125,7 @@ # name: TestQuery.test_query_joins_events_pdi_person ' - SELECT events.event AS event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, events__pdi.distinct_id AS distinct_id, events__pdi__person.id AS id + SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, 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 AS distinct_id FROM person_distinct_id2 @@ -107,17 +146,17 @@ # name: TestQuery.test_query_joins_events_pdi_person_properties ' - SELECT events.event AS event, toTimeZone(events.timestamp, %(hogql_val_1)s) AS timestamp, events__pdi.distinct_id AS distinct_id, events__pdi__person.properties___sneaky_mail AS sneaky_mail + SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_1)s) AS timestamp, events__pdi.distinct_id, events__pdi__person.properties___sneaky_mail AS sneaky_mail FROM events INNER JOIN ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS events__pdi ON equals(events.distinct_id, events__pdi.distinct_id) INNER JOIN ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -131,17 +170,17 @@ # name: TestQuery.test_query_joins_events_person_properties ' - SELECT e.event AS event, toTimeZone(e.timestamp, %(hogql_val_1)s) AS timestamp, e__pdi__person.properties___sneaky_mail AS sneaky_mail + SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_1)s) AS timestamp, e__pdi__person.properties___sneaky_mail AS sneaky_mail 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 AS distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS e__pdi ON equals(e.distinct_id, e__pdi.distinct_id) INNER JOIN ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -162,10 +201,10 @@ WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS s__pdi ON equals(s.distinct_id, s__pdi.distinct_id) INNER JOIN ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -180,9 +219,9 @@ # name: TestQuery.test_query_joins_pdi ' - SELECT e.event AS event, toTimeZone(e.timestamp, %(hogql_val_0)s) AS timestamp, pdi.person_id AS person_id + SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s) AS timestamp, pdi.person_id FROM events AS e INNER JOIN ( - SELECT person_distinct_id2.distinct_id AS distinct_id, argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id + SELECT person_distinct_id2.distinct_id, argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id @@ -192,10 +231,45 @@ SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 ' --- +# name: TestQuery.test_query_joins_pdi_person_properties + ' + + SELECT pdi.distinct_id, pdi__person.properties___sneaky_mail AS sneaky_mail + FROM person_distinct_id2 AS pdi INNER JOIN ( + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + FROM person + WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( + SELECT person.id, max(person.version) AS version + FROM person + WHERE equals(person.team_id, 420) + GROUP BY person.id + HAVING ifNull(equals(argMax(person.is_deleted, person.version), 0), 0))), 0)) + SETTINGS optimize_aggregation_in_order=1) AS pdi__person ON equals(pdi.person_id, pdi__person.id) + WHERE equals(pdi.team_id, 420) + LIMIT 10 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- +# name: TestQuery.test_query_joins_pdi_persons + ' + + SELECT pdi.distinct_id, toTimeZone(pdi__person.created_at, %(hogql_val_0)s) AS created_at + FROM person_distinct_id2 AS pdi INNER JOIN ( + SELECT argMax(person.created_at, person.version) AS created_at, person.id AS id + FROM person + WHERE equals(person.team_id, 420) + GROUP BY person.id + HAVING ifNull(equals(argMax(person.is_deleted, person.version), 0), 0) + SETTINGS optimize_aggregation_in_order=1) AS pdi__person ON equals(pdi.person_id, pdi__person.id) + WHERE equals(pdi.team_id, 420) + LIMIT 10 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- # name: TestQuery.test_query_joins_simple ' - SELECT e.event AS event, toTimeZone(e.timestamp, %(hogql_val_0)s) AS timestamp, pdi.distinct_id AS distinct_id, p.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(p.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS sneaky_mail + SELECT e.event, toTimeZone(e.timestamp, %(hogql_val_0)s) AS timestamp, pdi.distinct_id, p.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(p.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS sneaky_mail 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, 420), equals(pdi.team_id, 420), equals(e.team_id, 420)) LIMIT 100 @@ -205,7 +279,7 @@ # name: TestQuery.test_query_person_distinct_ids ' - SELECT DISTINCT person_distinct_ids.person_id AS person_id, person_distinct_ids.distinct_id AS distinct_id + SELECT DISTINCT person_distinct_ids.person_id, person_distinct_ids.distinct_id FROM ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 @@ -219,17 +293,17 @@ # name: TestQuery.test_query_select_person_with_joins_without_poe ' - SELECT events.event AS event, toTimeZone(events.timestamp, %(hogql_val_1)s) AS timestamp, events__pdi__person.id AS id, events__pdi__person.properties___sneaky_mail AS sneaky_mail + SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_1)s) AS timestamp, events__pdi__person.id, events__pdi__person.properties___sneaky_mail AS sneaky_mail FROM events INNER JOIN ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 WHERE equals(person_distinct_id2.team_id, 420) GROUP BY person_distinct_id2.distinct_id HAVING ifNull(equals(argMax(person_distinct_id2.is_deleted, person_distinct_id2.version), 0), 0)) AS events__pdi ON equals(events.distinct_id, events__pdi.distinct_id) INNER JOIN ( - SELECT person.id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail + SELECT person.id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS properties___sneaky_mail FROM person WHERE and(equals(person.team_id, 420), ifNull(in(tuple(person.id, person.version), ( - SELECT person.id AS id, max(person.version) AS version + SELECT person.id, max(person.version) AS version FROM person WHERE equals(person.team_id, 420) GROUP BY person.id @@ -243,7 +317,7 @@ # name: TestQuery.test_query_select_person_with_poe_without_joins ' - SELECT events.event AS event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, events.person_id AS id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.person_properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS sneaky_mail + SELECT events.event, toTimeZone(events.timestamp, %(hogql_val_0)s) AS timestamp, events.person_id, replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.person_properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', '') AS sneaky_mail FROM events WHERE equals(events.team_id, 420) LIMIT 10 @@ -264,9 +338,9 @@ # name: TestQuery.test_subquery ' - SELECT count AS count, event AS event + SELECT count, event FROM ( - SELECT count() AS count, events.event AS event + SELECT count() AS count, events.event FROM events WHERE and(equals(events.team_id, 420), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', ''), %(hogql_val_1)s), 0)) GROUP BY events.event) @@ -278,9 +352,9 @@ # name: TestQuery.test_subquery_alias ' - SELECT c.count AS count, c.event AS event + SELECT c.count, c.event FROM ( - SELECT count(*) AS count, events.event AS event + SELECT count(*) AS count, events.event FROM events WHERE and(equals(events.team_id, 420), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', ''), %(hogql_val_1)s), 0)) GROUP BY events.event) AS c @@ -292,9 +366,9 @@ # name: TestQuery.test_tuple_access ' - SELECT col_a AS col_a, arrayZip((sumMap((g).1, (g).2) AS x).1, x.2) AS r + SELECT col_a, arrayZip((sumMap((g).1, (g).2) AS x).1, x.2) AS r FROM ( - SELECT col_a AS col_a, groupArray(tuple(col_b, col_c)) AS g + SELECT col_a, groupArray(tuple(col_b, col_c)) AS g FROM ( SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS col_a, events.event AS col_b, count() AS col_c FROM events @@ -306,3 +380,43 @@ SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 ' --- +# name: TestQuery.test_with_pivot_table_1_level + ' + + SELECT PIVOT_FUNCTION_2.col_a, PIVOT_FUNCTION_2.r + FROM ( + SELECT PIVOT_FUNCTION_1.col_a, arrayZip((sumMap((PIVOT_FUNCTION_1.g).1, (PIVOT_FUNCTION_1.g).2) AS x).1, x.2) AS r + FROM ( + SELECT PIVOT_TABLE_COL_ABC.col_a, groupArray(tuple(PIVOT_TABLE_COL_ABC.col_b, PIVOT_TABLE_COL_ABC.col_c)) AS g + FROM ( + SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS col_a, events.event AS col_b, count() AS col_c + FROM events + WHERE equals(events.team_id, 420) + GROUP BY replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', ''), events.event) AS PIVOT_TABLE_COL_ABC + GROUP BY PIVOT_TABLE_COL_ABC.col_a) AS PIVOT_FUNCTION_1 + GROUP BY PIVOT_FUNCTION_1.col_a) AS PIVOT_FUNCTION_2 ORDER BY PIVOT_FUNCTION_2.col_a ASC + LIMIT 100 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- +# name: TestQuery.test_with_pivot_table_2_levels + ' + + SELECT final.col_a, final.r + FROM ( + SELECT PIVOT_FUNCTION_2.col_a, PIVOT_FUNCTION_2.r + FROM ( + SELECT PIVOT_FUNCTION_1.col_a, arrayZip((sumMap((PIVOT_FUNCTION_1.g).1, (PIVOT_FUNCTION_1.g).2) AS x).1, x.2) AS r + FROM ( + SELECT PIVOT_TABLE_COL_ABC.col_a, groupArray(tuple(PIVOT_TABLE_COL_ABC.col_b, PIVOT_TABLE_COL_ABC.col_c)) AS g + FROM ( + SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', '') AS col_a, events.event AS col_b, count() AS col_c + FROM events + WHERE equals(events.team_id, 420) + GROUP BY replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', ''), events.event) AS PIVOT_TABLE_COL_ABC + GROUP BY PIVOT_TABLE_COL_ABC.col_a) AS PIVOT_FUNCTION_1 + GROUP BY PIVOT_FUNCTION_1.col_a) AS PIVOT_FUNCTION_2) AS final ORDER BY final.col_a ASC + LIMIT 100 + SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1 + ' +--- diff --git a/posthog/hogql/test/__snapshots__/test_resolver.ambr b/posthog/hogql/test/__snapshots__/test_resolver.ambr index 78223c03c2b66..03f6a7369d379 100644 --- a/posthog/hogql/test/__snapshots__/test_resolver.ambr +++ b/posthog/hogql/test/__snapshots__/test_resolver.ambr @@ -3,217 +3,360 @@ { select: [ { - chain: [ - "uuid" - ] - type: { - name: "uuid" - table_type: { - aliases: {} - anonymous_tables: [] - columns: { - $group_0: { - name: "$group_0" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: { + name: "uuid" + table_type: { + aliases: {} + anonymous_tables: [] + columns: { + $group_0: { + alias: "$group_0" + type: { + name: "$group_0" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } + } } } + }, + $group_1: { + alias: "$group_1" + type: { + name: "$group_1" + table_type: + } + }, + $group_2: { + alias: "$group_2" + type: { + name: "$group_2" + table_type: + } + }, + $group_3: { + alias: "$group_3" + type: { + name: "$group_3" + table_type: + } + }, + $group_4: { + alias: "$group_4" + type: { + name: "$group_4" + table_type: + } + }, + $session_id: { + alias: "$session_id" + type: { + name: "$session_id" + table_type: + } + }, + created_at: { + alias: "created_at" + type: { + name: "created_at" + table_type: + } + }, + distinct_id: { + alias: "distinct_id" + type: { + name: "distinct_id" + table_type: + } + }, + elements_chain: { + alias: "elements_chain" + type: { + name: "elements_chain" + table_type: + } + }, + event: { + alias: "event" + type: { + name: "event" + table_type: + } + }, + properties: { + alias: "properties" + type: { + name: "properties" + table_type: + } + }, + timestamp: { + alias: "timestamp" + type: { + name: "timestamp" + table_type: + } + }, + uuid: { + alias: "uuid" + type: { + name: "uuid" + table_type: + } } - }, - $group_1: { - name: "$group_1" - table_type: - }, - $group_2: { - name: "$group_2" - table_type: - }, - $group_3: { - name: "$group_3" - table_type: - }, - $group_4: { - name: "$group_4" - table_type: - }, - $session_id: { - name: "$session_id" - table_type: - }, - created_at: { - name: "created_at" - table_type: - }, - distinct_id: { - name: "distinct_id" - table_type: - }, - elements_chain: { - name: "elements_chain" - table_type: - }, - event: { - name: "event" - table_type: - }, - properties: { - name: "properties" - table_type: - }, - timestamp: { - name: "timestamp" - table_type: - }, - uuid: { - name: "uuid" - table_type: } - } - ctes: {} - tables: { - events: + ctes: {} + tables: { + events: + } } } } + hidden: True + type: { + alias: "uuid" + type: + } }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: { + name: "properties" + table_type: + } + } + hidden: True type: { - name: "properties" - table_type: + alias: "properties" + type: } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: + } + } + hidden: True type: { - name: "distinct_id" - table_type: + alias: "distinct_id" + type: } }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: { + name: "elements_chain" + table_type: + } + } + hidden: True type: { - name: "elements_chain" - table_type: + alias: "elements_chain" + type: } }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: { + name: "created_at" + table_type: + } + } + hidden: True type: { - name: "created_at" - table_type: + alias: "created_at" + type: } }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: { + name: "$session_id" + table_type: + } + } + hidden: True type: { - name: "$session_id" - table_type: + alias: "$session_id" + type: } }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: { + name: "$group_0" + table_type: + } + } + hidden: True type: { - name: "$group_0" - table_type: + alias: "$group_0" + type: } }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: { + name: "$group_1" + table_type: + } + } + hidden: True type: { - name: "$group_1" - table_type: + alias: "$group_1" + type: } }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: { + name: "$group_2" + table_type: + } + } + hidden: True type: { - name: "$group_2" - table_type: + alias: "$group_2" + type: } }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: { + name: "$group_3" + table_type: + } + } + hidden: True type: { - name: "$group_3" - table_type: + alias: "$group_3" + type: } }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: { + name: "$group_4" + table_type: + } + } + hidden: True type: { - name: "$group_4" - table_type: + alias: "$group_4" + type: } } ] @@ -221,81 +364,146 @@ table: { select: [ { - chain: [ - "uuid" - ] + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: + } + hidden: True type: }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: + } + hidden: True type: }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: + } + hidden: True type: }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: + } + hidden: True type: }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: + } + hidden: True type: }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: + } + hidden: True type: }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: + } + hidden: True type: }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: + } + hidden: True type: } ] @@ -340,119 +548,23 @@ --- # name: TestResolver.test_asterisk_expander_select_union ' - { - select: [ - { - chain: [ - "uuid" - ] - type: { - name: "uuid" - table_type: { - types: [ - { - aliases: {} - anonymous_tables: [] - columns: { - $group_0: { - name: "$group_0" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} - } - } - } - }, - $group_1: { - name: "$group_1" - table_type: - }, - $group_2: { - name: "$group_2" - table_type: - }, - $group_3: { - name: "$group_3" - table_type: - }, - $group_4: { - name: "$group_4" - table_type: - }, - $session_id: { - name: "$session_id" - table_type: - }, - created_at: { - name: "created_at" - table_type: - }, - distinct_id: { - name: "distinct_id" - table_type: - }, - elements_chain: { - name: "elements_chain" - table_type: - }, - event: { - name: "event" - table_type: - }, - properties: { - name: "properties" - table_type: - }, - timestamp: { - name: "timestamp" - table_type: - }, - uuid: { - name: "uuid" - table_type: - } - } - ctes: {} - tables: { - events: - } - }, - { - aliases: {} - anonymous_tables: [] - columns: { - $group_0: { + { + select: [ + { + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: { + name: "uuid" + table_type: { + aliases: {} + anonymous_tables: [] + columns: { + $group_0: { + alias: "$group_0" + type: { name: "$group_0" table_type: { table: { @@ -491,171 +603,308 @@ } } } - }, - $group_1: { + } + }, + $group_1: { + alias: "$group_1" + type: { name: "$group_1" table_type: - }, - $group_2: { + } + }, + $group_2: { + alias: "$group_2" + type: { name: "$group_2" table_type: - }, - $group_3: { + } + }, + $group_3: { + alias: "$group_3" + type: { name: "$group_3" table_type: - }, - $group_4: { + } + }, + $group_4: { + alias: "$group_4" + type: { name: "$group_4" table_type: - }, - $session_id: { + } + }, + $session_id: { + alias: "$session_id" + type: { name: "$session_id" table_type: - }, - created_at: { + } + }, + created_at: { + alias: "created_at" + type: { name: "created_at" table_type: - }, - distinct_id: { + } + }, + distinct_id: { + alias: "distinct_id" + type: { name: "distinct_id" table_type: - }, - elements_chain: { + } + }, + elements_chain: { + alias: "elements_chain" + type: { name: "elements_chain" table_type: - }, - event: { + } + }, + event: { + alias: "event" + type: { name: "event" table_type: - }, - properties: { + } + }, + properties: { + alias: "properties" + type: { name: "properties" table_type: - }, - timestamp: { + } + }, + timestamp: { + alias: "timestamp" + type: { name: "timestamp" table_type: - }, - uuid: { + } + }, + uuid: { + alias: "uuid" + type: { name: "uuid" table_type: } } - ctes: {} - tables: { - events: - } } - ] + ctes: {} + tables: { + events: + } + } } } + hidden: True + type: { + alias: "uuid" + type: + } }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: { + name: "properties" + table_type: + } + } + hidden: True type: { - name: "properties" - table_type: + alias: "properties" + type: } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: + } + } + hidden: True type: { - name: "distinct_id" - table_type: + alias: "distinct_id" + type: } }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: { + name: "elements_chain" + table_type: + } + } + hidden: True type: { - name: "elements_chain" - table_type: + alias: "elements_chain" + type: } }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: { + name: "created_at" + table_type: + } + } + hidden: True type: { - name: "created_at" - table_type: + alias: "created_at" + type: } }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: { + name: "$session_id" + table_type: + } + } + hidden: True type: { - name: "$session_id" - table_type: + alias: "$session_id" + type: } }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: { + name: "$group_0" + table_type: + } + } + hidden: True type: { - name: "$group_0" - table_type: + alias: "$group_0" + type: } }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: { + name: "$group_1" + table_type: + } + } + hidden: True type: { - name: "$group_1" - table_type: + alias: "$group_1" + type: } }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: { + name: "$group_2" + table_type: + } + } + hidden: True type: { - name: "$group_2" - table_type: + alias: "$group_2" + type: } }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: { + name: "$group_3" + table_type: + } + } + hidden: True type: { - name: "$group_3" - table_type: + alias: "$group_3" + type: } }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: { + name: "$group_4" + table_type: + } + } + hidden: True type: { - name: "$group_4" - table_type: + alias: "$group_4" + type: } } ] @@ -665,81 +914,146 @@ { select: [ { - chain: [ - "uuid" - ] + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: + } + hidden: True type: }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: + } + hidden: True type: }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: + } + hidden: True type: }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: + } + hidden: True type: }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: + } + hidden: True type: }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: + } + hidden: True type: }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: + } + hidden: True type: }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: + } + hidden: True type: }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: + } + hidden: True type: } ] @@ -757,82 +1071,261 @@ { select: [ { - chain: [ - "uuid" - ] - type: + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: { + name: "uuid" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } + } + } + } + } + hidden: True + type: { + alias: "uuid" + type: + } }, { - chain: [ - "event" - ] - type: + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "properties" - ] - type: + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: { + name: "properties" + table_type: + } + } + hidden: True + type: { + alias: "properties" + type: + } }, { - chain: [ - "timestamp" - ] - type: + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True + type: { + alias: "timestamp" + type: + } }, { - chain: [ - "distinct_id" - ] - type: + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: + } + } + hidden: True + type: { + alias: "distinct_id" + type: + } }, { - chain: [ - "elements_chain" - ] - type: + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: { + name: "elements_chain" + table_type: + } + } + hidden: True + type: { + alias: "elements_chain" + type: + } }, { - chain: [ - "created_at" - ] - type: + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: { + name: "created_at" + table_type: + } + } + hidden: True + type: { + alias: "created_at" + type: + } }, { - chain: [ - "$session_id" - ] - type: + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: { + name: "$session_id" + table_type: + } + } + hidden: True + type: { + alias: "$session_id" + type: + } }, { - chain: [ - "$group_0" - ] - type: + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: { + name: "$group_0" + table_type: + } + } + hidden: True + type: { + alias: "$group_0" + type: + } }, { - chain: [ - "$group_1" - ] - type: + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: { + name: "$group_1" + table_type: + } + } + hidden: True + type: { + alias: "$group_1" + type: + } }, { - chain: [ - "$group_2" - ] - type: + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: { + name: "$group_2" + table_type: + } + } + hidden: True + type: { + alias: "$group_2" + type: + } }, { - chain: [ - "$group_3" - ] - type: + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: { + name: "$group_3" + table_type: + } + } + hidden: True + type: { + alias: "$group_3" + type: + } }, { - chain: [ - "$group_4" - ] - type: + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: { + name: "$group_4" + table_type: + } + } + hidden: True + type: { + alias: "$group_4" + type: + } } ] select_from: { @@ -844,10 +1337,37 @@ } type: } - type: + type: { + aliases: {} + anonymous_tables: [] + columns: { + $group_0: , + $group_1: , + $group_2: , + $group_3: , + $group_4: , + $session_id: , + created_at: , + distinct_id: , + elements_chain: , + event: , + properties: , + timestamp: , + uuid: + } + ctes: {} + tables: { + events: + } + } } ] - type: + type: { + types: [ + , + + ] + } } type: } @@ -882,43 +1402,59 @@ { select: [ { - chain: [ - "a" - ] - type: { - name: "a" - table_type: { - aliases: { - a: { - alias: "a" - type: { - data_type: "int" - } - }, - b: { - alias: "b" - type: { - data_type: "int" + alias: "a" + expr: { + chain: [ + "a" + ] + type: { + name: "a" + table_type: { + aliases: { + a: { + alias: "a" + type: { + data_type: "int" + } + }, + b: { + alias: "b" + type: { + data_type: "int" + } } } + anonymous_tables: [] + columns: { + a: , + b: + } + ctes: {} + tables: {} } - anonymous_tables: [] - columns: { - a: , - b: - } - ctes: {} - tables: {} } } + hidden: True + type: { + alias: "a" + type: + } }, { - chain: [ - "b" - ] + alias: "b" + expr: { + chain: [ + "b" + ] + type: { + name: "b" + table_type: + } + } + hidden: True type: { - name: "b" - table_type: + alias: "b" + type: } } ] @@ -931,6 +1467,7 @@ type: value: 1 } + hidden: False type: }, { @@ -939,6 +1476,7 @@ type: value: 2 } + hidden: False type: } ] @@ -966,46 +1504,62 @@ { select: [ { - chain: [ - "a" - ] - type: { - name: "a" - table_type: { - alias: "x" - select_query_type: { - aliases: { - a: { - alias: "a" - type: { - data_type: "int" - } - }, - b: { - alias: "b" - type: { - data_type: "int" + alias: "a" + expr: { + chain: [ + "a" + ] + type: { + name: "a" + table_type: { + alias: "x" + select_query_type: { + aliases: { + a: { + alias: "a" + type: { + data_type: "int" + } + }, + b: { + alias: "b" + type: { + data_type: "int" + } } } + anonymous_tables: [] + columns: { + a: , + b: + } + ctes: {} + tables: {} } - anonymous_tables: [] - columns: { - a: , - b: - } - ctes: {} - tables: {} } } } + hidden: True + type: { + alias: "a" + type: + } }, { - chain: [ - "b" - ] + alias: "b" + expr: { + chain: [ + "b" + ] + type: { + name: "b" + table_type: + } + } + hidden: True type: { - name: "b" - table_type: + alias: "b" + type: } } ] @@ -1019,6 +1573,7 @@ type: value: 1 } + hidden: False type: }, { @@ -1027,6 +1582,7 @@ type: value: 2 } + hidden: False type: } ] @@ -1053,157 +1609,261 @@ ' { select: [ - { - chain: [ - "uuid" - ] - type: { - name: "uuid" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + { + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: { + name: "uuid" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "uuid" + type: + } }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: { + name: "properties" + table_type: + } + } + hidden: True type: { - name: "properties" - table_type: + alias: "properties" + type: } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: + } + } + hidden: True type: { - name: "distinct_id" - table_type: + alias: "distinct_id" + type: } }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: { + name: "elements_chain" + table_type: + } + } + hidden: True type: { - name: "elements_chain" - table_type: + alias: "elements_chain" + type: } }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: { + name: "created_at" + table_type: + } + } + hidden: True type: { - name: "created_at" - table_type: + alias: "created_at" + type: } }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: { + name: "$session_id" + table_type: + } + } + hidden: True type: { - name: "$session_id" - table_type: + alias: "$session_id" + type: } }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: { + name: "$group_0" + table_type: + } + } + hidden: True type: { - name: "$group_0" - table_type: + alias: "$group_0" + type: } }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: { + name: "$group_1" + table_type: + } + } + hidden: True type: { - name: "$group_1" - table_type: + alias: "$group_1" + type: } }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: { + name: "$group_2" + table_type: + } + } + hidden: True type: { - name: "$group_2" - table_type: + alias: "$group_2" + type: } }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: { + name: "$group_3" + table_type: + } + } + hidden: True type: { - name: "$group_3" - table_type: + alias: "$group_3" + type: } }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: { + name: "$group_4" + table_type: + } + } + hidden: True type: { - name: "$group_4" - table_type: + alias: "$group_4" + type: } } ] @@ -1247,159 +1907,263 @@ { select: [ { - chain: [ - "uuid" - ] - type: { - name: "uuid" - table_type: { - alias: "e" + alias: "uuid" + expr: { + chain: [ + "uuid" + ] + type: { + name: "uuid" table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "e" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } } + hidden: True + type: { + alias: "uuid" + type: + } }, { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } }, { - chain: [ - "properties" - ] + alias: "properties" + expr: { + chain: [ + "properties" + ] + type: { + name: "properties" + table_type: + } + } + hidden: True type: { - name: "properties" - table_type: + alias: "properties" + type: } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } }, { - chain: [ - "distinct_id" - ] + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: + } + } + hidden: True type: { - name: "distinct_id" - table_type: + alias: "distinct_id" + type: } }, { - chain: [ - "elements_chain" - ] + alias: "elements_chain" + expr: { + chain: [ + "elements_chain" + ] + type: { + name: "elements_chain" + table_type: + } + } + hidden: True type: { - name: "elements_chain" - table_type: + alias: "elements_chain" + type: } }, { - chain: [ - "created_at" - ] + alias: "created_at" + expr: { + chain: [ + "created_at" + ] + type: { + name: "created_at" + table_type: + } + } + hidden: True type: { - name: "created_at" - table_type: + alias: "created_at" + type: } }, { - chain: [ - "$session_id" - ] + alias: "$session_id" + expr: { + chain: [ + "$session_id" + ] + type: { + name: "$session_id" + table_type: + } + } + hidden: True type: { - name: "$session_id" - table_type: + alias: "$session_id" + type: } }, { - chain: [ - "$group_0" - ] + alias: "$group_0" + expr: { + chain: [ + "$group_0" + ] + type: { + name: "$group_0" + table_type: + } + } + hidden: True type: { - name: "$group_0" - table_type: + alias: "$group_0" + type: } }, { - chain: [ - "$group_1" - ] + alias: "$group_1" + expr: { + chain: [ + "$group_1" + ] + type: { + name: "$group_1" + table_type: + } + } + hidden: True type: { - name: "$group_1" - table_type: + alias: "$group_1" + type: } }, { - chain: [ - "$group_2" - ] + alias: "$group_2" + expr: { + chain: [ + "$group_2" + ] + type: { + name: "$group_2" + table_type: + } + } + hidden: True type: { - name: "$group_2" - table_type: + alias: "$group_2" + type: } }, { - chain: [ - "$group_3" - ] + alias: "$group_3" + expr: { + chain: [ + "$group_3" + ] + type: { + name: "$group_3" + table_type: + } + } + hidden: True type: { - name: "$group_3" - table_type: + alias: "$group_3" + type: } }, { - chain: [ - "$group_4" - ] + alias: "$group_4" + expr: { + chain: [ + "$group_4" + ] + type: { + name: "$group_4" + table_type: + } + } + hidden: True type: { - name: "$group_4" - table_type: + alias: "$group_4" + type: } } ] @@ -1446,49 +2210,57 @@ { args: [ { - chain: [ - "timestamp" - ] - type: { - name: "timestamp" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "timestamp" + type: + } } ] distinct: False @@ -1678,137 +2450,31 @@ } ] } - value: (1, 2, 3) - } - ] - type: { - aliases: {} - anonymous_tables: [] - columns: {} - ctes: {} - tables: {} - } - } - ' ---- -# name: TestResolver.test_resolve_events_table - ' - { - select: [ - { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} - } - } - } - } - }, - { - chain: [ - "events", - "timestamp" - ] - type: { - name: "timestamp" - table_type: - } - } - ] - select_from: { - table: { - chain: [ - "events" - ] - type: - } - type: - } - type: { - aliases: {} - anonymous_tables: [] - columns: { - event: , - timestamp: - } - ctes: {} - tables: { - events: - } - } - where: { - left: { - chain: [ - "events", - "event" - ] - type: { - name: "event" - table_type: - } - } - op: "==" - right: { - type: { - data_type: "str" - } - value: "test" - } - type: { - data_type: "bool" + value: (1, 2, 3) } + ] + type: { + aliases: {} + anonymous_tables: [] + columns: {} + ctes: {} + tables: {} } } ' --- -# name: TestResolver.test_resolve_events_table_alias +# name: TestResolver.test_resolve_events_table ' { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - alias: "e" + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" table_type: { table: { fields: { @@ -1848,20 +2514,32 @@ } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "e", - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "events", + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } } ] select_from: { - alias: "e" table: { chain: [ "events" @@ -1879,18 +2557,26 @@ } ctes: {} tables: { - e: + events: } } where: { left: { - chain: [ - "e", - "event" - ] + alias: "event" + expr: { + chain: [ + "events", + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } } op: "==" @@ -1907,12 +2593,12 @@ } ' --- -# name: TestResolver.test_resolve_events_table_column_alias +# name: TestResolver.test_resolve_events_table_alias ' { select: [ { - alias: "ee" + alias: "event" expr: { chain: [ "event" @@ -1961,39 +2647,29 @@ } } } + hidden: True type: { - alias: "ee" + alias: "event" type: } }, { - chain: [ - "ee" - ] - type: - }, - { - alias: "e" + alias: "timestamp" expr: { chain: [ - "ee" + "e", + "timestamp" ] - type: + type: { + name: "timestamp" + table_type: + } } + hidden: True type: { - alias: "e" + alias: "timestamp" type: } - }, - { - chain: [ - "e", - "timestamp" - ] - type: { - name: "timestamp" - table_type: - } } ] select_from: { @@ -2007,14 +2683,10 @@ type: } type: { - aliases: { - e: , - ee: - } + aliases: {} anonymous_tables: [] columns: { - e: , - ee: , + event: , timestamp: } ctes: {} @@ -2024,13 +2696,21 @@ } where: { left: { - chain: [ - "e", - "event" - ] + alias: "event" + expr: { + chain: [ + "e", + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True type: { - name: "event" - table_type: + alias: "event" + type: } } op: "==" @@ -2047,83 +2727,263 @@ } ' --- -# name: TestResolver.test_resolve_events_table_column_alias_inside_subquery +# name: TestResolver.test_resolve_events_table_column_alias ' { select: [ + { + alias: "ee" + expr: { + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + alias: "e" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } + } + } + } + } + } + hidden: True + type: { + alias: "event" + type: + } + } + hidden: False + type: { + alias: "ee" + type: + } + }, { chain: [ - "b" + "ee" ] + type: + }, + { + alias: "e" + expr: { + chain: [ + "ee" + ] + type: + } + hidden: False type: { - name: "b" - table_type: { - alias: "e" - select_query_type: { - aliases: { - b: { - alias: "b" - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "e" + type: + } + }, + { + alias: "timestamp" + expr: { + chain: [ + "e", + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True + type: { + alias: "timestamp" + type: + } + } + ] + select_from: { + alias: "e" + table: { + chain: [ + "events" + ] + type: + } + type: + } + type: { + aliases: { + e: , + ee: + } + anonymous_tables: [] + columns: { + e: , + ee: , + timestamp: + } + ctes: {} + tables: { + e: + } + } + where: { + left: { + alias: "event" + expr: { + chain: [ + "e", + "event" + ] + type: { + name: "event" + table_type: + } + } + hidden: True + type: { + alias: "event" + type: + } + } + op: "==" + right: { + type: { + data_type: "str" + } + value: "test" + } + type: { + data_type: "bool" + } + } + } + ' +--- +# name: TestResolver.test_resolve_events_table_column_alias_inside_subquery + ' + { + select: [ + { + alias: "b" + expr: { + chain: [ + "b" + ] + type: { + name: "b" + table_type: { + alias: "e" + select_query_type: { + aliases: { + b: { + alias: "b" + type: { + alias: "event" + type: { + name: "event" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } + } } } } - } - }, - c: { - alias: "c" - type: { - name: "timestamp" - table_type: + }, + c: { + alias: "c" + type: { + alias: "timestamp" + type: { + name: "timestamp" + table_type: + } + } } } - } - anonymous_tables: [] - columns: { - b: , - c: - } - ctes: {} - tables: { - events: + anonymous_tables: [] + columns: { + b: , + c: + } + ctes: {} + tables: { + events: + } } } } } + hidden: True + type: { + alias: "b" + type: + } } ] select_from: { @@ -2133,21 +2993,33 @@ { alias: "b" expr: { - chain: [ - "event" - ] + alias: "event" + expr: { + chain: [ + "event" + ] + type: + } + hidden: True type: } + hidden: False type: }, { alias: "c" expr: { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: + } + hidden: True type: } + hidden: False type: } ] @@ -2177,13 +3049,21 @@ } where: { left: { - chain: [ - "e", - "b" - ] + alias: "b" + expr: { + chain: [ + "e", + "b" + ] + type: { + name: "b" + table_type: + } + } + hidden: True type: { - name: "b" - table_type: + alias: "b" + type: } } op: "==" @@ -2205,95 +3085,249 @@ { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "event" + type: + } }, { + alias: "id" + expr: { + chain: [ + "pdi", + "person", + "id" + ] + type: { + name: "id" + table_type: { + field: "person" + lazy_join: { + from_field: "person_id", + join_function: , + join_table: { + fields: { + created_at: {}, + id: {}, + is_identified: {}, + pdi: {}, + properties: {}, + team_id: {} + } + } + } + table_type: { + field: "pdi" + lazy_join: { + from_field: "distinct_id", + join_function: , + join_table: { + fields: { + distinct_id: {}, + person: {}, + person_id: {}, + team_id: {} + } + } + } + table_type: + } + } + } + } + hidden: True + type: { + alias: "id" + type: + } + } + ] + select_from: { + table: { chain: [ - "pdi", - "person", - "id" + "events" ] - type: { - name: "id" - table_type: { - field: "person" - lazy_join: { - from_field: "person_id", - join_function: , - join_table: { - fields: { - created_at: {}, - id: {}, - is_identified: {}, - pdi: {}, - properties: {}, - team_id: {} + type: + } + type: + } + type: { + aliases: {} + anonymous_tables: [] + columns: { + event: , + id: + } + ctes: {} + tables: { + events: + } + } + } + ' +--- +# name: TestResolver.test_resolve_lazy_events_pdi_person_table_aliased + ' + { + select: [ + { + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + alias: "e" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } + } + } + hidden: True + type: { + alias: "event" + type: + } + }, + { + alias: "id" + expr: { + chain: [ + "e", + "pdi", + "person", + "id" + ] + type: { + name: "id" table_type: { - field: "pdi" + field: "person" lazy_join: { - from_field: "distinct_id", + from_field: "person_id", join_function: , join_table: { fields: { - distinct_id: {}, - person: {}, - person_id: {}, + created_at: {}, + id: {}, + is_identified: {}, + pdi: {}, + properties: {}, team_id: {} } } } - table_type: + table_type: { + field: "pdi" + lazy_join: { + from_field: "distinct_id", + join_function: , + join_table: { + fields: { + distinct_id: {}, + person: {}, + person_id: {}, + team_id: {} + } + } + } + table_type: + } } } } + hidden: True + type: { + alias: "id" + type: + } } ] select_from: { + alias: "e" table: { chain: [ "events" @@ -2311,24 +3345,24 @@ } ctes: {} tables: { - events: + e: } } } ' --- -# name: TestResolver.test_resolve_lazy_events_pdi_person_table_aliased +# name: TestResolver.test_resolve_lazy_events_pdi_table ' { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - alias: "e" + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" table_type: { table: { fields: { @@ -2368,32 +3402,21 @@ } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "e", - "pdi", - "person", - "id" - ] - type: { - name: "id" - table_type: { - field: "person" - lazy_join: { - from_field: "person_id", - join_function: , - join_table: { - fields: { - created_at: {}, - id: {}, - is_identified: {}, - pdi: {}, - properties: {}, - team_id: {} - } - } - } + alias: "person_id" + expr: { + chain: [ + "pdi", + "person_id" + ] + type: { + name: "person_id" table_type: { field: "pdi" lazy_join: { @@ -2412,105 +3435,10 @@ } } } - } - ] - select_from: { - alias: "e" - table: { - chain: [ - "events" - ] - type: - } - type: - } - type: { - aliases: {} - anonymous_tables: [] - columns: { - event: , - id: - } - ctes: {} - tables: { - e: - } - } - } - ' ---- -# name: TestResolver.test_resolve_lazy_events_pdi_table - ' - { - select: [ - { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} - } - } - } - } - }, - { - chain: [ - "pdi", - "person_id" - ] + hidden: True type: { - name: "person_id" - table_type: { - field: "pdi" - lazy_join: { - from_field: "distinct_id", - join_function: , - join_table: { - fields: { - distinct_id: {}, - person: {}, - person_id: {}, - team_id: {} - } - } - } - table_type: - } + alias: "person_id" + type: } } ] @@ -2543,78 +3471,94 @@ { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - alias: "e" + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "e" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "e", - "pdi", - "person_id" - ] - type: { - name: "person_id" - table_type: { - field: "pdi" - lazy_join: { - from_field: "distinct_id", - join_function: , - join_table: { - fields: { - distinct_id: {}, - person: {}, - person_id: {}, - team_id: {} + alias: "person_id" + expr: { + chain: [ + "e", + "pdi", + "person_id" + ] + type: { + name: "person_id" + table_type: { + field: "pdi" + lazy_join: { + from_field: "distinct_id", + join_function: , + join_table: { + fields: { + distinct_id: {}, + person: {}, + person_id: {}, + team_id: {} + } } } + table_type: } - table_type: } } + hidden: True + type: { + alias: "person_id" + type: + } } ] select_from: { @@ -2647,49 +3591,65 @@ { select: [ { - chain: [ - "distinct_id" - ] - type: { - name: "distinct_id" - table_type: { - table: { - fields: { - distinct_id: {}, - person: {}, - person_id: {}, - team_id: {} + alias: "distinct_id" + expr: { + chain: [ + "distinct_id" + ] + type: { + name: "distinct_id" + table_type: { + table: { + fields: { + distinct_id: {}, + person: {}, + person_id: {}, + team_id: {} + } } } } } + hidden: True + type: { + alias: "distinct_id" + type: + } }, { - chain: [ - "person", - "id" - ] - type: { - name: "id" - table_type: { - field: "person" - lazy_join: { - from_field: "person_id", - join_function: , - join_table: { - fields: { - created_at: {}, - id: {}, - is_identified: {}, - pdi: {}, - properties: {}, - team_id: {} + alias: "id" + expr: { + chain: [ + "person", + "id" + ] + type: { + name: "id" + table_type: { + field: "person" + lazy_join: { + from_field: "person_id", + join_function: , + join_table: { + fields: { + created_at: {}, + id: {}, + is_identified: {}, + pdi: {}, + properties: {}, + team_id: {} + } } } + table_type: } - table_type: } } + hidden: True + type: { + alias: "id" + type: + } } ] select_from: { @@ -2723,57 +3683,73 @@ { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } } ] @@ -2802,57 +3778,73 @@ { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "timestamp" - ] + alias: "timestamp" + expr: { + chain: [ + "timestamp" + ] + type: { + name: "timestamp" + table_type: + } + } + hidden: True type: { - name: "timestamp" - table_type: + alias: "timestamp" + type: } } ] @@ -2893,69 +3885,85 @@ { select: [ { - chain: [ - "event" - ] - type: { - name: "event" - table_type: { - table: { - fields: { - $group_0: {}, - $group_1: {}, - $group_2: {}, - $group_3: {}, - $group_4: {}, - $session_id: {}, - created_at: {}, - distinct_id: {}, - elements_chain: {}, - event: {}, - goe_0: {}, - goe_1: {}, - goe_2: {}, - goe_3: {}, - goe_4: {}, - group_0: {}, - group_1: {}, - group_2: {}, - group_3: {}, - group_4: {}, - override: {}, - override_person_id: {}, - pdi: {}, - person: {}, - person_id: {}, - poe: {}, - properties: {}, - session: {}, - team_id: {}, - timestamp: {}, - uuid: {} + alias: "event" + expr: { + chain: [ + "event" + ] + type: { + name: "event" + table_type: { + table: { + fields: { + $group_0: {}, + $group_1: {}, + $group_2: {}, + $group_3: {}, + $group_4: {}, + $session_id: {}, + created_at: {}, + distinct_id: {}, + elements_chain: {}, + event: {}, + goe_0: {}, + goe_1: {}, + goe_2: {}, + goe_3: {}, + goe_4: {}, + group_0: {}, + group_1: {}, + group_2: {}, + group_3: {}, + group_4: {}, + override: {}, + override_person_id: {}, + pdi: {}, + person: {}, + person_id: {}, + poe: {}, + properties: {}, + session: {}, + team_id: {}, + timestamp: {}, + uuid: {} + } } } } } + hidden: True + type: { + alias: "event" + type: + } }, { - chain: [ - "poe", - "id" - ] - type: { - name: "id" - table_type: { - field: "poe" - table_type: - virtual_table: { - fields: { - created_at: {}, - id: {}, - properties: {} + alias: "id" + expr: { + chain: [ + "poe", + "id" + ] + type: { + name: "id" + table_type: { + field: "poe" + table_type: + virtual_table: { + fields: { + created_at: {}, + id: {}, + properties: {} + } } } } } + hidden: True + type: { + alias: "id" + type: + } } ] select_from: { diff --git a/posthog/hogql/test/test_modifiers.py b/posthog/hogql/test/test_modifiers.py index 4296213727f37..028f9dd455216 100644 --- a/posthog/hogql/test/test_modifiers.py +++ b/posthog/hogql/test/test_modifiers.py @@ -51,28 +51,28 @@ def test_modifiers_persons_on_events_mode_mapping(self): "events.event", "events__pdi__person.id", "events__pdi__person.properties", - "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s)", + "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s) AS created_at", ), ( PersonsOnEventsMode.v1_enabled, "events.event", "events.person_id", "events.person_properties", - "toTimeZone(events.person_created_at, %(hogql_val_0)s)", + "toTimeZone(events.person_created_at, %(hogql_val_0)s) AS created_at", ), ( PersonsOnEventsMode.v1_mixed, "events.event", "events__pdi.person_id", "events.person_properties", - "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s)", + "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s) AS created_at", ), ( PersonsOnEventsMode.v2_enabled, "events.event", "events.person_id", "events.person_properties", - "toTimeZone(events.person_created_at, %(hogql_val_0)s)", + "toTimeZone(events.person_created_at, %(hogql_val_0)s) AS created_at", ), ] @@ -159,21 +159,25 @@ def test_modifiers_materialization_mode(self): team=self.team, modifiers=HogQLQueryModifiers(materializationMode=MaterializationMode.auto), ) - assert "SELECT nullIf(nullIf(events.`mat_$browser`, ''), 'null') FROM events" in response.clickhouse + assert ( + "SELECT nullIf(nullIf(events.`mat_$browser`, ''), 'null') AS `$browser` FROM events" in response.clickhouse + ) response = execute_hogql_query( "SELECT properties.$browser FROM events", team=self.team, modifiers=HogQLQueryModifiers(materializationMode=MaterializationMode.legacy_null_as_null), ) - assert "SELECT nullIf(nullIf(events.`mat_$browser`, ''), 'null') FROM events" in response.clickhouse + assert ( + "SELECT nullIf(nullIf(events.`mat_$browser`, ''), 'null') AS `$browser` FROM events" in response.clickhouse + ) response = execute_hogql_query( "SELECT properties.$browser FROM events", team=self.team, modifiers=HogQLQueryModifiers(materializationMode=MaterializationMode.legacy_null_as_string), ) - assert "SELECT nullIf(events.`mat_$browser`, '') FROM events" in response.clickhouse + assert "SELECT nullIf(events.`mat_$browser`, '') AS `$browser` FROM events" in response.clickhouse response = execute_hogql_query( "SELECT properties.$browser FROM events", @@ -181,6 +185,6 @@ def test_modifiers_materialization_mode(self): modifiers=HogQLQueryModifiers(materializationMode=MaterializationMode.disabled), ) assert ( - "SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^\"|\"$', '') FROM events" + "SELECT replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^\"|\"$', '') AS `$browser` FROM events" in response.clickhouse ) diff --git a/posthog/hogql/test/test_query.py b/posthog/hogql/test/test_query.py index 235ef2d251ab1..67e3cd6c0e049 100644 --- a/posthog/hogql/test/test_query.py +++ b/posthog/hogql/test/test_query.py @@ -1043,7 +1043,7 @@ def test_property_access_with_arrays(self): self.assertEqual( response.clickhouse, f"SELECT " - f"replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^\"|\"$', ''), " + f"replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_0)s), ''), 'null'), '^\"|\"$', '') AS string, " f"replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_1)s, %(hogql_val_2)s), ''), 'null'), '^\"|\"$', ''), " f"replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_3)s, %(hogql_val_4)s), ''), 'null'), '^\"|\"$', ''), " f"replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(events.properties, %(hogql_val_5)s, %(hogql_val_6)s, %(hogql_val_7)s), ''), 'null'), '^\"|\"$', ''), " diff --git a/posthog/hogql/test/test_resolver.py b/posthog/hogql/test/test_resolver.py index 069e633e0a457..c2fc2324271bb 100644 --- a/posthog/hogql/test/test_resolver.py +++ b/posthog/hogql/test/test_resolver.py @@ -325,7 +325,7 @@ def test_visit_hogqlx_tag(self): node = cast(ast.SelectQuery, resolve_types(node, self.context)) table_node = cast(ast.SelectQuery, node).select_from.table expected = ast.SelectQuery( - select=[ast.Field(chain=["event"])], + select=[ast.Alias(hidden=True, alias="event", expr=ast.Field(chain=["event"]))], select_from=ast.JoinExpr(table=ast.Field(chain=["events"])), ) assert clone_expr(table_node, clear_types=True) == expected diff --git a/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr b/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr index 9689b1c761d26..4afb16d85f3b5 100644 --- a/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr +++ b/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr @@ -1,7 +1,7 @@ # name: TestLazyJoins.test_resolve_lazy_table_as_select_table ' - SELECT persons.id AS id, persons.properties___email AS email, persons.`properties___$browser` AS `$browser` + SELECT persons.id, persons.properties___email AS email, persons.`properties___$browser` AS `$browser` FROM ( SELECT argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_0)s), ''), 'null'), '^"|"$', ''), person.version) AS properties___email, argMax(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person.properties, %(hogql_val_1)s), ''), 'null'), '^"|"$', ''), person.version) AS `properties___$browser`, person.id AS id FROM person @@ -15,7 +15,7 @@ # name: TestLazyJoins.test_resolve_lazy_table_as_table_in_join ' - SELECT events.event AS event, events.distinct_id AS distinct_id, events__pdi.person_id AS person_id, persons.properties___email AS email + SELECT events.event, events.distinct_id, events__pdi.person_id, persons.properties___email AS email FROM events INNER JOIN ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 @@ -35,7 +35,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables ' - SELECT events.event AS event, events__pdi.person_id AS person_id + SELECT events.event, 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 AS distinct_id FROM person_distinct_id2 @@ -68,7 +68,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_one_level_properties_deep ' - SELECT person_distinct_ids__person.`properties___$browser___in___json` AS json + SELECT person_distinct_ids__person.`properties___$browser___in___json` AS `$browser__in__json` FROM ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 @@ -87,7 +87,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_traversed_fields ' - SELECT events.event AS event, events__pdi.person_id AS person_id + SELECT events.event, 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 AS distinct_id FROM person_distinct_id2 @@ -101,7 +101,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_two_levels ' - SELECT events.event AS event, events__pdi__person.id AS id + SELECT events.event, 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 AS distinct_id FROM person_distinct_id2 @@ -121,7 +121,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_two_levels_properties ' - SELECT events.event AS event, events__pdi__person.`properties___$browser` AS `$browser` + SELECT events.event, events__pdi__person.`properties___$browser` AS `$browser` FROM events INNER JOIN ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 @@ -141,7 +141,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_two_levels_properties_duplicate ' - SELECT events.event AS event, events__pdi__person.properties AS properties, events__pdi__person.properties___name AS name + SELECT events.event, events__pdi__person.properties, events__pdi__person.properties___name AS name FROM events INNER JOIN ( SELECT argMax(person_distinct_id2.person_id, person_distinct_id2.version) AS person_id, person_distinct_id2.distinct_id AS distinct_id FROM person_distinct_id2 @@ -161,7 +161,7 @@ # name: TestLazyJoins.test_resolve_lazy_tables_two_levels_traversed ' - SELECT events.event AS event, events__pdi__person.id AS id + SELECT events.event, 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 AS distinct_id FROM person_distinct_id2