@gscdump/lakehouse 4.2.0 → 4.2.1

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.
@@ -11,13 +11,9 @@ export type ManifestPartitionFilter = (partitions: IcebergFieldSummary[] | undef
11
11
  /**
12
12
  * One identity/dims value to prune an `identity`-transform partition field by.
13
13
  *
14
- * `'int32'`-encoded fields are deliberately NOT pruned here (mirrors the
15
- * original engine behavior): an INT column's bound bytes are a 4-byte int, but
16
- * per-team catalogs are single-tenant, so identity pruning on them saves ~nothing
17
- * — the per-file partition check in the resolver remains the authoritative
18
- * correctness filter. Only `'string'`-encoded identity fields are pruned by
19
- * lexicographic UTF-8 bound comparison (the truncated-string-stats case R2 SQL
20
- * needs the workaround for).
14
+ * Identity summaries use the declared field encoding: UTF-8 for strings and
15
+ * four-byte little-endian for INT. Unknown bounds keep the manifest. The
16
+ * per-file partition check remains the authoritative correctness filter.
21
17
  */
22
18
  export interface PartitionValueMatch {
23
19
  /** Partition field name as declared in the partition spec (e.g. `'site_id'`). */
@@ -7,11 +7,12 @@ function decodeString(bytes) {
7
7
  const u = toUint8(bytes);
8
8
  return u == null ? null : UTF8_DECODER.decode(u);
9
9
  }
10
- function decodeMonthInt(bytes) {
10
+ function decodeInt32(bytes) {
11
11
  const u = toUint8(bytes);
12
- if (u == null) return null;
12
+ if (u?.byteLength !== 4) return null;
13
13
  return new DataView(u.buffer, u.byteOffset, u.byteLength).getInt32(0, true);
14
14
  }
15
+ const decodeMonthInt = decodeInt32;
15
16
  function buildManifestPartitionFilter(partitionSpec, matches, wantedMonths) {
16
17
  const fieldIndex = (name) => partitionSpec.findIndex((f) => f.name === name || f.sourceColumn === name);
17
18
  const monthFieldIndex = partitionSpec.findIndex((f) => f.transform === "month");
@@ -23,6 +24,14 @@ function buildManifestPartitionFilter(partitionSpec, matches, wantedMonths) {
23
24
  value: String(match.value)
24
25
  }];
25
26
  });
27
+ const intMatches = matches.flatMap((match) => {
28
+ if (match.encoding !== "int32" || typeof match.value !== "number" || !Number.isInteger(match.value) || match.value < -2147483648 || match.value > 2147483647) return [];
29
+ const index = fieldIndex(match.field);
30
+ return index < 0 || partitionSpec[index]?.transform !== "identity" ? [] : [{
31
+ index,
32
+ value: match.value
33
+ }];
34
+ });
26
35
  const wantedMonthValues = wantedMonths ? [...wantedMonths].filter(Number.isFinite).sort((a, b) => a - b) : [];
27
36
  const hasWantedMonthInRange = (lo, hi) => {
28
37
  let left = 0;
@@ -43,6 +52,13 @@ function buildManifestPartitionFilter(partitionSpec, matches, wantedMonths) {
43
52
  const hi = decodeString(summary.upper_bound);
44
53
  if (lo != null && hi != null && (match.value < lo || match.value > hi)) return false;
45
54
  }
55
+ for (const match of intMatches) {
56
+ const summary = partitions[match.index];
57
+ if (!summary || summary.lower_bound == null || summary.upper_bound == null) continue;
58
+ const lo = decodeInt32(summary.lower_bound);
59
+ const hi = decodeInt32(summary.upper_bound);
60
+ if (lo != null && hi != null && lo <= hi && (match.value < lo || match.value > hi)) return false;
61
+ }
46
62
  if (wantedMonthValues.length > 0 && monthFieldIndex >= 0) {
47
63
  const monthSummary = partitions[monthFieldIndex];
48
64
  if (monthSummary && (monthSummary.lower_bound != null || monthSummary.upper_bound != null)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/lakehouse",
3
3
  "type": "module",
4
- "version": "4.2.0",
4
+ "version": "4.2.1",
5
5
  "description": "Dataset-agnostic Iceberg lakehouse layer + dataset registry for R2 Data Catalog producers (ADR-0021).",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",