rowpipe 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -55
- package/dist/cli/commands/count.d.ts +12 -0
- package/dist/cli/commands/count.d.ts.map +1 -0
- package/dist/cli/commands/count.js +49 -0
- package/dist/cli/commands/count.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +3 -0
- package/dist/cli/commands/explain.d.ts.map +1 -0
- package/dist/cli/commands/explain.js +11 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/commands/files.d.ts +2 -1
- package/dist/cli/commands/files.d.ts.map +1 -1
- package/dist/cli/commands/files.js +5 -2
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/group.d.ts +12 -0
- package/dist/cli/commands/group.d.ts.map +1 -0
- package/dist/cli/commands/group.js +51 -0
- package/dist/cli/commands/group.js.map +1 -0
- package/dist/cli/commands/head.d.ts +7 -0
- package/dist/cli/commands/head.d.ts.map +1 -0
- package/dist/cli/commands/head.js +6 -0
- package/dist/cli/commands/head.js.map +1 -0
- package/dist/cli/commands/limit.d.ts +11 -0
- package/dist/cli/commands/limit.d.ts.map +1 -0
- package/dist/cli/commands/limit.js +40 -0
- package/dist/cli/commands/limit.js.map +1 -0
- package/dist/cli/commands/offset.d.ts +11 -0
- package/dist/cli/commands/offset.d.ts.map +1 -0
- package/dist/cli/commands/offset.js +39 -0
- package/dist/cli/commands/offset.js.map +1 -0
- package/dist/cli/commands/pipeline.d.ts +43 -0
- package/dist/cli/commands/pipeline.d.ts.map +1 -0
- package/dist/cli/commands/pipeline.js +198 -0
- package/dist/cli/commands/pipeline.js.map +1 -0
- package/dist/cli/commands/sort.d.ts +17 -0
- package/dist/cli/commands/sort.d.ts.map +1 -0
- package/dist/cli/commands/sort.js +55 -0
- package/dist/cli/commands/sort.js.map +1 -0
- package/dist/cli/commands/tail.d.ts +13 -0
- package/dist/cli/commands/tail.d.ts.map +1 -0
- package/dist/cli/commands/tail.js +39 -0
- package/dist/cli/commands/tail.js.map +1 -0
- package/dist/cli/commands/top.d.ts +19 -0
- package/dist/cli/commands/top.d.ts.map +1 -0
- package/dist/cli/commands/top.js +51 -0
- package/dist/cli/commands/top.js.map +1 -0
- package/dist/cli/commands/unique.d.ts +15 -0
- package/dist/cli/commands/unique.d.ts.map +1 -0
- package/dist/cli/commands/unique.js +44 -0
- package/dist/cli/commands/unique.js.map +1 -0
- package/dist/cli/index.js +252 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/core/pipeline.d.ts +40 -0
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +65 -0
- package/dist/core/pipeline.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/planner/executor.d.ts +8 -0
- package/dist/planner/executor.d.ts.map +1 -0
- package/dist/planner/executor.js +86 -0
- package/dist/planner/executor.js.map +1 -0
- package/dist/planner/explain.d.ts +6 -0
- package/dist/planner/explain.d.ts.map +1 -0
- package/dist/planner/explain.js +91 -0
- package/dist/planner/explain.js.map +1 -0
- package/dist/planner/index.d.ts +5 -0
- package/dist/planner/index.d.ts.map +1 -0
- package/dist/planner/index.js +5 -0
- package/dist/planner/index.js.map +1 -0
- package/dist/planner/optimizer.d.ts +9 -0
- package/dist/planner/optimizer.d.ts.map +1 -0
- package/dist/planner/optimizer.js +78 -0
- package/dist/planner/optimizer.js.map +1 -0
- package/dist/planner/types.d.ts +63 -0
- package/dist/planner/types.d.ts.map +1 -0
- package/dist/planner/types.js +2 -0
- package/dist/planner/types.js.map +1 -0
- package/dist/transforms/count.d.ts +21 -0
- package/dist/transforms/count.d.ts.map +1 -0
- package/dist/transforms/count.js +65 -0
- package/dist/transforms/count.js.map +1 -0
- package/dist/transforms/group.d.ts +25 -0
- package/dist/transforms/group.d.ts.map +1 -0
- package/dist/transforms/group.js +71 -0
- package/dist/transforms/group.js.map +1 -0
- package/dist/transforms/limit.d.ts +7 -0
- package/dist/transforms/limit.d.ts.map +1 -0
- package/dist/transforms/limit.js +40 -0
- package/dist/transforms/limit.js.map +1 -0
- package/dist/transforms/offset.d.ts +7 -0
- package/dist/transforms/offset.d.ts.map +1 -0
- package/dist/transforms/offset.js +38 -0
- package/dist/transforms/offset.js.map +1 -0
- package/dist/transforms/sort/comparator.d.ts +43 -0
- package/dist/transforms/sort/comparator.d.ts.map +1 -0
- package/dist/transforms/sort/comparator.js +131 -0
- package/dist/transforms/sort/comparator.js.map +1 -0
- package/dist/transforms/sort/external-sort.d.ts +8 -0
- package/dist/transforms/sort/external-sort.d.ts.map +1 -0
- package/dist/transforms/sort/external-sort.js +159 -0
- package/dist/transforms/sort/external-sort.js.map +1 -0
- package/dist/transforms/sort/index.d.ts +10 -0
- package/dist/transforms/sort/index.d.ts.map +1 -0
- package/dist/transforms/sort/index.js +11 -0
- package/dist/transforms/sort/index.js.map +1 -0
- package/dist/transforms/tail.d.ts +6 -0
- package/dist/transforms/tail.d.ts.map +1 -0
- package/dist/transforms/tail.js +27 -0
- package/dist/transforms/tail.js.map +1 -0
- package/dist/transforms/top.d.ts +17 -0
- package/dist/transforms/top.d.ts.map +1 -0
- package/dist/transforms/top.js +52 -0
- package/dist/transforms/top.js.map +1 -0
- package/dist/transforms/unique.d.ts +13 -0
- package/dist/transforms/unique.d.ts.map +1 -0
- package/dist/transforms/unique.js +91 -0
- package/dist/transforms/unique.js.map +1 -0
- package/dist/utils/heap.d.ts +25 -0
- package/dist/utils/heap.d.ts.map +1 -0
- package/dist/utils/heap.js +90 -0
- package/dist/utils/heap.js.map +1 -0
- package/dist/utils/keystore.d.ts +80 -0
- package/dist/utils/keystore.d.ts.map +1 -0
- package/dist/utils/keystore.js +217 -0
- package/dist/utils/keystore.js.map +1 -0
- package/dist/utils/ring-buffer.d.ts +15 -0
- package/dist/utils/ring-buffer.d.ts.map +1 -0
- package/dist/utils/ring-buffer.js +40 -0
- package/dist/utils/ring-buffer.js.map +1 -0
- package/package.json +3 -2
- package/skills/rowpipe/SKILL.md +9 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Limits the number of rows emitted to `maxCount` and cancels the upstream stream immediately.
|
|
3
|
+
* Zero memory overhead ($O(1)$) and true early cancellation.
|
|
4
|
+
*/
|
|
5
|
+
export function limitRows(maxCount) {
|
|
6
|
+
const limit = Math.max(0, maxCount);
|
|
7
|
+
return (stream) => {
|
|
8
|
+
return (async function* () {
|
|
9
|
+
if (limit === 0)
|
|
10
|
+
return;
|
|
11
|
+
let emitted = 0;
|
|
12
|
+
for await (const batch of stream) {
|
|
13
|
+
if (batch.rows.length === 0)
|
|
14
|
+
continue;
|
|
15
|
+
const remaining = limit - emitted;
|
|
16
|
+
if (remaining <= 0) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
if (batch.rows.length <= remaining) {
|
|
20
|
+
yield batch;
|
|
21
|
+
emitted += batch.rows.length;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// Slice partial batch to meet exact limit
|
|
25
|
+
const sliceRows = batch.rows.slice(0, remaining);
|
|
26
|
+
yield {
|
|
27
|
+
rows: sliceRows,
|
|
28
|
+
offset: batch.offset,
|
|
29
|
+
};
|
|
30
|
+
emitted += sliceRows.length;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
if (emitted >= limit) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
})();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limit.js","sourceRoot":"","sources":["../../src/transforms/limit.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAEpC,OAAO,CAAC,MAAkB,EAAc,EAAE;QACxC,OAAO,CAAC,KAAK,SAAS,CAAC;YACrB,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO;YAExB,IAAI,OAAO,GAAG,CAAC,CAAC;YAEhB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAEtC,MAAM,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC;gBAClC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;oBACnB,MAAM;gBACR,CAAC;gBAED,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;oBACnC,MAAM,KAAK,CAAC;oBACZ,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,0CAA0C;oBAC1C,MAAM,SAAS,GAAU,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;oBACxD,MAAM;wBACJ,IAAI,EAAE,SAAS;wBACf,MAAM,EAAE,KAAK,CAAC,MAAM;qBACrB,CAAC;oBACF,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC;oBAC5B,MAAM;gBACR,CAAC;gBAED,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;oBACrB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TransformFunction } from "../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Skips the first `skipCount` rows in the stream without buffering.
|
|
4
|
+
* Zero memory overhead ($O(1)$).
|
|
5
|
+
*/
|
|
6
|
+
export declare function offsetRows(skipCount: number): TransformFunction;
|
|
7
|
+
//# sourceMappingURL=offset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offset.d.ts","sourceRoot":"","sources":["../../src/transforms/offset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEtF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAqC/D"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skips the first `skipCount` rows in the stream without buffering.
|
|
3
|
+
* Zero memory overhead ($O(1)$).
|
|
4
|
+
*/
|
|
5
|
+
export function offsetRows(skipCount) {
|
|
6
|
+
const offsetToSkip = Math.max(0, skipCount);
|
|
7
|
+
return (stream) => {
|
|
8
|
+
return (async function* () {
|
|
9
|
+
if (offsetToSkip === 0) {
|
|
10
|
+
yield* stream;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let skipped = 0;
|
|
14
|
+
for await (const batch of stream) {
|
|
15
|
+
if (batch.rows.length === 0)
|
|
16
|
+
continue;
|
|
17
|
+
if (skipped < offsetToSkip) {
|
|
18
|
+
const remainingToSkip = offsetToSkip - skipped;
|
|
19
|
+
if (batch.rows.length <= remainingToSkip) {
|
|
20
|
+
skipped += batch.rows.length;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
// Partial batch skip
|
|
24
|
+
const remainingRows = batch.rows.slice(remainingToSkip);
|
|
25
|
+
skipped += remainingToSkip;
|
|
26
|
+
yield {
|
|
27
|
+
rows: remainingRows,
|
|
28
|
+
offset: batch.offset + remainingToSkip,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
yield batch;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=offset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offset.js","sourceRoot":"","sources":["../../src/transforms/offset.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAE5C,OAAO,CAAC,MAAkB,EAAc,EAAE;QACxC,OAAO,CAAC,KAAK,SAAS,CAAC;YACrB,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;gBACvB,KAAK,CAAC,CAAC,MAAM,CAAC;gBACd,OAAO;YACT,CAAC;YAED,IAAI,OAAO,GAAG,CAAC,CAAC;YAEhB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAEtC,IAAI,OAAO,GAAG,YAAY,EAAE,CAAC;oBAC3B,MAAM,eAAe,GAAG,YAAY,GAAG,OAAO,CAAC;oBAE/C,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC;wBACzC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;wBAC7B,SAAS;oBACX,CAAC;oBAED,qBAAqB;oBACrB,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;oBACxD,OAAO,IAAI,eAAe,CAAC;oBAE3B,MAAM;wBACJ,IAAI,EAAE,aAAa;wBACnB,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,eAAe;qBACvC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Row } from "../../core/types.js";
|
|
2
|
+
export interface SortKeySpec {
|
|
3
|
+
column: string;
|
|
4
|
+
direction?: "asc" | "desc";
|
|
5
|
+
nulls?: "first" | "last";
|
|
6
|
+
ignoreCase?: boolean;
|
|
7
|
+
natural?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface SortOptions {
|
|
10
|
+
by: string | string[] | SortKeySpec[];
|
|
11
|
+
nulls?: "first" | "last";
|
|
12
|
+
ignoreCase?: boolean;
|
|
13
|
+
natural?: boolean;
|
|
14
|
+
memoryLimit?: number | string;
|
|
15
|
+
tempDir?: string;
|
|
16
|
+
batchSize?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SequencedRow {
|
|
19
|
+
row: Row;
|
|
20
|
+
seq: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parses sort specifications from strings (e.g. "country,revenue:desc", "age:desc") or objects.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseSortSpecs(input: string | string[] | SortKeySpec[], defaults?: {
|
|
26
|
+
defaultDirection?: "asc" | "desc";
|
|
27
|
+
nulls?: "first" | "last";
|
|
28
|
+
ignoreCase?: boolean;
|
|
29
|
+
natural?: boolean;
|
|
30
|
+
}): SortKeySpec[];
|
|
31
|
+
/**
|
|
32
|
+
* Compares two primitive values with typed semantics (numbers, dates, booleans, strings).
|
|
33
|
+
*/
|
|
34
|
+
export declare function compareValues(a: unknown, b: unknown, spec: SortKeySpec): number;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a deterministic, multi-column, stable row comparator.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createRowComparator(specs: SortKeySpec[]): (a: SequencedRow, b: SequencedRow) => number;
|
|
39
|
+
/**
|
|
40
|
+
* Creates a raw Row comparator (without seq).
|
|
41
|
+
*/
|
|
42
|
+
export declare function createRawRowComparator(specs: SortKeySpec[]): (a: Row, b: Row) => number;
|
|
43
|
+
//# sourceMappingURL=comparator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparator.d.ts","sourceRoot":"","sources":["../../../src/transforms/sort/comparator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,EAAE,EACxC,QAAQ,GAAE;IACR,gBAAgB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,GACL,WAAW,EAAE,CA0Cf;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,OAAO,EACV,IAAI,EAAE,WAAW,GAChB,MAAM,CAkDR;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,MAAM,CAmBtG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,MAAM,CAcvF"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses sort specifications from strings (e.g. "country,revenue:desc", "age:desc") or objects.
|
|
3
|
+
*/
|
|
4
|
+
export function parseSortSpecs(input, defaults = {}) {
|
|
5
|
+
const fallbackDir = defaults.defaultDirection || "asc";
|
|
6
|
+
if (Array.isArray(input) && input.length > 0 && typeof input[0] === "object") {
|
|
7
|
+
return input.map((spec) => ({
|
|
8
|
+
...spec,
|
|
9
|
+
direction: spec.direction || fallbackDir,
|
|
10
|
+
nulls: spec.nulls || defaults.nulls || "last",
|
|
11
|
+
ignoreCase: spec.ignoreCase ?? defaults.ignoreCase ?? false,
|
|
12
|
+
natural: spec.natural ?? defaults.natural ?? false,
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
const rawSpecs = [];
|
|
16
|
+
if (typeof input === "string") {
|
|
17
|
+
rawSpecs.push(...input.split(",").map((s) => s.trim()).filter(Boolean));
|
|
18
|
+
}
|
|
19
|
+
else if (Array.isArray(input)) {
|
|
20
|
+
for (const item of input) {
|
|
21
|
+
if (typeof item === "string") {
|
|
22
|
+
rawSpecs.push(...item.split(",").map((s) => s.trim()).filter(Boolean));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return rawSpecs.map((spec) => {
|
|
27
|
+
const parts = spec.split(":");
|
|
28
|
+
const column = parts[0].trim();
|
|
29
|
+
let direction;
|
|
30
|
+
if (parts[1]) {
|
|
31
|
+
const dirStr = parts[1].trim().toLowerCase();
|
|
32
|
+
direction = dirStr === "desc" ? "desc" : "asc";
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
direction = fallbackDir;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
column,
|
|
39
|
+
direction,
|
|
40
|
+
nulls: defaults.nulls || "last",
|
|
41
|
+
ignoreCase: defaults.ignoreCase ?? false,
|
|
42
|
+
natural: defaults.natural ?? false,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Compares two primitive values with typed semantics (numbers, dates, booleans, strings).
|
|
48
|
+
*/
|
|
49
|
+
export function compareValues(a, b, spec) {
|
|
50
|
+
const isANull = a === null || a === undefined || a === "";
|
|
51
|
+
const isBNull = b === null || b === undefined || b === "";
|
|
52
|
+
if (isANull && isBNull)
|
|
53
|
+
return 0;
|
|
54
|
+
if (isANull)
|
|
55
|
+
return spec.nulls === "first" ? -1 : 1;
|
|
56
|
+
if (isBNull)
|
|
57
|
+
return spec.nulls === "first" ? 1 : -1;
|
|
58
|
+
// Number comparison (including numeric strings)
|
|
59
|
+
const isANum = typeof a === "number" || (typeof a === "string" && /^-?\d+(\.\d+)?$/.test(a.trim()));
|
|
60
|
+
const isBNum = typeof b === "number" || (typeof b === "string" && /^-?\d+(\.\d+)?$/.test(b.trim()));
|
|
61
|
+
if (isANum && isBNum) {
|
|
62
|
+
const numA = typeof a === "number" ? a : Number.parseFloat(a);
|
|
63
|
+
const numB = typeof b === "number" ? b : Number.parseFloat(b);
|
|
64
|
+
if (!Number.isNaN(numA) && !Number.isNaN(numB)) {
|
|
65
|
+
return numA < numB ? -1 : numA > numB ? 1 : 0;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Boolean comparison
|
|
69
|
+
if (typeof a === "boolean" || typeof b === "boolean") {
|
|
70
|
+
const boolA = Boolean(a);
|
|
71
|
+
const boolB = Boolean(b);
|
|
72
|
+
return boolA === boolB ? 0 : boolA ? 1 : -1;
|
|
73
|
+
}
|
|
74
|
+
// Date comparison
|
|
75
|
+
if (a instanceof Date && b instanceof Date) {
|
|
76
|
+
return a.getTime() - b.getTime();
|
|
77
|
+
}
|
|
78
|
+
// String comparison
|
|
79
|
+
const strA = String(a);
|
|
80
|
+
const strB = String(b);
|
|
81
|
+
if (spec.natural) {
|
|
82
|
+
return strA.localeCompare(strB, undefined, {
|
|
83
|
+
numeric: true,
|
|
84
|
+
sensitivity: spec.ignoreCase ? "base" : "variant",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (spec.ignoreCase) {
|
|
88
|
+
const lowerA = strA.toLowerCase();
|
|
89
|
+
const lowerB = strB.toLowerCase();
|
|
90
|
+
return lowerA < lowerB ? -1 : lowerA > lowerB ? 1 : 0;
|
|
91
|
+
}
|
|
92
|
+
return strA < strB ? -1 : strA > strB ? 1 : 0;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates a deterministic, multi-column, stable row comparator.
|
|
96
|
+
*/
|
|
97
|
+
export function createRowComparator(specs) {
|
|
98
|
+
return (aObj, bObj) => {
|
|
99
|
+
const a = aObj.row;
|
|
100
|
+
const b = bObj.row;
|
|
101
|
+
for (let i = 0; i < specs.length; i++) {
|
|
102
|
+
const spec = specs[i];
|
|
103
|
+
const valA = a[spec.column];
|
|
104
|
+
const valB = b[spec.column];
|
|
105
|
+
const cmp = compareValues(valA, valB, spec);
|
|
106
|
+
if (cmp !== 0) {
|
|
107
|
+
return spec.direction === "desc" ? -cmp : cmp;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Preserve original insertion sequence for stability
|
|
111
|
+
return aObj.seq - bObj.seq;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Creates a raw Row comparator (without seq).
|
|
116
|
+
*/
|
|
117
|
+
export function createRawRowComparator(specs) {
|
|
118
|
+
return (a, b) => {
|
|
119
|
+
for (let i = 0; i < specs.length; i++) {
|
|
120
|
+
const spec = specs[i];
|
|
121
|
+
const valA = a[spec.column];
|
|
122
|
+
const valB = b[spec.column];
|
|
123
|
+
const cmp = compareValues(valA, valB, spec);
|
|
124
|
+
if (cmp !== 0) {
|
|
125
|
+
return spec.direction === "desc" ? -cmp : cmp;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return 0;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=comparator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparator.js","sourceRoot":"","sources":["../../../src/transforms/sort/comparator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TransformFunction } from "../../core/types.js";
|
|
2
|
+
import { SortOptions } from "./comparator.js";
|
|
3
|
+
/**
|
|
4
|
+
* External Merge Sort Engine.
|
|
5
|
+
* Sorts arbitrary-scale datasets with bounded RAM and K-Way Heap merge.
|
|
6
|
+
*/
|
|
7
|
+
export declare function externalSort(options: SortOptions): TransformFunction;
|
|
8
|
+
//# sourceMappingURL=external-sort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-sort.d.ts","sourceRoot":"","sources":["../../../src/transforms/sort/external-sort.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAA8B,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAIL,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAQzB;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,CAwKpE"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { createReadStream, createWriteStream, promises as fsPromises } from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import * as readline from "node:readline";
|
|
5
|
+
import { parseMemoryLimit } from "../../diff/storage/spillable-index.js";
|
|
6
|
+
import { Heap } from "../../utils/heap.js";
|
|
7
|
+
import { createRowComparator, parseSortSpecs, } from "./comparator.js";
|
|
8
|
+
/**
|
|
9
|
+
* External Merge Sort Engine.
|
|
10
|
+
* Sorts arbitrary-scale datasets with bounded RAM and K-Way Heap merge.
|
|
11
|
+
*/
|
|
12
|
+
export function externalSort(options) {
|
|
13
|
+
const specs = parseSortSpecs(options.by, {
|
|
14
|
+
nulls: options.nulls,
|
|
15
|
+
ignoreCase: options.ignoreCase,
|
|
16
|
+
natural: options.natural,
|
|
17
|
+
});
|
|
18
|
+
const rowComparator = createRowComparator(specs);
|
|
19
|
+
const memoryLimitBytes = parseMemoryLimit(options.memoryLimit, 256 * 1024 * 1024);
|
|
20
|
+
const effectiveBatchSize = options.batchSize || 1000;
|
|
21
|
+
const baseTempDir = options.tempDir || os.tmpdir();
|
|
22
|
+
return (stream) => {
|
|
23
|
+
return (async function* () {
|
|
24
|
+
let currentRun = [];
|
|
25
|
+
let currentRunBytes = 0;
|
|
26
|
+
let totalSeq = 0;
|
|
27
|
+
const runFiles = [];
|
|
28
|
+
const sessionDir = path.join(baseTempDir, `rowpipe-sort-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
29
|
+
const cleanup = async () => {
|
|
30
|
+
try {
|
|
31
|
+
await fsPromises.rm(sessionDir, { recursive: true, force: true });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Ignore temp cleanup error
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
for await (const batch of stream) {
|
|
39
|
+
for (let i = 0; i < batch.rows.length; i++) {
|
|
40
|
+
const row = batch.rows[i];
|
|
41
|
+
currentRun.push({ row, seq: totalSeq++ });
|
|
42
|
+
// Estimate row memory (~64 bytes overhead + keys/values)
|
|
43
|
+
currentRunBytes += 64 + Object.keys(row).length * 24;
|
|
44
|
+
if (currentRunBytes >= memoryLimitBytes) {
|
|
45
|
+
// Spill current run
|
|
46
|
+
await fsPromises.mkdir(sessionDir, { recursive: true });
|
|
47
|
+
currentRun.sort(rowComparator);
|
|
48
|
+
const runFilePath = path.join(sessionDir, `run_${runFiles.length}.jsonl`);
|
|
49
|
+
const writeStream = createWriteStream(runFilePath, { encoding: "utf-8" });
|
|
50
|
+
for (let r = 0; r < currentRun.length; r++) {
|
|
51
|
+
const item = currentRun[r];
|
|
52
|
+
writeStream.write(JSON.stringify({ row: item.row, seq: item.seq }) + "\n");
|
|
53
|
+
}
|
|
54
|
+
await new Promise((resolve, reject) => {
|
|
55
|
+
writeStream.end((err) => {
|
|
56
|
+
if (err)
|
|
57
|
+
reject(err);
|
|
58
|
+
else
|
|
59
|
+
resolve();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
runFiles.push(runFilePath);
|
|
63
|
+
currentRun = [];
|
|
64
|
+
currentRunBytes = 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Case 1: All data fit in memory without spilling
|
|
69
|
+
if (runFiles.length === 0) {
|
|
70
|
+
currentRun.sort(rowComparator);
|
|
71
|
+
let offset = 0;
|
|
72
|
+
for (let i = 0; i < currentRun.length; i += effectiveBatchSize) {
|
|
73
|
+
const slice = currentRun.slice(i, i + effectiveBatchSize).map((item) => item.row);
|
|
74
|
+
yield {
|
|
75
|
+
rows: slice,
|
|
76
|
+
offset,
|
|
77
|
+
};
|
|
78
|
+
offset += slice.length;
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Case 2: Spill remainder run if any rows are in memory
|
|
83
|
+
if (currentRun.length > 0) {
|
|
84
|
+
await fsPromises.mkdir(sessionDir, { recursive: true });
|
|
85
|
+
currentRun.sort(rowComparator);
|
|
86
|
+
const runFilePath = path.join(sessionDir, `run_${runFiles.length}.jsonl`);
|
|
87
|
+
const writeStream = createWriteStream(runFilePath, { encoding: "utf-8" });
|
|
88
|
+
for (let r = 0; r < currentRun.length; r++) {
|
|
89
|
+
const item = currentRun[r];
|
|
90
|
+
writeStream.write(JSON.stringify({ row: item.row, seq: item.seq }) + "\n");
|
|
91
|
+
}
|
|
92
|
+
await new Promise((resolve, reject) => {
|
|
93
|
+
writeStream.end((err) => {
|
|
94
|
+
if (err)
|
|
95
|
+
reject(err);
|
|
96
|
+
else
|
|
97
|
+
resolve();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
runFiles.push(runFilePath);
|
|
101
|
+
currentRun = [];
|
|
102
|
+
currentRunBytes = 0;
|
|
103
|
+
}
|
|
104
|
+
// Case 3: K-Way Merge using Min-Heap
|
|
105
|
+
const k = runFiles.length;
|
|
106
|
+
const iterators = new Array(k);
|
|
107
|
+
for (let i = 0; i < k; i++) {
|
|
108
|
+
const rl = readline.createInterface({
|
|
109
|
+
input: createReadStream(runFiles[i], { encoding: "utf-8" }),
|
|
110
|
+
crlfDelay: Infinity,
|
|
111
|
+
});
|
|
112
|
+
iterators[i] = rl[Symbol.asyncIterator]();
|
|
113
|
+
}
|
|
114
|
+
const heapComparator = (a, b) => {
|
|
115
|
+
return rowComparator({ row: a.row, seq: a.seq }, { row: b.row, seq: b.seq });
|
|
116
|
+
};
|
|
117
|
+
const heap = new Heap(heapComparator);
|
|
118
|
+
// Prime the heap with 1 item from each run
|
|
119
|
+
for (let i = 0; i < k; i++) {
|
|
120
|
+
const next = await iterators[i].next();
|
|
121
|
+
if (!next.done && next.value.trim().length > 0) {
|
|
122
|
+
const parsed = JSON.parse(next.value);
|
|
123
|
+
heap.push({ row: parsed.row, seq: parsed.seq, runIndex: i });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
let outputRows = [];
|
|
127
|
+
let globalOffset = 0;
|
|
128
|
+
while (!heap.isEmpty()) {
|
|
129
|
+
const smallest = heap.pop();
|
|
130
|
+
outputRows.push(smallest.row);
|
|
131
|
+
if (outputRows.length >= effectiveBatchSize) {
|
|
132
|
+
yield {
|
|
133
|
+
rows: outputRows,
|
|
134
|
+
offset: globalOffset,
|
|
135
|
+
};
|
|
136
|
+
globalOffset += outputRows.length;
|
|
137
|
+
outputRows = [];
|
|
138
|
+
}
|
|
139
|
+
// Advance iterator for smallest.runIndex
|
|
140
|
+
const next = await iterators[smallest.runIndex].next();
|
|
141
|
+
if (!next.done && next.value.trim().length > 0) {
|
|
142
|
+
const parsed = JSON.parse(next.value);
|
|
143
|
+
heap.push({ row: parsed.row, seq: parsed.seq, runIndex: smallest.runIndex });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (outputRows.length > 0) {
|
|
147
|
+
yield {
|
|
148
|
+
rows: outputRows,
|
|
149
|
+
offset: globalOffset,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
await cleanup();
|
|
155
|
+
}
|
|
156
|
+
})();
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=external-sort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-sort.js","sourceRoot":"","sources":["../../../src/transforms/sort/external-sort.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TransformFunction } from "../../core/types.js";
|
|
2
|
+
import type { SortOptions } from "./comparator.js";
|
|
3
|
+
export * from "./comparator.js";
|
|
4
|
+
export * from "./external-sort.js";
|
|
5
|
+
/**
|
|
6
|
+
* Sorts tabular stream by one or more columns with typed comparisons,
|
|
7
|
+
* stable ordering, and automatic external merge sort on large streams.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sortRows(options: SortOptions): TransformFunction;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transforms/sort/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAEnC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,iBAAiB,CAEhE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { externalSort } from "./external-sort.js";
|
|
2
|
+
export * from "./comparator.js";
|
|
3
|
+
export * from "./external-sort.js";
|
|
4
|
+
/**
|
|
5
|
+
* Sorts tabular stream by one or more columns with typed comparisons,
|
|
6
|
+
* stable ordering, and automatic external merge sort on large streams.
|
|
7
|
+
*/
|
|
8
|
+
export function sortRows(options) {
|
|
9
|
+
return externalSort(options);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transforms/sort/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAoB;IAC3C,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TransformFunction } from "../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Retains and emits only the last `count` rows of a stream using a bounded O(N) Ring Buffer.
|
|
4
|
+
*/
|
|
5
|
+
export declare function tailRows(count?: number): TransformFunction;
|
|
6
|
+
//# sourceMappingURL=tail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tail.d.ts","sourceRoot":"","sources":["../../src/transforms/tail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGtF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAK,GAAG,iBAAiB,CAwBtD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RingBuffer } from "../utils/ring-buffer.js";
|
|
2
|
+
/**
|
|
3
|
+
* Retains and emits only the last `count` rows of a stream using a bounded O(N) Ring Buffer.
|
|
4
|
+
*/
|
|
5
|
+
export function tailRows(count = 10) {
|
|
6
|
+
const tailCount = Math.max(1, count);
|
|
7
|
+
return (stream) => {
|
|
8
|
+
return (async function* () {
|
|
9
|
+
const ringBuffer = new RingBuffer(tailCount);
|
|
10
|
+
let totalRowsSeen = 0;
|
|
11
|
+
for await (const batch of stream) {
|
|
12
|
+
for (let i = 0; i < batch.rows.length; i++) {
|
|
13
|
+
ringBuffer.push(batch.rows[i]);
|
|
14
|
+
totalRowsSeen++;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (ringBuffer.size > 0) {
|
|
18
|
+
const rows = ringBuffer.toArray();
|
|
19
|
+
yield {
|
|
20
|
+
rows,
|
|
21
|
+
offset: Math.max(0, totalRowsSeen - rows.length),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
})();
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=tail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tail.js","sourceRoot":"","sources":["../../src/transforms/tail.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAK,GAAG,EAAE;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAErC,OAAO,CAAC,MAAkB,EAAc,EAAE;QACxC,OAAO,CAAC,KAAK,SAAS,CAAC;YACrB,MAAM,UAAU,GAAG,IAAI,UAAU,CAAM,SAAS,CAAC,CAAC;YAClD,IAAI,aAAa,GAAG,CAAC,CAAC;YAEtB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3C,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;oBAChC,aAAa,EAAE,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM;oBACJ,IAAI;oBACJ,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;iBACjD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TransformFunction } from "../core/types.js";
|
|
2
|
+
import { SortKeySpec } from "./sort/comparator.js";
|
|
3
|
+
export interface TopOptions {
|
|
4
|
+
by: string | string[] | SortKeySpec[];
|
|
5
|
+
count?: number;
|
|
6
|
+
order?: "asc" | "desc";
|
|
7
|
+
smallest?: boolean;
|
|
8
|
+
nulls?: "first" | "last";
|
|
9
|
+
ignoreCase?: boolean;
|
|
10
|
+
natural?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Retains only the Top-K (or Bottom-K) rows using a bounded O(K) Binary Heap.
|
|
14
|
+
* Time complexity: O(N * log K), Memory complexity: O(K).
|
|
15
|
+
*/
|
|
16
|
+
export declare function topRows(options: TopOptions): TransformFunction;
|
|
17
|
+
//# sourceMappingURL=top.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"top.d.ts","sourceRoot":"","sources":["../../src/transforms/top.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA8B,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEtF,OAAO,EAGL,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CAkD9D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Heap } from "../utils/heap.js";
|
|
2
|
+
import { createRawRowComparator, parseSortSpecs, } from "./sort/comparator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Retains only the Top-K (or Bottom-K) rows using a bounded O(K) Binary Heap.
|
|
5
|
+
* Time complexity: O(N * log K), Memory complexity: O(K).
|
|
6
|
+
*/
|
|
7
|
+
export function topRows(options) {
|
|
8
|
+
const k = Math.max(1, options.count ?? 10);
|
|
9
|
+
const isSmallest = options.smallest || options.order === "asc";
|
|
10
|
+
const defaultDirection = isSmallest ? "asc" : "desc";
|
|
11
|
+
const rawSpecs = parseSortSpecs(options.by, {
|
|
12
|
+
defaultDirection,
|
|
13
|
+
nulls: options.nulls,
|
|
14
|
+
ignoreCase: options.ignoreCase,
|
|
15
|
+
natural: options.natural,
|
|
16
|
+
});
|
|
17
|
+
// Desired output comparator: desiredComparator(a, b) < 0 means 'a' comes before 'b'
|
|
18
|
+
const desiredComparator = createRawRowComparator(rawSpecs);
|
|
19
|
+
return (stream) => {
|
|
20
|
+
return (async function* () {
|
|
21
|
+
// Min-Heap where root is the LEAST preferred element among current top K
|
|
22
|
+
// If desiredComparator(a, b) > 0 ('a' is worse than 'b'), then heapComparator(a, b) < 0 (floats to root)
|
|
23
|
+
const heapComparator = (a, b) => -desiredComparator(a, b);
|
|
24
|
+
const heap = new Heap(heapComparator);
|
|
25
|
+
for await (const batch of stream) {
|
|
26
|
+
for (let i = 0; i < batch.rows.length; i++) {
|
|
27
|
+
const row = batch.rows[i];
|
|
28
|
+
if (heap.size < k) {
|
|
29
|
+
heap.push(row);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const worst = heap.peek();
|
|
33
|
+
// If incoming row is more preferred than the current worst, replace it
|
|
34
|
+
if (desiredComparator(row, worst) < 0) {
|
|
35
|
+
heap.replace(row);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Drain and sort results in exact desired comparator order
|
|
41
|
+
const drained = heap.drain();
|
|
42
|
+
drained.sort(desiredComparator);
|
|
43
|
+
if (drained.length > 0) {
|
|
44
|
+
yield {
|
|
45
|
+
rows: drained,
|
|
46
|
+
offset: 0,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=top.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"top.js","sourceRoot":"","sources":["../../src/transforms/top.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EACL,sBAAsB,EACtB,cAAc,GAEf,MAAM,sBAAsB,CAAC;AAY9B;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,OAAmB;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC;IAC/D,MAAM,gBAAgB,GAAmB,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAErE,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE;QAC1C,gBAAgB;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IAEH,oFAAoF;IACpF,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAE3D,OAAO,CAAC,MAAkB,EAAc,EAAE;QACxC,OAAO,CAAC,KAAK,SAAS,CAAC;YACrB,yEAAyE;YACzE,yGAAyG;YACzG,MAAM,cAAc,GAAG,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAM,cAAc,CAAC,CAAC;YAE3C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;oBAE3B,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;wBAClB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACjB,CAAC;yBAAM,CAAC;wBACN,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAG,CAAC;wBAC3B,uEAAuE;wBACvE,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;4BACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;wBACpB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,2DAA2D;YAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAEhC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM;oBACJ,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,CAAC;iBACV,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,CAAC;AACJ,CAAC"}
|