Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions packages/db/src/services/chart-sql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,22 @@ describe('chart.service / getChartSql', () => {
await explain(sql);
});

itCH(
'one_event_per_user + property breakdown resolves the events alias',
async () => {
const sql = await getChartSql({
event: event({ segment: 'one_event_per_user' }),
breakdowns: [breakdown('properties.linked')],
interval: 'day',
startDate: START,
endDate: END,
projectId: PROJECT_ID,
timezone: 'UTC',
});
await explain(sql);
},
);

// Regressions from HyperDX 2026-05-14 → 2026-05-17 ClickHouse error log.
// Saved reports / older clients send field names that don't match the events
// schema; the chart service used to inline them verbatim, crashing parse.
Expand Down Expand Up @@ -416,6 +432,39 @@ describe('chart.service / getAggregateChartSql', () => {
expect(sql).toContain("e.properties['__query.utm_source']");
await explain(sql);
});

itCH(
'one_event_per_user + group filter drops the out-of-scope WHERE',
async () => {
const sql = await getAggregateChartSql({
event: event({
segment: 'one_event_per_user',
filters: [{ name: 'group.plan', operator: 'is', value: ['pro'] }],
}),
breakdowns: [],
startDate: START,
endDate: END,
projectId: PROJECT_ID,
timezone: 'UTC',
});
await explain(sql);
},
);

itCH(
'one_event_per_user + property breakdown resolves the events alias',
async () => {
const sql = await getAggregateChartSql({
event: event({ segment: 'one_event_per_user' }),
breakdowns: [breakdown('properties.linked')],
startDate: START,
endDate: END,
projectId: PROJECT_ID,
timezone: 'UTC',
});
await explain(sql);
},
);
});

describe('overview.service / getRawWhereClause (UTM remapping)', () => {
Expand Down
17 changes: 12 additions & 5 deletions packages/db/src/services/chart.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,12 +817,13 @@ export async function getChartSql({
' AND '
)}
ORDER BY profile_id, created_at DESC
) as subQuery`;
) as e`;
sb.joins = {};
// Filters were already applied inside the subquery, and the outer query
// selects from `subQuery` — the `e` alias used in sb.where is no longer
// in scope, so re-emitting WHERE would produce
// "Unknown identifier `e.name`". Clear it.
// selects from the subquery aliased `e` — the `e` alias used in sb.where
// still resolves to it (the subquery does `SELECT * FROM events e`), but
// re-emitting WHERE here would just re-apply the same filters a second
// time. Clear it.
sb.where = {};

const sql = rewriteProfilePropertyRefs(
Expand Down Expand Up @@ -1166,8 +1167,14 @@ export async function getAggregateChartSql({
' AND '
)}
ORDER BY profile_id, created_at DESC
) as subQuery`;
) as e`;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
sb.joins = {};
// Filters were already applied inside the subquery. A profile or group
// filter's join (and any ARRAY JOIN alias like _group_id) is scoped to
// it and is gone now that sb.joins is cleared, so re-emitting WHERE here
// would produce "Unknown identifier `_group_id`"/`profile.*`. Clear it,
// matching getChartSql.
sb.where = {};

const sql = rewriteProfilePropertyRefs(getSql(), profileProps.keys);
console.log('-- Aggregate Chart --');
Expand Down