@loaders.gl/scan 5.0.0-alpha.3 → 5.0.0-alpha.4

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/dist.min.js CHANGED
@@ -17574,29 +17574,29 @@ return true;`);
17574
17574
  }
17575
17575
 
17576
17576
  // src/scan-engine.ts
17577
- var scanBackendLoaders = /* @__PURE__ */ new Map();
17577
+ var scanBackends = /* @__PURE__ */ new Map();
17578
17578
  var arrowScanBackend = Object.freeze({
17579
17579
  name: "arrow",
17580
17580
  query: queryArrowTable,
17581
- queryAsync: async (sourceTable, options) => queryArrowTable(sourceTable, options),
17581
+ queryAsync: (sourceTable, options) => Promise.resolve().then(queryArrowTable.bind(null, sourceTable, options)),
17582
17582
  explain: explainArrowTableQuery
17583
17583
  });
17584
- scanBackendLoaders.set("arrow", () => arrowScanBackend);
17584
+ scanBackends.set("arrow", arrowScanBackend);
17585
17585
  function registerScanBackend(name, loader) {
17586
17586
  if (!name || !loader) {
17587
17587
  throw new Error("A scan backend name and loader are required");
17588
17588
  }
17589
- scanBackendLoaders.set(name, loader);
17589
+ scanBackends.set(name, loader);
17590
17590
  }
17591
17591
  async function createScanEngine(options = {}) {
17592
17592
  const backendName = options.backend || "arrow";
17593
- const loader = scanBackendLoaders.get(backendName);
17594
- if (!loader) {
17593
+ const registeredBackend = scanBackends.get(backendName);
17594
+ if (!registeredBackend) {
17595
17595
  throw new Error(
17596
17596
  `Scan backend "${backendName}" is not registered. The built-in backend is "arrow".`
17597
17597
  );
17598
17598
  }
17599
- const backend = await loader();
17599
+ const backend = typeof registeredBackend === "function" ? await registeredBackend() : registeredBackend;
17600
17600
  if (backend.name !== backendName) {
17601
17601
  throw new Error(
17602
17602
  `Scan backend loader returned "${backend.name}" while "${backendName}" was requested.`
package/dist/hudi.cjs CHANGED
@@ -20676,6 +20676,201 @@ var init_decoders = __esm({
20676
20676
  }
20677
20677
  });
20678
20678
 
20679
+ // ../parquet/src/parquetjs/parser/encoded-pages.ts
20680
+ async function scanParquetEncodedPages(buffer, context) {
20681
+ const pages = [];
20682
+ let offset = 0;
20683
+ let dataPageOrdinal = 0;
20684
+ while (offset < buffer.byteLength) {
20685
+ const { pageHeader, length: headerByteLength } = decodePageHeader(buffer, offset);
20686
+ const bodyOffset = offset + headerByteLength;
20687
+ const bodyEnd = bodyOffset + pageHeader.compressed_page_size;
20688
+ if (pageHeader.compressed_page_size < 0 || pageHeader.uncompressed_page_size < 0 || bodyEnd > buffer.byteLength) {
20689
+ throw new Error("Parquet page extends beyond the available column-chunk buffer");
20690
+ }
20691
+ const compressedBody = buffer.subarray(bodyOffset, bodyEnd);
20692
+ verifyEncodedPageChecksum(compressedBody, pageHeader, context.verifyPageChecksums);
20693
+ const pageType = getThriftEnum(PageType, pageHeader.type);
20694
+ if (pageType === "DICTIONARY_PAGE") {
20695
+ pages.push(await createDictionaryPage(compressedBody, pageHeader, context));
20696
+ } else if (pageType === "DATA_PAGE") {
20697
+ pages.push(await createDataPageV1(compressedBody, pageHeader, context, dataPageOrdinal++));
20698
+ } else if (pageType === "DATA_PAGE_V2") {
20699
+ pages.push(await createDataPageV2(compressedBody, pageHeader, context, dataPageOrdinal++));
20700
+ } else {
20701
+ throw new Error(`Unsupported Parquet page type ${pageType}`);
20702
+ }
20703
+ offset = bodyEnd;
20704
+ }
20705
+ return pages;
20706
+ }
20707
+ async function createDictionaryPage(compressedBody, pageHeader, context) {
20708
+ const dictionaryHeader = pageHeader.dictionary_page_header;
20709
+ if (!dictionaryHeader) {
20710
+ throw new Error("Parquet dictionary page is missing its dictionary header");
20711
+ }
20712
+ const preserveCompression = shouldPreserveCompression(context);
20713
+ const data = preserveCompression ? compressedBody : await decompressPageBody(compressedBody, pageHeader.uncompressed_page_size, context);
20714
+ return Object.freeze({
20715
+ type: "dictionary",
20716
+ pageOrdinal: -1,
20717
+ encoding: getThriftEnum(Encoding, dictionaryHeader.encoding),
20718
+ compression: context.compression,
20719
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20720
+ valueCount: dictionaryHeader.num_values,
20721
+ nonNullValueCount: dictionaryHeader.num_values,
20722
+ data,
20723
+ values: preserveCompression ? void 0 : createSection(0, data.byteLength),
20724
+ compressedByteLength: pageHeader.compressed_page_size,
20725
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20726
+ });
20727
+ }
20728
+ async function createDataPageV1(compressedBody, pageHeader, context, pageOrdinal) {
20729
+ const dataHeader = pageHeader.data_page_header;
20730
+ if (!dataHeader) {
20731
+ throw new Error("Parquet V1 data page is missing its data header");
20732
+ }
20733
+ const preserveCompression = shouldPreserveCompression(context);
20734
+ const data = preserveCompression ? compressedBody : await decompressPageBody(compressedBody, pageHeader.uncompressed_page_size, context);
20735
+ let repetitionLevels;
20736
+ let definitionLevels;
20737
+ let values;
20738
+ if (!preserveCompression) {
20739
+ let sectionOffset = 0;
20740
+ const repetitionLevelEncoding = getThriftEnum(Encoding, dataHeader.repetition_level_encoding);
20741
+ repetitionLevels = readV1LevelSection(
20742
+ data,
20743
+ sectionOffset,
20744
+ dataHeader.num_values,
20745
+ context.column.rLevelMax,
20746
+ repetitionLevelEncoding
20747
+ );
20748
+ sectionOffset = repetitionLevels.byteOffset + repetitionLevels.byteLength;
20749
+ const definitionLevelEncoding = getThriftEnum(Encoding, dataHeader.definition_level_encoding);
20750
+ definitionLevels = readV1LevelSection(
20751
+ data,
20752
+ sectionOffset,
20753
+ dataHeader.num_values,
20754
+ context.column.dLevelMax,
20755
+ definitionLevelEncoding
20756
+ );
20757
+ sectionOffset = definitionLevels.byteOffset + definitionLevels.byteLength;
20758
+ values = createSection(sectionOffset, data.byteLength - sectionOffset);
20759
+ }
20760
+ return Object.freeze({
20761
+ type: "data-v1",
20762
+ pageOrdinal,
20763
+ encoding: getThriftEnum(Encoding, dataHeader.encoding),
20764
+ repetitionLevelEncoding: getThriftEnum(Encoding, dataHeader.repetition_level_encoding),
20765
+ definitionLevelEncoding: getThriftEnum(Encoding, dataHeader.definition_level_encoding),
20766
+ compression: context.compression,
20767
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20768
+ valueCount: dataHeader.num_values,
20769
+ data,
20770
+ repetitionLevels,
20771
+ definitionLevels,
20772
+ values,
20773
+ compressedByteLength: pageHeader.compressed_page_size,
20774
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20775
+ });
20776
+ }
20777
+ async function createDataPageV2(compressedBody, pageHeader, context, pageOrdinal) {
20778
+ const dataHeader = pageHeader.data_page_header_v2;
20779
+ if (!dataHeader) {
20780
+ throw new Error("Parquet V2 data page is missing its data header");
20781
+ }
20782
+ const repetitionByteLength = dataHeader.repetition_levels_byte_length;
20783
+ const definitionByteLength = dataHeader.definition_levels_byte_length;
20784
+ const levelsByteLength = repetitionByteLength + definitionByteLength;
20785
+ if (levelsByteLength > compressedBody.byteLength) {
20786
+ throw new Error("Parquet V2 level sections extend beyond the page body");
20787
+ }
20788
+ const valuesAreCompressed = dataHeader.is_compressed !== false && context.compression !== "UNCOMPRESSED";
20789
+ const preserveCompression = valuesAreCompressed && shouldPreserveCompression(context);
20790
+ let data = compressedBody;
20791
+ if (valuesAreCompressed && !preserveCompression) {
20792
+ const uncompressedValuesByteLength = pageHeader.uncompressed_page_size - levelsByteLength;
20793
+ if (uncompressedValuesByteLength < 0) {
20794
+ throw new Error("Invalid Parquet V2 uncompressed value length");
20795
+ }
20796
+ const values = await context.decompressPage(
20797
+ compressedBody.subarray(levelsByteLength),
20798
+ uncompressedValuesByteLength
20799
+ );
20800
+ data = new Uint8Array(levelsByteLength + values.byteLength);
20801
+ data.set(compressedBody.subarray(0, levelsByteLength));
20802
+ data.set(values, levelsByteLength);
20803
+ }
20804
+ return Object.freeze({
20805
+ type: "data-v2",
20806
+ pageOrdinal,
20807
+ encoding: getThriftEnum(Encoding, dataHeader.encoding),
20808
+ repetitionLevelEncoding: "RLE",
20809
+ definitionLevelEncoding: "RLE",
20810
+ compression: context.compression,
20811
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20812
+ valueCount: dataHeader.num_values,
20813
+ nonNullValueCount: dataHeader.num_values - dataHeader.num_nulls,
20814
+ data,
20815
+ repetitionLevels: createSection(0, repetitionByteLength),
20816
+ definitionLevels: createSection(repetitionByteLength, definitionByteLength),
20817
+ values: createSection(levelsByteLength, data.byteLength - levelsByteLength),
20818
+ compressedByteLength: pageHeader.compressed_page_size,
20819
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20820
+ });
20821
+ }
20822
+ function shouldPreserveCompression(context) {
20823
+ var _a;
20824
+ return context.compression !== "UNCOMPRESSED" && Boolean((_a = context.preserveCompression) == null ? void 0 : _a.has(context.compression));
20825
+ }
20826
+ async function decompressPageBody(compressedBody, uncompressedByteLength, context) {
20827
+ if (context.compression === "UNCOMPRESSED") return compressedBody;
20828
+ return await context.decompressPage(compressedBody, uncompressedByteLength);
20829
+ }
20830
+ function readV1LevelSection(data, offset, valueCount, maxLevel, encoding) {
20831
+ if (maxLevel === 0) return createSection(offset, 0);
20832
+ if (encoding === "RLE") {
20833
+ if (offset + 4 > data.byteLength) {
20834
+ throw new Error("Parquet V1 RLE level stream is missing its length prefix");
20835
+ }
20836
+ const byteLength = readUInt32LE(data, offset);
20837
+ const byteOffset = offset + 4;
20838
+ assertSectionBounds(data, byteOffset, byteLength);
20839
+ return createSection(byteOffset, byteLength);
20840
+ }
20841
+ if (encoding === "BIT_PACKED") {
20842
+ const byteLength = Math.ceil(valueCount / 8) * getBitWidth(maxLevel);
20843
+ assertSectionBounds(data, offset, byteLength);
20844
+ return createSection(offset, byteLength);
20845
+ }
20846
+ throw new Error(`Unsupported Parquet V1 level encoding ${encoding}`);
20847
+ }
20848
+ function createSection(byteOffset, byteLength) {
20849
+ return Object.freeze({ byteOffset, byteLength });
20850
+ }
20851
+ function assertSectionBounds(data, byteOffset, byteLength) {
20852
+ if (byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.byteLength) {
20853
+ throw new Error("Parquet page section extends beyond the page body");
20854
+ }
20855
+ }
20856
+ function verifyEncodedPageChecksum(compressedBody, pageHeader, verifyPageChecksums = false) {
20857
+ if (!verifyPageChecksums || pageHeader.crc === void 0) return;
20858
+ const expected = pageHeader.crc >>> 0;
20859
+ const actual = crc32(compressedBody);
20860
+ if (actual !== expected) {
20861
+ throw new Error(`Parquet page checksum mismatch: expected ${expected}, calculated ${actual}`);
20862
+ }
20863
+ }
20864
+ var init_encoded_pages = __esm({
20865
+ "../parquet/src/parquetjs/parser/encoded-pages.ts"() {
20866
+ "use strict";
20867
+ init_parquet_thrift();
20868
+ init_crc32();
20869
+ init_binary_utils();
20870
+ init_read_utils();
20871
+ }
20872
+ });
20873
+
20679
20874
  // ../parquet/src/lib/parquet-encryption.ts
20680
20875
  function readParquetEncryptedModule(buffer, offset = 0) {
20681
20876
  if (offset + 4 > buffer.length) {
@@ -20918,6 +21113,7 @@ var init_parquet_reader = __esm({
20918
21113
  "use strict";
20919
21114
  init_schema();
20920
21115
  init_decoders();
21116
+ init_encoded_pages();
20921
21117
  init_shred();
20922
21118
  init_compression2();
20923
21119
  init_constants();
@@ -21404,6 +21600,50 @@ var init_parquet_reader = __esm({
21404
21600
  columnData: Object.fromEntries(columnEntries)
21405
21601
  };
21406
21602
  }
21603
+ /**
21604
+ * Reads selected column chunks as encoded page descriptors without materializing values.
21605
+ *
21606
+ * Page headers, encryption, checksums, and optional decompression remain reader concerns. Value,
21607
+ * dictionary, and level decoding is deliberately left to the downstream consumer.
21608
+ */
21609
+ async readRowGroupEncodedPages(schema, rowGroup, columnList, preserveCompression, signal, rowGroupOrdinal = 0) {
21610
+ await this.resolveColumnMetadata(rowGroup, rowGroupOrdinal, columnList);
21611
+ const selectedColumnChunks = [];
21612
+ for (let columnOrdinal = 0; columnOrdinal < rowGroup.columns.length; columnOrdinal++) {
21613
+ const columnChunk = rowGroup.columns[columnOrdinal];
21614
+ const path = getColumnChunkPath(columnChunk);
21615
+ if (columnList.length > 0 && (!path || fieldIndexOf(columnList, path) < 0)) continue;
21616
+ const physicalColumnOrdinal = getPhysicalColumnOrdinal(columnChunk, columnOrdinal);
21617
+ const metadata = columnChunk.meta_data || await this.getColumnMetadata(columnChunk, rowGroupOrdinal, physicalColumnOrdinal);
21618
+ if (columnList.length === 0 || fieldIndexOf(columnList, metadata.path_in_schema) >= 0) {
21619
+ selectedColumnChunks.push({
21620
+ columnChunk,
21621
+ metadata,
21622
+ columnOrdinal: physicalColumnOrdinal
21623
+ });
21624
+ }
21625
+ }
21626
+ const columns = [];
21627
+ for (let batchStart = 0; batchStart < selectedColumnChunks.length; batchStart += MAXIMUM_CONCURRENT_COLUMN_READS) {
21628
+ columns.push(
21629
+ ...await Promise.all(
21630
+ selectedColumnChunks.slice(batchStart, batchStart + MAXIMUM_CONCURRENT_COLUMN_READS).map(async ({ columnChunk, metadata, columnOrdinal }) => {
21631
+ const encodedColumn = await this.readColumnChunkEncodedPages(
21632
+ schema,
21633
+ columnChunk,
21634
+ preserveCompression,
21635
+ signal,
21636
+ rowGroupOrdinal,
21637
+ columnOrdinal,
21638
+ metadata
21639
+ );
21640
+ return encodedColumn;
21641
+ })
21642
+ )
21643
+ );
21644
+ }
21645
+ return Object.freeze(columns);
21646
+ }
21407
21647
  /** Reads independently materializable non-repeated columns for one row range using page indexes. */
21408
21648
  async readRowGroupRange(schema, rowGroup, columnList, rowRange, pageLocations, signal, rowGroupOrdinal = 0) {
21409
21649
  await this.resolveColumnMetadata(rowGroup, rowGroupOrdinal, columnList);
@@ -21596,6 +21836,99 @@ var init_parquet_reader = __esm({
21596
21836
  ) : chunkBuffer.subarray(pagesRelativeOffset, pagesRelativeOffset + pagesSize);
21597
21837
  return await decodeDataPages(pagesBuf, { ...context, dictionary });
21598
21838
  }
21839
+ /** Reads one column chunk as encoded dictionaries, levels, and values for deferred decoding. */
21840
+ async readColumnChunkEncodedPages(schema, columnChunk, preserveCompression, signal, rowGroupOrdinal = 0, columnOrdinal = 0, resolvedMetadata) {
21841
+ if (columnChunk.file_path !== void 0 && columnChunk.file_path !== null) {
21842
+ throw new Error("external references are not supported");
21843
+ }
21844
+ const metadata = resolvedMetadata || columnChunk.meta_data;
21845
+ if (!metadata) throw new Error("Parquet column metadata is missing");
21846
+ const field = schema.findField(metadata.path_in_schema);
21847
+ const physicalType = getThriftEnum(Type, metadata.type);
21848
+ if (physicalType !== field.primitiveType) {
21849
+ throw new Error(`chunk type not matching schema: ${physicalType}`);
21850
+ }
21851
+ const compression = getThriftEnum(CompressionCodec, metadata.codec);
21852
+ const dataPageOffset = Number(metadata.data_page_offset);
21853
+ const dictionaryPageOffset = metadata.dictionary_page_offset;
21854
+ const validDictionaryPageOffset = dictionaryPageOffset !== void 0 && Number(dictionaryPageOffset) > 0 ? Number(dictionaryPageOffset) : void 0;
21855
+ const chunkOffset = Math.min(dataPageOffset, validDictionaryPageOffset ?? dataPageOffset);
21856
+ const chunkEnd = chunkOffset + Number(metadata.total_compressed_size);
21857
+ const chunkByteLength = Math.min(
21858
+ this.file.size - chunkOffset,
21859
+ Math.max(0, chunkEnd - chunkOffset)
21860
+ );
21861
+ const chunkBuffer = await this.readBytes(chunkOffset, chunkByteLength, signal);
21862
+ const dataPageRelativeOffset = dataPageOffset - chunkOffset;
21863
+ const dataPageByteLength = Math.min(
21864
+ chunkBuffer.byteLength - dataPageRelativeOffset,
21865
+ Math.max(0, chunkEnd - dataPageOffset)
21866
+ );
21867
+ const context = {
21868
+ column: field,
21869
+ compression,
21870
+ decompressPage: this.getPageDecompressor(compression),
21871
+ preserveCompression,
21872
+ verifyPageChecksums: this.props.verifyPageChecksums
21873
+ };
21874
+ let dictionary;
21875
+ if (validDictionaryPageOffset !== void 0) {
21876
+ const dictionaryRelativeOffset = validDictionaryPageOffset - chunkOffset;
21877
+ const dictionaryByteLength = Math.min(
21878
+ Math.max(0, dataPageOffset - validDictionaryPageOffset),
21879
+ chunkBuffer.byteLength - dictionaryRelativeOffset,
21880
+ this.props.defaultDictionarySize
21881
+ );
21882
+ const dictionaryBuffer = chunkBuffer.subarray(
21883
+ dictionaryRelativeOffset,
21884
+ dictionaryRelativeOffset + dictionaryByteLength
21885
+ );
21886
+ const plaintextDictionaryBuffer = columnChunk.crypto_metadata ? await this.decryptColumnPages(
21887
+ dictionaryBuffer,
21888
+ {
21889
+ type: physicalType,
21890
+ rLevelMax: field.rLevelMax,
21891
+ dLevelMax: field.dLevelMax,
21892
+ compression,
21893
+ column: field
21894
+ },
21895
+ rowGroupOrdinal,
21896
+ columnOrdinal,
21897
+ this.getColumnKeyMetadata(columnChunk),
21898
+ true
21899
+ ) : dictionaryBuffer;
21900
+ dictionary = (await scanParquetEncodedPages(plaintextDictionaryBuffer, context))[0];
21901
+ }
21902
+ const dataPageBuffer = chunkBuffer.subarray(
21903
+ dataPageRelativeOffset,
21904
+ dataPageRelativeOffset + dataPageByteLength
21905
+ );
21906
+ const plaintextDataPageBuffer = columnChunk.crypto_metadata ? await this.decryptColumnPages(
21907
+ dataPageBuffer,
21908
+ {
21909
+ type: physicalType,
21910
+ rLevelMax: field.rLevelMax,
21911
+ dLevelMax: field.dLevelMax,
21912
+ compression,
21913
+ column: field
21914
+ },
21915
+ rowGroupOrdinal,
21916
+ columnOrdinal,
21917
+ this.getColumnKeyMetadata(columnChunk)
21918
+ ) : dataPageBuffer;
21919
+ const pages = await scanParquetEncodedPages(plaintextDataPageBuffer, context);
21920
+ return Object.freeze({
21921
+ path: Object.freeze([...metadata.path_in_schema]),
21922
+ physicalType,
21923
+ typeLength: field.typeLength,
21924
+ maxRepetitionLevel: field.rLevelMax,
21925
+ maxDefinitionLevel: field.dLevelMax,
21926
+ compression,
21927
+ valueCount: Number(metadata.num_values),
21928
+ dictionary,
21929
+ pages: Object.freeze(pages)
21930
+ });
21931
+ }
21599
21932
  /** Decrypts the length-prefixed page header and data modules in one column chunk. */
21600
21933
  async decryptColumnPages(encryptedPages, context, rowGroupOrdinal, columnOrdinal, keyMetadata, includesDictionary = false, dataPageOrdinalStart = 0) {
21601
21934
  if (!this.encryptionContext || !this.props.keyRetriever) {
@@ -22419,6 +22752,7 @@ var init_parquet_source_loader = __esm({
22419
22752
  init_src5();
22420
22753
  init_src2();
22421
22754
  init_src3();
22755
+ init_src4();
22422
22756
  init_get_parquet_schema();
22423
22757
  init_geoparquet_covering();
22424
22758
  init_parquet_bloom_filter();
@@ -22572,6 +22906,73 @@ var init_parquet_source_loader = __esm({
22572
22906
  scan(options = {}) {
22573
22907
  return this.read(options);
22574
22908
  }
22909
+ /**
22910
+ * Reads candidate encoded pages without decoding values or constructing Arrow arrays.
22911
+ *
22912
+ * Footer statistics and Bloom filters prune complete row groups. Any exact predicate or spatial
22913
+ * filter is returned as residual work, and its hidden columns are included in the page batch.
22914
+ */
22915
+ async *readPages(options = {}) {
22916
+ const readOptions = this.getReadOptions({
22917
+ rowGroups: options.rowGroups,
22918
+ columns: options.columns,
22919
+ rowGroupFilter: options.rowGroupFilter,
22920
+ predicate: options.predicate,
22921
+ bbox: options.bbox,
22922
+ geometryColumn: options.geometryColumn,
22923
+ signal: options.signal
22924
+ });
22925
+ const readContext = createReadAbortContext(readOptions.signal);
22926
+ this.activeReadControllers.add(readContext.abortController);
22927
+ try {
22928
+ const initialization = await this.getInitialization(readContext.abortController.signal);
22929
+ await this.getCompressionInitialization();
22930
+ throwIfAborted2(readContext.abortController.signal);
22931
+ const physicalPlan = await this.planRowGroups(
22932
+ initialization,
22933
+ readOptions,
22934
+ readContext.abortController.signal
22935
+ );
22936
+ const projectedColumns = normalizeColumns(readOptions.columns, initialization.schema);
22937
+ const predicateColumns = physicalPlan.predicate ? getParquetPredicateColumns(physicalPlan.predicate) : [];
22938
+ const geoMetadata = readOptions.bbox ? getGeoMetadata(initialization.schema.metadata) : void 0;
22939
+ const geometryColumn = readOptions.bbox ? readOptions.geometryColumn || (geoMetadata == null ? void 0 : geoMetadata.primary_column) : void 0;
22940
+ const filterColumns = [
22941
+ .../* @__PURE__ */ new Set([...predicateColumns, ...geometryColumn ? [geometryColumn] : []])
22942
+ ];
22943
+ const decodedColumns = projectedColumns.length === 0 ? [] : [.../* @__PURE__ */ new Set([...projectedColumns, ...filterColumns])];
22944
+ const columnList = decodedColumns.map((column) => [column]);
22945
+ const preserveCompression = new Set(options.preserveCompression ?? []);
22946
+ const residualFilter = readOptions.predicate || readOptions.bbox ? Object.freeze({
22947
+ predicate: readOptions.predicate,
22948
+ bbox: readOptions.bbox,
22949
+ geometryColumn
22950
+ }) : void 0;
22951
+ for (const rowGroupIndex of physicalPlan.rowGroupIndices) {
22952
+ throwIfAborted2(readContext.abortController.signal);
22953
+ const columns = await initialization.reader.readRowGroupEncodedPages(
22954
+ initialization.parquetSchema,
22955
+ initialization.fileMetadata.row_groups[rowGroupIndex],
22956
+ columnList,
22957
+ preserveCompression,
22958
+ readContext.abortController.signal,
22959
+ rowGroupIndex
22960
+ );
22961
+ yield Object.freeze({
22962
+ shape: "parquet-encoded-pages",
22963
+ rowGroup: initialization.metadata.rowGroups[rowGroupIndex],
22964
+ projectedColumns: Object.freeze([...projectedColumns]),
22965
+ filterColumns: Object.freeze(filterColumns),
22966
+ columns,
22967
+ residualFilter
22968
+ });
22969
+ }
22970
+ } finally {
22971
+ readContext.abortController.abort();
22972
+ readContext.removeSignalListener();
22973
+ this.activeReadControllers.delete(readContext.abortController);
22974
+ }
22975
+ }
22575
22976
  /** Returns a copy of cumulative transport, decode, conversion, and pruning telemetry. */
22576
22977
  getTelemetry() {
22577
22978
  return Object.freeze({ ...this.telemetry });
@@ -24021,7 +24422,7 @@ var HudiTableSource = class extends DataSource {
24021
24422
  }
24022
24423
  async loadDescriptor(signal) {
24023
24424
  var _a;
24024
- const text = typeof this.data === "string" ? await (await this.fetch(this.data, { headers: (_a = this.options.hudi) == null ? void 0 : _a.headers, signal })).text() : await this.data.text();
24425
+ const text = typeof this.data === "string" ? await (await this.fetch(this.url, { headers: (_a = this.options.hudi) == null ? void 0 : _a.headers, signal })).text() : await this.data.text();
24025
24426
  let descriptor;
24026
24427
  try {
24027
24428
  descriptor = JSON.parse(text);
@@ -24032,6 +24433,24 @@ var HudiTableSource = class extends DataSource {
24032
24433
  if (!Array.isArray(files)) {
24033
24434
  throw new Error("Hudi snapshot descriptor must contain a files array");
24034
24435
  }
24436
+ for (const [index, file] of files.entries()) {
24437
+ if (!file || typeof file !== "object" || Array.isArray(file)) {
24438
+ throw new Error(`Hudi snapshot file at index ${index} must be an object`);
24439
+ }
24440
+ const value2 = file;
24441
+ if (typeof value2.path !== "string" || !value2.path) {
24442
+ throw new Error(`Hudi snapshot file at index ${index} must contain a non-empty string path`);
24443
+ }
24444
+ if (value2.size !== void 0 && (typeof value2.size !== "number" || !Number.isFinite(value2.size))) {
24445
+ throw new Error(`Hudi snapshot file at index ${index} size must be a finite number`);
24446
+ }
24447
+ if (value2.numRecords !== void 0 && (typeof value2.numRecords !== "number" || !Number.isFinite(value2.numRecords))) {
24448
+ throw new Error(`Hudi snapshot file at index ${index} numRecords must be a finite number`);
24449
+ }
24450
+ if (value2.partitionValues !== void 0 && (!value2.partitionValues || typeof value2.partitionValues !== "object" || Array.isArray(value2.partitionValues))) {
24451
+ throw new Error(`Hudi snapshot file at index ${index} partitionValues must be an object`);
24452
+ }
24453
+ }
24035
24454
  const value = descriptor;
24036
24455
  if (value.tableType && value.tableType !== "COPY_ON_WRITE" && value.tableType !== "MERGE_ON_READ") {
24037
24456
  throw new Error(`Unsupported Hudi table type: ${String(value.tableType)}`);