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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/fumadb/src/adapters/drizzle/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ export function fromDrizzle(
);
}
if (filter.kind === "or") {
if (filter.items.length === 0) return Drizzle.sql`1 = 0`;
return Drizzle.or(
...filter.items.map((item) => buildJsonFilter(jsonColumn, item)),
);
Expand Down
18 changes: 18 additions & 0 deletions packages/core/fumadb/src/query/aggregate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ const runSuite = (name: string, makeHarness: () => Promise<Harness>) => {
).toBe(2);
});

it("matches empty composite filter semantics", async () => {
const { orm } = harness;
expect(
await orm.jsonCount("events", {
column: "data",
where: inT1,
filter: { kind: "or", items: [] },
}),
).toBe(0);
expect(
await orm.jsonCount("events", {
column: "data",
where: inT1,
filter: { kind: "and", items: [] },
}),
).toBe(4);
});

it("jsonGroupCount counts distinct values", async () => {
const rows = await harness.orm.jsonGroupCount("events", {
column: "data",
Expand Down
15 changes: 14 additions & 1 deletion packages/core/fumadb/src/query/aggregate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ export interface JsonTimeBucketRow {
export interface JsonStatsAdapterOptions extends JsonAdapterBase {
/** Numeric path the stats are computed over. */
readonly path: JsonPath;
/** Percentile fractions in [0, 1] (e.g. 0.5, 0.95). */
/**
* Percentile fractions in [0, 1] (e.g. 0.5, 0.95).
*
* SQLite adapters compute percentiles from all matching numeric values after
* projection because SQLite has no native percentile aggregate. Count, min,
* and max still run as SQL aggregates.
*/
readonly percentiles?: readonly number[];
}

Expand Down Expand Up @@ -155,6 +161,13 @@ export interface JsonTimeBucketOptions<TColumns extends Record<string, AnyColumn
export interface JsonStatsOptions<TColumns extends Record<string, AnyColumn>>
extends JsonPublicBase<TColumns> {
readonly path: JsonPath;
/**
* Percentile fractions in [0, 1] (e.g. 0.5, 0.95).
*
* SQLite adapters compute percentiles from all matching numeric values after
* projection because SQLite has no native percentile aggregate. Count, min,
* and max still run as SQL aggregates.
*/
readonly percentiles?: readonly number[];
}

Expand Down
25 changes: 16 additions & 9 deletions packages/core/sdk/src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
withQueryContext,
type Condition,
type ConditionBuilder,
type JsonCompareOperator,
type JsonFilter,
type JsonGroupCountRow,
type JsonKeysetCursor,
Expand Down Expand Up @@ -1115,6 +1116,17 @@ const isPluginStorageRecord = (value: unknown): value is Readonly<Record<string,

const pluginStorageWhereOperators = ["eq", "in", "gt", "gte", "lt", "lte"] as const;

const pluginStorageJsonCompareOperators = {
eq: "=",
gt: ">",
gte: ">=",
lt: "<",
lte: "<=",
} satisfies Record<
Exclude<(typeof pluginStorageWhereOperators)[number], "in">,
JsonCompareOperator
>;

const isPluginStorageWhereFilter = (value: unknown): value is Readonly<Record<string, unknown>> =>
isPluginStorageRecord(value) && pluginStorageWhereOperators.some((operator) => operator in value);

Expand Down Expand Up @@ -1211,16 +1223,11 @@ const pluginStorageWhereToJsonFilter = (
});
continue;
}
if (!(operator in pluginStorageJsonCompareOperators)) continue;
const compareOperator =
operator === "gt"
? ">"
: operator === "gte"
? ">="
: operator === "lt"
? "<"
: operator === "lte"
? "<="
: "=";
pluginStorageJsonCompareOperators[
operator as keyof typeof pluginStorageJsonCompareOperators
];
items.push({
kind: "compare",
path,
Expand Down
8 changes: 7 additions & 1 deletion packages/core/sdk/src/plugin-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,13 @@ export interface PluginStorageStatsInput<
> extends PluginStorageAggregateFilter<TDefinition> {
/** Numeric field the stats are computed over. */
readonly field: PluginStorageCollectionIndexedField<TDefinition>;
/** Percentile fractions in [0, 1] (e.g. 0.5, 0.95). */
/**
* Percentile fractions in [0, 1] (e.g. 0.5, 0.95).
*
* SQLite-backed storage computes percentiles from all matching numeric values
* after projection because SQLite has no native percentile aggregate. Count,
* min, and max still run as SQL aggregates.
*/
readonly percentiles?: readonly number[];
}

Expand Down
Loading