Skip to content

Commit e527bc4

Browse files
committed
fix(analytics): taking orderBy in query now
1 parent b47f89f commit e527bc4

5 files changed

Lines changed: 33 additions & 44 deletions

File tree

‎src/interface/storage/Storage.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { SerializedEvent, EventKind } from "../event/Event";
22
import { type UserId } from "../../config/identifiers";
33
import type { DateTime } from "luxon";
44
import type { AuthContext } from "../../context/auth";
5+
import type { OrderByRequest } from "../../zod/data";
56

67
export type QueryOperator = "EQ" | "GT" | "GTE" | "LT" | "LTE" | "NEQ";
78

@@ -54,6 +55,7 @@ export interface QueryRequest {
5455
groupBy?: string;
5556
limit?: number;
5657
offset?: number;
58+
orderBy?: OrderByRequest;
5759
}
5860

5961
export type QueryResultRow = Record<string, unknown>;

‎src/storage/adapter/common/clickHouseDialect.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ export class ClickHouseQueryDialect implements QueryDialect {
4747
});
4848

4949
let unionQuery = queries.join(" UNION ALL ");
50-
unionQuery += " ORDER BY reportedTimestamp DESC";
50+
const orderByField = request.orderBy?.field ?? "reportedTimestamp";
51+
const orderByDir = request.orderBy?.descending ? "DESC" : "ASC";
52+
53+
unionQuery += ` ORDER BY ${orderByField} ${orderByDir}`;
5154

5255
if (request.limit) {
5356
const limitParam = `p_${paramIndex.value++}`;

‎src/storage/adapter/common/postgresDialect.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ export class PostgresQueryDialect implements QueryDialect {
3737
});
3838

3939
const unionQuery = sql.join(subqueries, sql` UNION ALL `);
40+
const orderByField = request.orderBy?.field ?? "reportedTimestamp";
41+
const orderByDir = request.orderBy?.descending ? "DESC" : "ASC";
4042

4143
const finalQuery = sql`
4244
${unionQuery}
43-
ORDER BY "reportedTimestamp" DESC
45+
ORDER BY ${sql.raw(`"${orderByField}" ${orderByDir}`)}
4446
LIMIT ${request.limit ?? 100}
4547
OFFSET ${request.offset ?? 0}
4648
`;

‎src/storage/adapter/common/queryEventsBase.ts‎

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import type {
66
export type EventTypeLabel = "BASIC_USAGE" | "AI_TOKEN_USAGE" | "PAYMENT";
77

88
export type EventTableName =
9-
| "basic_usage_events"
10-
| "ai_token_usage_events"
11-
| "payment_events";
9+
"basic_usage_events" | "ai_token_usage_events" | "payment_events";
1210

1311
const EVENT_TYPE_TO_TABLE: Record<EventTypeLabel, EventTableName> = {
1412
BASIC_USAGE: "basic_usage_events",
@@ -43,50 +41,33 @@ export const OPERATOR_SQL: Record<string, string> = {
4341
NEQ: "!=",
4442
};
4543

46-
interface EventTypeFilter {
47-
operator: string;
48-
value: string;
49-
}
44+
function canTableMatch(
45+
group: QueryFilterGroup,
46+
table: EventTableName
47+
): boolean {
48+
const tableEventType = TABLE_TO_EVENT_TYPE[table];
5049

51-
function collectEventTypeFilters(group: QueryFilterGroup): EventTypeFilter[] {
52-
const filters: EventTypeFilter[] = [];
53-
for (const c of group.conditions) {
50+
const conditionResults = group.conditions.map((c) => {
5451
if (c.field === "eventType") {
55-
filters.push({ operator: c.operator, value: c.value });
52+
if (c.operator === "EQ") return c.value === tableEventType;
53+
if (c.operator === "NEQ") return c.value !== tableEventType;
54+
return true;
5655
}
57-
}
58-
for (const sub of group.groups) {
59-
filters.push(...collectEventTypeFilters(sub));
60-
}
61-
return filters;
62-
}
56+
return true;
57+
});
6358

64-
export function getTablesForRequest(where: QueryFilterGroup): EventTableName[] {
65-
const filters = collectEventTypeFilters(where);
66-
if (filters.length === 0) {
67-
return [...ALL_TABLES];
68-
}
59+
const groupResults = group.groups.map((g) => canTableMatch(g, table));
60+
const allResults = [...conditionResults, ...groupResults];
6961

70-
const included = new Set<EventTableName>();
71-
const excluded = new Set<EventTableName>();
62+
if (allResults.length === 0) return true;
7263

73-
for (const { operator, value } of filters) {
74-
if (!(value in EVENT_TYPE_TO_TABLE)) continue;
75-
const table = EVENT_TYPE_TO_TABLE[value as EventTypeLabel];
76-
if (operator === "EQ") {
77-
included.add(table);
78-
} else if (operator === "NEQ") {
79-
excluded.add(table);
80-
}
81-
}
82-
83-
if (included.size > 0) {
84-
return [...included];
85-
}
86-
87-
if (excluded.size > 0) {
88-
return ALL_TABLES.filter((t) => !excluded.has(t));
64+
if (group.logical === "AND") {
65+
return allResults.every((res) => res);
66+
} else {
67+
return allResults.some((res) => res);
8968
}
69+
}
9070

91-
return [];
71+
export function getTablesForRequest(where: QueryFilterGroup): EventTableName[] {
72+
return ALL_TABLES.filter((table) => canTableMatch(where, table));
9273
}

‎src/zod/data.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ const filterGroupSchema = createFilterGroupSchema(
3434
LOGICAL_MAP
3535
);
3636

37-
const orderBySchema = z.object({
37+
export const orderBySchema = z.object({
3838
field: z.string(),
3939
descending: z.boolean().default(false),
4040
});
41+
export type OrderByRequest = z.output<typeof orderBySchema>;
4142

4243
export const dataQuerySchema = z
4344
.object({

0 commit comments

Comments
 (0)