@gscdump/engine-duckdb-wasm 0.25.4 → 0.25.6
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/dist/index.d.mts +11 -0
- package/dist/index.mjs +32 -8
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -105,6 +105,17 @@ interface OpfsParquetTable {
|
|
|
105
105
|
/** Iceberg table name — becomes the DuckDB view name. */
|
|
106
106
|
table: string;
|
|
107
107
|
files: OpfsParquetFile[];
|
|
108
|
+
/**
|
|
109
|
+
* Recent-window overlay parquet (the non-stable tail the lake excludes). When
|
|
110
|
+
* present it is materialised into OPFS alongside `files` and the view unions
|
|
111
|
+
* it with an anti-join dedup: the lake (`files`) serves every day it has, the
|
|
112
|
+
* overlay serves ONLY days the lake lacks. So a stale overlay whose days have
|
|
113
|
+
* since landed in the lake can't double-count, and a day that stabilised but
|
|
114
|
+
* isn't yet in the lake still serves from the overlay. Its `contentHash` must
|
|
115
|
+
* change when the overlay bytes change (it is overwritten in place) so the
|
|
116
|
+
* cache re-downloads.
|
|
117
|
+
*/
|
|
118
|
+
overlay?: OpfsParquetFile;
|
|
108
119
|
}
|
|
109
120
|
interface AttachOpfsTablesOptions {
|
|
110
121
|
db: AsyncDuckDB;
|
package/dist/index.mjs
CHANGED
|
@@ -540,8 +540,19 @@ async function materialiseFile(root, name, staleSweepPrefix, file, fetchImpl, fe
|
|
|
540
540
|
outcome: "downloaded"
|
|
541
541
|
};
|
|
542
542
|
}
|
|
543
|
+
function quoteList(files) {
|
|
544
|
+
return files.map((f) => `'${f.replace(/'/g, "''")}'`).join(", ");
|
|
545
|
+
}
|
|
546
|
+
function lakeSelect(files) {
|
|
547
|
+
return `SELECT * REPLACE (CAST(date AS DATE) AS date) FROM read_parquet([${quoteList(files)}], union_by_name = true)`;
|
|
548
|
+
}
|
|
543
549
|
function readParquetViewSql$1(schema, table, files) {
|
|
544
|
-
return `CREATE OR REPLACE VIEW ${schema}.${table} AS
|
|
550
|
+
return `CREATE OR REPLACE VIEW ${schema}.${table} AS ${lakeSelect(files)}`;
|
|
551
|
+
}
|
|
552
|
+
function readParquetViewWithOverlaySql(schema, table, lakeFiles, overlayFile) {
|
|
553
|
+
const overlay = `SELECT * REPLACE (CAST(date AS DATE) AS date) FROM read_parquet(['${overlayFile.replace(/'/g, "''")}'], union_by_name = true)`;
|
|
554
|
+
if (lakeFiles.length === 0) return `CREATE OR REPLACE VIEW ${schema}.${table} AS ${overlay}`;
|
|
555
|
+
return `CREATE OR REPLACE VIEW ${schema}.${table} AS ${lakeSelect(lakeFiles)} UNION ALL BY NAME ${overlay} WHERE CAST(date AS DATE) NOT IN (SELECT DISTINCT CAST(date AS DATE) FROM read_parquet([${quoteList(lakeFiles)}], union_by_name = true))`;
|
|
545
556
|
}
|
|
546
557
|
async function runWithConcurrency$1(items, concurrency, fn) {
|
|
547
558
|
let next = 0;
|
|
@@ -564,12 +575,22 @@ async function attachOpfsParquetTables(options) {
|
|
|
564
575
|
await requestPersistentStorage();
|
|
565
576
|
const root = await getOpfsRoot();
|
|
566
577
|
const flat = [];
|
|
567
|
-
for (const t of tables)
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
578
|
+
for (const t of tables) {
|
|
579
|
+
for (let i = 0; i < t.files.length; i++) flat.push({
|
|
580
|
+
table: t.table,
|
|
581
|
+
file: t.files[i],
|
|
582
|
+
fileIndex: i
|
|
583
|
+
});
|
|
584
|
+
if (t.overlay) flat.push({
|
|
585
|
+
table: t.table,
|
|
586
|
+
file: t.overlay,
|
|
587
|
+
fileIndex: t.files.length,
|
|
588
|
+
overlay: true
|
|
589
|
+
});
|
|
590
|
+
}
|
|
572
591
|
const total = flat.length;
|
|
592
|
+
const overlayNames = /* @__PURE__ */ new Map();
|
|
593
|
+
const expectedCount = new Map(tables.map((t) => [t.table, t.files.length + (t.overlay ? 1 : 0)]));
|
|
573
594
|
const { DuckDBDataProtocol } = await import("@duckdb/duckdb-wasm");
|
|
574
595
|
const registry = getOpfsRegistry(db, DuckDBDataProtocol.BROWSER_FSACCESS);
|
|
575
596
|
const tableFiles = /* @__PURE__ */ new Map();
|
|
@@ -615,6 +636,7 @@ async function attachOpfsParquetTables(options) {
|
|
|
615
636
|
handle: result.handle
|
|
616
637
|
});
|
|
617
638
|
tableFiles.set(item.table, list);
|
|
639
|
+
if (item.overlay) overlayNames.set(item.table, name);
|
|
618
640
|
bytesAttached += item.file.bytes;
|
|
619
641
|
onFileProgress?.({
|
|
620
642
|
table: item.table,
|
|
@@ -639,14 +661,16 @@ async function attachOpfsParquetTables(options) {
|
|
|
639
661
|
continue;
|
|
640
662
|
}
|
|
641
663
|
const files = tableFiles.get(t.table) ?? [];
|
|
642
|
-
if (files.length !== t.files.length) {
|
|
664
|
+
if (files.length !== (expectedCount.get(t.table) ?? t.files.length)) {
|
|
643
665
|
degraded.add(t.table);
|
|
644
666
|
await releaseTable(t.table);
|
|
645
667
|
continue;
|
|
646
668
|
}
|
|
669
|
+
const overlayName = overlayNames.get(t.table);
|
|
670
|
+
const lakeNames = overlayName ? files.map((f) => f.name).filter((n) => n !== overlayName) : files.map((f) => f.name);
|
|
647
671
|
try {
|
|
648
672
|
signal?.throwIfAborted();
|
|
649
|
-
await conn.query(
|
|
673
|
+
await conn.query(overlayName ? readParquetViewWithOverlaySql(schema, t.table, lakeNames, overlayName) : readParquetViewSql$1(schema, t.table, lakeNames));
|
|
650
674
|
} catch (err) {
|
|
651
675
|
if (isAbortError$1(err)) {
|
|
652
676
|
await detachOpfs(registry, conn, schema, attached, [...acquiredNames]).catch(() => {});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/engine-duckdb-wasm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.25.
|
|
4
|
+
"version": "0.25.6",
|
|
5
5
|
"description": "DuckDB-WASM engine adapter for @gscdump/analysis — typed browser analytics against parquet via R2.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"drizzle-orm": "1.0.0-rc.3",
|
|
48
|
-
"@gscdump/engine": "0.25.
|
|
49
|
-
"@gscdump/sdk": "0.25.
|
|
50
|
-
"gscdump": "0.25.
|
|
48
|
+
"@gscdump/engine": "0.25.6",
|
|
49
|
+
"@gscdump/sdk": "0.25.6",
|
|
50
|
+
"gscdump": "0.25.6"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@duckdb/duckdb-wasm": "^1.32.0",
|