@sixb/ducklake 0.1.8 → 0.2.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.
Files changed (69) hide show
  1. package/README.md +59 -4
  2. package/dist/ducklake-storage.d.ts +1 -0
  3. package/dist/ducklake-storage.d.ts.map +1 -1
  4. package/dist/index.js +1817 -511
  5. package/dist/index.js.map +24 -14
  6. package/dist/internal/dataset-row-commit.d.ts +10 -0
  7. package/dist/internal/dataset-row-commit.d.ts.map +1 -1
  8. package/dist/internal/dataset-row-merge.d.ts.map +1 -1
  9. package/dist/internal/ducklake-dataset-catalog.d.ts +20 -3
  10. package/dist/internal/ducklake-dataset-catalog.d.ts.map +1 -1
  11. package/dist/internal/ducklake-dataset-table-ref.d.ts +13 -0
  12. package/dist/internal/ducklake-dataset-table-ref.d.ts.map +1 -1
  13. package/dist/internal/ducklake-maintenance.d.ts +21 -1
  14. package/dist/internal/ducklake-maintenance.d.ts.map +1 -1
  15. package/dist/internal/ducklake-snapshot-reader.d.ts +63 -16
  16. package/dist/internal/ducklake-snapshot-reader.d.ts.map +1 -1
  17. package/dist/internal/ducklake-sql-executor.d.ts +9 -1
  18. package/dist/internal/ducklake-sql-executor.d.ts.map +1 -1
  19. package/dist/internal/ducklake-version-transaction.d.ts +54 -0
  20. package/dist/internal/ducklake-version-transaction.d.ts.map +1 -0
  21. package/dist/internal/ducklake-write-coordinator.d.ts +30 -3
  22. package/dist/internal/ducklake-write-coordinator.d.ts.map +1 -1
  23. package/dist/internal/lineage-encoding.d.ts +8 -0
  24. package/dist/internal/lineage-encoding.d.ts.map +1 -0
  25. package/dist/internal/sql-lineage/analysis.d.ts +32 -0
  26. package/dist/internal/sql-lineage/analysis.d.ts.map +1 -0
  27. package/dist/internal/sql-lineage/expressions.d.ts +9 -0
  28. package/dist/internal/sql-lineage/expressions.d.ts.map +1 -0
  29. package/dist/internal/sql-lineage/plan-json.d.ts +34 -0
  30. package/dist/internal/sql-lineage/plan-json.d.ts.map +1 -0
  31. package/dist/internal/sql-lineage/plan-relation.d.ts +28 -0
  32. package/dist/internal/sql-lineage/plan-relation.d.ts.map +1 -0
  33. package/dist/internal/sql-lineage/plan-walker.d.ts +18 -0
  34. package/dist/internal/sql-lineage/plan-walker.d.ts.map +1 -0
  35. package/dist/internal/sql-lineage/rejection.d.ts +11 -0
  36. package/dist/internal/sql-lineage/rejection.d.ts.map +1 -0
  37. package/dist/internal/sql-lineage/statement-gate.d.ts +21 -0
  38. package/dist/internal/sql-lineage/statement-gate.d.ts.map +1 -0
  39. package/dist/internal/sql-lineage/table-functions.d.ts +6 -0
  40. package/dist/internal/sql-lineage/table-functions.d.ts.map +1 -0
  41. package/dist/internal/sql-transform-relations.d.ts +20 -5
  42. package/dist/internal/sql-transform-relations.d.ts.map +1 -1
  43. package/dist/internal/versions.d.ts +10 -1
  44. package/dist/internal/versions.d.ts.map +1 -1
  45. package/dist/types.d.ts +10 -1
  46. package/dist/types.d.ts.map +1 -1
  47. package/package.json +6 -6
  48. package/src/ducklake-storage.ts +9 -2
  49. package/src/internal/dataset-row-commit.ts +28 -2
  50. package/src/internal/dataset-row-merge.ts +4 -0
  51. package/src/internal/ducklake-dataset-catalog.ts +162 -49
  52. package/src/internal/ducklake-dataset-table-ref.ts +75 -17
  53. package/src/internal/ducklake-maintenance.ts +110 -48
  54. package/src/internal/ducklake-snapshot-reader.ts +352 -304
  55. package/src/internal/ducklake-sql-executor.ts +214 -14
  56. package/src/internal/ducklake-version-transaction.ts +224 -0
  57. package/src/internal/ducklake-write-coordinator.ts +226 -148
  58. package/src/internal/lineage-encoding.ts +136 -0
  59. package/src/internal/sql-lineage/analysis.ts +257 -0
  60. package/src/internal/sql-lineage/expressions.ts +208 -0
  61. package/src/internal/sql-lineage/plan-json.ts +130 -0
  62. package/src/internal/sql-lineage/plan-relation.ts +59 -0
  63. package/src/internal/sql-lineage/plan-walker.ts +727 -0
  64. package/src/internal/sql-lineage/rejection.ts +16 -0
  65. package/src/internal/sql-lineage/statement-gate.ts +164 -0
  66. package/src/internal/sql-lineage/table-functions.ts +11 -0
  67. package/src/internal/sql-transform-relations.ts +90 -40
  68. package/src/internal/versions.ts +37 -14
  69. package/src/types.ts +11 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-relation.d.ts","sourceRoot":"","sources":["../../../src/internal/sql-lineage/plan-relation.ts"],"names":[],"mappings":"AAEA,0FAA0F;AAC1F,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;AAE9C;;;GAGG;AACH,eAAO,MAAM,cAAc,KAAK,CAAA;AAEhC,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAA;IACnC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,qGAAqG;AACrG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IACvC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAC5B;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,mEAAmE;AACnE,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAO7E;AAED,wBAAgB,OAAO,CAAC,GAAG,IAAI,EAAE,SAAS,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOrE;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAI1E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAEjF"}
@@ -0,0 +1,18 @@
1
+ /** The tables a plan may scan: physical table name, then column name, to a source column id. */
2
+ export type PlanSourceTables = ReadonlyMap<string, ReadonlyMap<string, number>>;
3
+ /** Source column ids, sorted, for the whole result and for each output column by position. */
4
+ export interface PlanLineage {
5
+ readonly rows: readonly number[];
6
+ readonly columns: readonly (readonly number[])[];
7
+ }
8
+ /**
9
+ * Column lineage of one bound, unoptimized logical plan (`json_serialize_plan(sql, optimize :=
10
+ * false)`), walked bottom-up. Each operator yields its output columns with the source columns their
11
+ * values come from, plus the source columns that decide which rows exist or their order. Those row
12
+ * dependencies accumulate upwards and apply to every output column.
13
+ *
14
+ * Expressions mostly reference their operator's input by position, so each operator below states
15
+ * the order of its output columns.
16
+ */
17
+ export declare function planLineage(plan: unknown, tables: PlanSourceTables): PlanLineage;
18
+ //# sourceMappingURL=plan-walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-walker.d.ts","sourceRoot":"","sources":["../../../src/internal/sql-lineage/plan-walker.ts"],"names":[],"mappings":"AA8BA,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAE/E,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;CACjD;AAaD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAUhF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A transform whose lineage cannot be derived exactly. The message names the construct and becomes
3
+ * the `reason` of an unsupported analysis; it never escapes the analysis as an error.
4
+ */
5
+ export declare class SqlLineageRejected extends Error {
6
+ readonly name = "SqlLineageRejected";
7
+ }
8
+ export declare function reject(reason: string): never;
9
+ /** DuckDB serialized something the analysis does not recognize, most likely after an upgrade. */
10
+ export declare function rejectPlanFormat(detail: string): never;
11
+ //# sourceMappingURL=rejection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejection.d.ts","sourceRoot":"","sources":["../../../src/internal/sql-lineage/rejection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAkB,IAAI,wBAAuB;CAC9C;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAE5C;AAED,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAEtD"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Checks the parse tree (`json_serialize_sql`) before DuckDB binds the query. Binding already runs
3
+ * table functions' bind code, and table macros such as `query()` only expand during binding, so
4
+ * they must be refused from the parse tree. PIVOT is refused here because its output columns depend
5
+ * on data the empty analysis tables do not have.
6
+ */
7
+ export declare function assertSingleSelect(statements: readonly unknown[]): void;
8
+ /**
9
+ * Whether the statement reads nothing but its sources, for a transform the analysis rejected: then
10
+ * every column it outputs depends on at most every column of its sources. PIVOT reads only its
11
+ * input.
12
+ *
13
+ * Data reaches a query through its table references. Each must be one of `sourceTables`, or a
14
+ * common table expression an enclosing query defines; a table function must compute from its
15
+ * arguments alone. A name a query does not define resolves to a table of the lake.
16
+ *
17
+ * A function must carry a name DuckDB itself defines, one of `builtinFunctions`: a macro the
18
+ * lake's setup defines can read any table, and its call shows none.
19
+ */
20
+ export declare function readsOnlySources(statements: readonly unknown[], sourceTables: ReadonlySet<string>, builtinFunctions: ReadonlySet<string>): boolean;
21
+ //# sourceMappingURL=statement-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statement-gate.d.ts","sourceRoot":"","sources":["../../../src/internal/sql-lineage/statement-gate.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAevE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,SAAS,OAAO,EAAE,EAC9B,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,EACjC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,GACpC,OAAO,CAYT"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Table functions that compute only from their arguments. Every other table function reads outside
3
+ * the transform's sources (files, catalogs, settings) or runs SQL of its own, like `query()`.
4
+ */
5
+ export declare const PURE_TABLE_FUNCTIONS: ReadonlySet<string>;
6
+ //# sourceMappingURL=table-functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-functions.d.ts","sourceRoot":"","sources":["../../../src/internal/sql-lineage/table-functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAMnD,CAAA"}
@@ -1,13 +1,28 @@
1
+ import type { DatasetColumnDefinition, DatasetDefinition } from "@sixb/core";
1
2
  import { type SqlTransformBody } from "@sixb/core/lake-storage";
2
3
  import type { DuckLakeStorageOptions } from "../types";
3
4
  export interface DuckLakeSqlTransformSourceRelation {
4
5
  readonly datasetId: string;
5
6
  readonly versionId: string;
7
+ /** The only columns the transform may read, in order. Every column when omitted. */
8
+ readonly columns?: readonly string[];
6
9
  }
7
- export interface RenderDuckLakeSqlTransformSqlInput {
8
- readonly options: Pick<DuckLakeStorageOptions, "alias">;
9
- readonly sources: Readonly<Record<string, DuckLakeSqlTransformSourceRelation>>;
10
- readonly sql: SqlTransformBody<"duckdb">;
10
+ /**
11
+ * The SQL a transform body returned, with a placeholder where each source relation belongs. The
12
+ * body runs once; the same SQL then renders against the lake and against the lineage analysis.
13
+ */
14
+ export interface DuckLakeSqlTransformTemplate {
15
+ /** Replaces each placeholder with its source's relation SQL, keyed by source name. */
16
+ render(relations: ReadonlyMap<string, string>): string;
11
17
  }
12
- export declare function renderDuckLakeSqlTransformSql(input: RenderDuckLakeSqlTransformSqlInput): string;
18
+ export declare function createDuckLakeSqlTransformTemplate(sourceNames: readonly string[], body: SqlTransformBody<"duckdb">): DuckLakeSqlTransformTemplate;
19
+ /** Each source as DuckLake time travel to its resolved version. */
20
+ export declare function renderDuckLakeSourceRelations(options: Pick<DuckLakeStorageOptions, "alias">, sources: Readonly<Record<string, DuckLakeSqlTransformSourceRelation>>): ReadonlyMap<string, string>;
21
+ /**
22
+ * The shape of every source relation. A pick lists its columns, so the transform cannot read any
23
+ * other column of the source.
24
+ */
25
+ export declare function renderSourceRelation(tableSql: string, columns?: readonly string[]): string;
26
+ /** The columns a source exposes to a transform: its pick, in order, or every column. */
27
+ export declare function pickSourceColumns(sourceName: string, dataset: DatasetDefinition, columns?: readonly string[]): readonly DatasetColumnDefinition[];
13
28
  //# sourceMappingURL=sql-transform-relations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sql-transform-relations.d.ts","sourceRoot":"","sources":["../../src/internal/sql-transform-relations.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAQtD,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAA;IACvD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAC,CAAA;IAC9E,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;CACzC;AAeD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,kCAAkC,GAAG,MAAM,CAS/F"}
1
+ {"version":3,"file":"sql-transform-relations.d.ts","sourceRoot":"","sources":["../../src/internal/sql-transform-relations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAQtD,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C,sFAAsF;IACtF,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;CACvD;AAUD,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,IAAI,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAC/B,4BAA4B,CAmC9B;AAED,mEAAmE;AACnE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,EAC9C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAC,GACpE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAW7B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI1F;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAC1B,SAAS,uBAAuB,EAAE,CA+BpC"}
@@ -12,11 +12,20 @@ export interface SixbCommitMetadata {
12
12
  readonly rowCount?: number;
13
13
  readonly validatedPrimaryKeyColumns?: readonly string[];
14
14
  readonly schemaChange?: SixbSchemaChangeMetadata;
15
+ /** As `encodeLineage` stored it: decoded only for the versions a read returns. */
16
+ readonly lineage?: unknown;
15
17
  }
16
18
  export declare function parseVersionId(versionId: string): string;
17
19
  export declare function toVersionId(snapshotId: string): string;
18
20
  export declare function parseCommitMetadata(value: unknown): SixbCommitMetadata | undefined;
19
- export declare function parseInlineDataChange(changesMade: string, tableId: bigint): {
21
+ /** Whether a DuckLake snapshot's `changes_made` names one of the tables, for any change. */
22
+ export declare function changesTouchTables(changesMade: string, tableIds: readonly bigint[]): boolean;
23
+ /**
24
+ * Whether a DuckLake snapshot changed a table's rows, and whether it removed any. DuckLake records
25
+ * every row change in `changes_made`, for inlined rows (`inlined_insert:<id>`) as for files
26
+ * (`inserted_into_table:<id>`, `deleted_from_table:<id>`); altering a table changes none.
27
+ */
28
+ export declare function parseTableDataChange(changesMade: string, tableId: bigint): {
20
29
  readonly hasDataChange: boolean;
21
30
  readonly hasDeleteChange: boolean;
22
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/internal/versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAG7D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,CAAA;CACjD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CA2ClF;AAED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd;IAAE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAsBxE"}
1
+ {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/internal/versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAG9E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,CAAA;IAChD,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CA6ClF;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAG5F;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd;IAAE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAsBxE"}
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { DatasetVersionRef } from "@sixb/core/lake-storage";
1
2
  /**
2
3
  * DuckLake catalog connection settings.
3
4
  *
@@ -107,18 +108,26 @@ export interface AzureSecretOptions extends BaseSecretOptions {
107
108
  }
108
109
  export type DuckDbSecretOptions = S3SecretOptions | R2SecretOptions | GcsSecretOptions | AzureSecretOptions;
109
110
  export interface DuckLakeMaintenanceOptions {
110
- /** How long to keep snapshots before they can expire. Default: "7 days". */
111
+ /**
112
+ * How long to keep snapshots before they can expire. Default: "7 days". Each dataset's latest
113
+ * version and the `protect` versions are kept whatever their age.
114
+ */
111
115
  readonly expireOlderThan?: string;
112
116
  /** How long to keep deleted/orphaned files before reclaim. Default: expireOlderThan. */
113
117
  readonly deleteOlderThan?: string;
114
118
  /** Report what would be expired/deleted without changing the lake. Default: false. */
115
119
  readonly dryRun?: boolean;
120
+ /** Versions to keep whatever their age, such as those projections applied. */
121
+ readonly protect?: readonly DatasetVersionRef[];
116
122
  }
117
123
  export interface DuckLakeMaintenanceReport {
118
124
  readonly dryRun: boolean;
119
125
  readonly expireOlderThan: string;
120
126
  readonly deleteOlderThan: string;
127
+ /** Snapshots expired, or that would expire on a dry run. */
121
128
  readonly snapshots: number;
129
+ /** Snapshots older than `expireOlderThan` kept because a version they hold is still needed. */
130
+ readonly keptSnapshots: number;
122
131
  readonly oldFiles: number;
123
132
  readonly orphanedFiles: number;
124
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sixb/ducklake",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
4
4
  "description": "DuckDB/DuckLake lake storage provider for Sixb",
5
5
  "keywords": [
6
6
  "sixb",
@@ -36,18 +36,18 @@
36
36
  "typecheck": "tsc --noEmit",
37
37
  "test": "bun test",
38
38
  "test:e2e": "bun run test:e2e:local && bun run test:e2e:remote",
39
- "test:e2e:local": "bun test ./tests/ducklake-reader.e2e.ts ./tests/ducklake-changes.e2e.ts ./tests/ducklake-contract.e2e.ts ./tests/ducklake-file-refs.e2e.ts ./tests/ducklake-catalog-state.e2e.ts ./tests/ducklake-catalogs.e2e.ts ./tests/ducklake-concurrency.e2e.ts ./tests/ducklake-datasets.e2e.ts ./tests/ducklake-driver.e2e.ts ./tests/ducklake-maintenance.e2e.ts ./tests/ducklake-merges.e2e.ts ./tests/ducklake-sql-transforms.e2e.ts ./tests/ducklake-versions.e2e.ts ./tests/ducklake-long-history.e2e.ts ./tests/ducklake-writes.e2e.ts ./tests/ducklake-sqlite-writes.e2e.ts",
40
- "test:e2e:remote": "bun test --preload ./tests/setup.ts ./tests/ducklake-remote.e2e.ts",
39
+ "test:e2e:local": "bun test --preload ./tests/extensions.ts ./tests/ducklake-reader.e2e.ts ./tests/ducklake-changes.e2e.ts ./tests/ducklake-contract.e2e.ts ./tests/ducklake-catalog-state.e2e.ts ./tests/ducklake-catalogs.e2e.ts ./tests/ducklake-concurrency.e2e.ts ./tests/ducklake-datasets.e2e.ts ./tests/ducklake-driver.e2e.ts ./tests/ducklake-maintenance.e2e.ts ./tests/ducklake-merges.e2e.ts ./tests/ducklake-sql-transforms.e2e.ts ./tests/ducklake-versions.e2e.ts ./tests/ducklake-long-history.e2e.ts ./tests/ducklake-writes.e2e.ts ./tests/ducklake-sqlite-writes.e2e.ts",
40
+ "test:e2e:remote": "bun test --preload ./tests/extensions.ts --preload ./tests/setup.ts ./tests/ducklake-remote.e2e.ts",
41
41
  "prepack": "bun run build"
42
42
  },
43
43
  "dependencies": {
44
- "@duckdb/node-api": "^1.5.2-r.1"
44
+ "@duckdb/node-api": "1.5.2-r.2"
45
45
  },
46
46
  "peerDependencies": {
47
- "@sixb/core": "^0.1.17"
47
+ "@sixb/core": "^0.2.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@sixb/core": "0.1.17",
50
+ "@sixb/core": "0.2.0",
51
51
  "@types/bun": "latest",
52
52
  "typescript": "^5.7.0"
53
53
  },
@@ -35,6 +35,7 @@ import type {
35
35
  */
36
36
  export class DuckLakeStorage implements LakeStorageWithSql<"duckdb"> {
37
37
  readonly standard = { id: "ducklake", version: "1.0" } as const
38
+ readonly recordsLineage = true
38
39
  readonly sql: DuckLakeSqlExecutor
39
40
 
40
41
  private readonly connections: DuckLakeConnectionManager
@@ -58,12 +59,16 @@ export class DuckLakeStorage implements LakeStorageWithSql<"duckdb"> {
58
59
  }
59
60
  this.connections = new DuckLakeConnectionManager(normalizedOptions)
60
61
  this.datasets = new DuckLakeDatasetCatalog(normalizedOptions, this.connections)
61
- this.maintenance = new DuckLakeMaintenance(normalizedOptions, this.connections)
62
62
  this.snapshotReader = new DuckLakeSnapshotReader(
63
63
  normalizedOptions,
64
64
  this.connections,
65
65
  this.datasets
66
66
  )
67
+ this.maintenance = new DuckLakeMaintenance(
68
+ normalizedOptions,
69
+ this.connections,
70
+ this.snapshotReader
71
+ )
67
72
  this.rows = new DuckLakeRowReader(normalizedOptions, this.connections, this.snapshotReader)
68
73
  this.changes = new DuckLakeChangeReader(
69
74
  normalizedOptions,
@@ -86,7 +91,9 @@ export class DuckLakeStorage implements LakeStorageWithSql<"duckdb"> {
86
91
  }
87
92
 
88
93
  async createDataset(definition: DatasetDefinition): Promise<DatasetDefinition> {
89
- return this.datasets.createDataset(definition)
94
+ return this.datasets.createDataset(definition, (runtime, dataset) =>
95
+ this.snapshotReader.getLatestVersionSummaryAtCurrentSnapshot(runtime, dataset)
96
+ )
90
97
  }
91
98
 
92
99
  async assertDatasetDefinitionsCompatible(
@@ -19,6 +19,16 @@ export interface ApplyDatasetRowsResult {
19
19
  readonly dataChangeExpected: boolean
20
20
  readonly sourceRowCount: number
21
21
  readonly resultingRowCount: CommitRowCount
22
+ /**
23
+ * The table held no rows when this transaction read it. A write into an empty table deletes
24
+ * nothing, so DuckLake lets it commit alongside a concurrent one that also read the table empty.
25
+ */
26
+ readonly targetWasEmpty: boolean
27
+ /**
28
+ * The write inserted or deleted rows of the dataset table, which DuckLake checks against
29
+ * concurrent changes to the table. A merge that only advances source ordering changes none.
30
+ */
31
+ readonly changedTableRows: boolean
22
32
  }
23
33
 
24
34
  export function assertDatasetWriteMode(
@@ -46,6 +56,7 @@ export async function applyDatasetRowsFromRelation(input: {
46
56
  const columnsSql = datasetSchemaColumnNamesSql(input.dataset.schema)
47
57
  const primaryKeyColumns = getDatasetPrimaryKeyColumns(input.dataset)
48
58
 
59
+ let baselineRowCount: number | undefined
49
60
  if (primaryKeyColumns !== null) {
50
61
  await inspectUniqueKeyedRelation({
51
62
  runtime: input.runtime,
@@ -55,7 +66,7 @@ export async function applyDatasetRowsFromRelation(input: {
55
66
  })
56
67
 
57
68
  if (input.mode === "append") {
58
- await inspectUniqueKeyedRelation({
69
+ baselineRowCount = await inspectUniqueKeyedRelation({
59
70
  runtime: input.runtime,
60
71
  dataset: input.dataset,
61
72
  relationSql: table,
@@ -80,6 +91,8 @@ export async function applyDatasetRowsFromRelation(input: {
80
91
  dataChangeExpected: false,
81
92
  sourceRowCount: source.rowCount,
82
93
  resultingRowCount: { kind: "exact", value: target.rowCount },
94
+ targetWasEmpty: target.rowCount === 0,
95
+ changedTableRows: false,
83
96
  }
84
97
  }
85
98
 
@@ -88,20 +101,28 @@ export async function applyDatasetRowsFromRelation(input: {
88
101
  `INSERT INTO ${table} (${columnsSql}) SELECT ${columnsSql} FROM ${input.sourceRelationSql}`
89
102
  )
90
103
 
104
+ const changedTableRows = source.rowCount > 0 || target.rowCount > 0
91
105
  return {
92
- dataChangeExpected: source.rowCount > 0 || target.rowCount > 0,
106
+ dataChangeExpected: changedTableRows,
93
107
  sourceRowCount: source.rowCount,
94
108
  resultingRowCount: { kind: "exact", value: source.rowCount },
109
+ targetWasEmpty: target.rowCount === 0,
110
+ changedTableRows,
95
111
  }
96
112
  }
97
113
 
98
114
  const sourceRowCount = await countRows(input.runtime, input.sourceRelationSql)
115
+ const knownRowCount = baselineRowCount ?? input.previousRowCount
116
+ const targetWasEmpty =
117
+ knownRowCount === undefined ? await isEmptyRelation(input.runtime, table) : knownRowCount === 0
99
118
  await input.runtime.run(
100
119
  `INSERT INTO ${table} (${columnsSql}) SELECT ${columnsSql} FROM ${input.sourceRelationSql}`
101
120
  )
102
121
 
103
122
  return {
104
123
  dataChangeExpected: sourceRowCount > 0,
124
+ targetWasEmpty,
125
+ changedTableRows: sourceRowCount > 0,
105
126
  sourceRowCount,
106
127
  resultingRowCount:
107
128
  input.previousRowCount === undefined
@@ -219,3 +240,8 @@ async function countRows(runtime: DuckDbQueryRuntime, relationSql: string): Prom
219
240
 
220
241
  return Number(getBigIntLike(row, "row_count"))
221
242
  }
243
+
244
+ async function isEmptyRelation(runtime: DuckDbQueryRuntime, relationSql: string): Promise<boolean> {
245
+ const rows = await runtime.query(`SELECT 1 AS present FROM ${relationSql} LIMIT 1`)
246
+ return rows.length === 0
247
+ }
@@ -58,6 +58,8 @@ export async function applyDatasetMergeFromRelation(
58
58
  dataChangeExpected: orderingChanged,
59
59
  sourceRowCount,
60
60
  resultingRowCount: { kind: "exact", value: previousRowCount },
61
+ targetWasEmpty: previousRowCount === 0,
62
+ changedTableRows: false,
61
63
  }
62
64
  }
63
65
 
@@ -103,6 +105,8 @@ export async function applyDatasetMergeFromRelation(
103
105
  kind: "exact",
104
106
  value: previousRowCount + effects.inserts - effects.deletes,
105
107
  },
108
+ targetWasEmpty: previousRowCount === 0,
109
+ changedTableRows: true,
106
110
  }
107
111
  }
108
112
  )