@loaders.gl/parquet 5.0.0-alpha.2 → 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/LICENSE +1 -1
- package/dist/bundled.d.ts +1 -1
- package/dist/bundled.d.ts.map +1 -1
- package/dist/bundled.js.map +1 -1
- package/dist/delta-format.d.ts +9 -0
- package/dist/delta-format.d.ts.map +1 -0
- package/dist/delta-format.js +12 -0
- package/dist/delta-format.js.map +1 -0
- package/dist/delta-source-loader-types.d.ts +27 -0
- package/dist/delta-source-loader-types.d.ts.map +1 -0
- package/dist/delta-source-loader-types.js +28 -0
- package/dist/delta-source-loader-types.js.map +1 -0
- package/dist/delta-source.d.ts +48 -0
- package/dist/delta-source.d.ts.map +1 -0
- package/dist/delta-source.js +222 -0
- package/dist/delta-source.js.map +1 -0
- package/dist/delta-types.d.ts +38 -0
- package/dist/delta-types.d.ts.map +1 -0
- package/dist/delta-types.js +5 -0
- package/dist/delta-types.js.map +1 -0
- package/dist/geoparquet-loader.js +1 -1
- package/dist/iceberg-rest-catalog.d.ts +49 -0
- package/dist/iceberg-rest-catalog.d.ts.map +1 -0
- package/dist/iceberg-rest-catalog.js +78 -0
- package/dist/iceberg-rest-catalog.js.map +1 -0
- package/dist/iceberg-table-source.d.ts +63 -0
- package/dist/iceberg-table-source.d.ts.map +1 -0
- package/dist/iceberg-table-source.js +797 -0
- package/dist/iceberg-table-source.js.map +1 -0
- package/dist/iceberg-types.d.ts +150 -0
- package/dist/iceberg-types.d.ts.map +1 -0
- package/dist/iceberg-types.js +5 -0
- package/dist/iceberg-types.js.map +1 -0
- package/dist/index.cjs +15841 -3306
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/arrow/convert-schema-from-parquet.d.ts +3 -1
- package/dist/lib/arrow/convert-schema-from-parquet.d.ts.map +1 -1
- package/dist/lib/arrow/convert-schema-from-parquet.js +94 -19
- package/dist/lib/arrow/convert-schema-from-parquet.js.map +1 -1
- package/dist/lib/arrow/create-nested-arrow-vector.js +89 -0
- package/dist/lib/arrow/create-nested-arrow-vector.js.map +1 -1
- package/dist/lib/constants.js +1 -1
- package/dist/lib/encoders/encode-table-to-parquet-js.d.ts.map +1 -1
- package/dist/lib/encoders/encode-table-to-parquet-js.js +202 -7
- package/dist/lib/encoders/encode-table-to-parquet-js.js.map +1 -1
- package/dist/lib/geo/geoparquet-covering.d.ts +19 -0
- package/dist/lib/geo/geoparquet-covering.d.ts.map +1 -0
- package/dist/lib/geo/geoparquet-covering.js +137 -0
- package/dist/lib/geo/geoparquet-covering.js.map +1 -0
- package/dist/lib/geo/geospatial-metadata.d.ts.map +1 -1
- package/dist/lib/geo/geospatial-metadata.js +39 -13
- package/dist/lib/geo/geospatial-metadata.js.map +1 -1
- package/dist/lib/parquet-bloom-filter-planner.d.ts +16 -0
- package/dist/lib/parquet-bloom-filter-planner.d.ts.map +1 -0
- package/dist/lib/parquet-bloom-filter-planner.js +57 -0
- package/dist/lib/parquet-bloom-filter-planner.js.map +1 -0
- package/dist/lib/parquet-bloom-filter.d.ts +30 -0
- package/dist/lib/parquet-bloom-filter.d.ts.map +1 -0
- package/dist/lib/parquet-bloom-filter.js +289 -0
- package/dist/lib/parquet-bloom-filter.js.map +1 -0
- package/dist/lib/parquet-encryption.d.ts +80 -0
- package/dist/lib/parquet-encryption.d.ts.map +1 -0
- package/dist/lib/parquet-encryption.js +190 -0
- package/dist/lib/parquet-encryption.js.map +1 -0
- package/dist/lib/parquet-page-index.d.ts +34 -5
- package/dist/lib/parquet-page-index.d.ts.map +1 -1
- package/dist/lib/parquet-page-index.js +114 -28
- package/dist/lib/parquet-page-index.js.map +1 -1
- package/dist/lib/parquet-predicate.d.ts +5 -1
- package/dist/lib/parquet-predicate.d.ts.map +1 -1
- package/dist/lib/parquet-predicate.js +42 -14
- package/dist/lib/parquet-predicate.js.map +1 -1
- package/dist/lib/parquet-source-worker-decoder.d.ts +4 -1
- package/dist/lib/parquet-source-worker-decoder.d.ts.map +1 -1
- package/dist/lib/parquet-source-worker-decoder.js +83 -17
- package/dist/lib/parquet-source-worker-decoder.js.map +1 -1
- package/dist/lib/parquet-source-worker-types.d.ts +24 -0
- package/dist/lib/parquet-source-worker-types.d.ts.map +1 -1
- package/dist/lib/parsers/get-parquet-schema.d.ts.map +1 -1
- package/dist/lib/parsers/get-parquet-schema.js +3 -1
- package/dist/lib/parsers/get-parquet-schema.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow-js.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow-js.js +327 -18
- package/dist/lib/parsers/parse-parquet-to-arrow-js.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow.js +5 -5
- package/dist/lib/parsers/parse-parquet-to-arrow.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-columns.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-columns.js +3 -1
- package/dist/lib/parsers/parse-parquet-to-columns.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-json.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-json.js +18 -2
- package/dist/lib/parsers/parse-parquet-to-json.js.map +1 -1
- package/dist/lib/slice-parquet-batch.d.ts +9 -0
- package/dist/lib/slice-parquet-batch.d.ts.map +1 -0
- package/dist/lib/slice-parquet-batch.js +28 -0
- package/dist/lib/slice-parquet-batch.js.map +1 -0
- package/dist/lib/sources/parquet-range-file.d.ts +1 -1
- package/dist/lib/sources/parquet-range-file.d.ts.map +1 -1
- package/dist/lib/sources/parquet-range-file.js +28 -22
- package/dist/lib/sources/parquet-range-file.js.map +1 -1
- package/dist/lib/utils/normalize-parquet-options.d.ts.map +1 -1
- package/dist/lib/utils/normalize-parquet-options.js +15 -1
- package/dist/lib/utils/normalize-parquet-options.js.map +1 -1
- package/dist/parquet-dataset-source.cjs +16528 -4928
- package/dist/parquet-dataset-source.cjs.map +3 -3
- package/dist/parquet-dataset-source.d.ts +31 -4
- package/dist/parquet-dataset-source.d.ts.map +1 -1
- package/dist/parquet-dataset-source.js +296 -74
- package/dist/parquet-dataset-source.js.map +1 -1
- package/dist/parquet-encoded-page-types.d.ts +108 -0
- package/dist/parquet-encoded-page-types.d.ts.map +1 -0
- package/dist/parquet-encoded-page-types.js +5 -0
- package/dist/parquet-encoded-page-types.js.map +1 -0
- package/dist/parquet-js-loader-types.d.ts +2 -0
- package/dist/parquet-js-loader-types.d.ts.map +1 -1
- package/dist/parquet-js-loader-types.js +2 -1
- package/dist/parquet-js-loader-types.js.map +1 -1
- package/dist/parquet-js-loader.d.ts +1 -0
- package/dist/parquet-js-loader.d.ts.map +1 -1
- package/dist/parquet-js-loader.js +2 -1
- package/dist/parquet-js-loader.js.map +1 -1
- package/dist/parquet-js-writer.d.ts +23 -2
- package/dist/parquet-js-writer.d.ts.map +1 -1
- package/dist/parquet-js-writer.js +1 -1
- package/dist/parquet-js-writer.js.map +1 -1
- package/dist/parquet-loader-base.js +1 -1
- package/dist/parquet-loader-options.d.ts +11 -0
- package/dist/parquet-loader-options.d.ts.map +1 -1
- package/dist/parquet-loader-options.js.map +1 -1
- package/dist/parquet-source-capabilities.d.ts +8 -1
- package/dist/parquet-source-capabilities.d.ts.map +1 -1
- package/dist/parquet-source-capabilities.js +10 -0
- package/dist/parquet-source-capabilities.js.map +1 -1
- package/dist/parquet-source-loader-types.d.ts +10 -0
- package/dist/parquet-source-loader-types.d.ts.map +1 -1
- package/dist/parquet-source-loader-types.js +11 -1
- package/dist/parquet-source-loader-types.js.map +1 -1
- package/dist/parquet-source-loader.cjs +14121 -2796
- package/dist/parquet-source-loader.cjs.map +3 -3
- package/dist/parquet-source-loader.d.ts +51 -4
- package/dist/parquet-source-loader.d.ts.map +1 -1
- package/dist/parquet-source-loader.js +651 -38
- package/dist/parquet-source-loader.js.map +1 -1
- package/dist/parquet-source-types.d.ts +180 -30
- package/dist/parquet-source-types.d.ts.map +1 -1
- package/dist/parquet-source-worker.js +7378 -6989
- package/dist/parquet-source-worker.js.map +4 -4
- package/dist/parquet-worker-node.cjs +8501 -1045
- package/dist/parquet-worker-node.cjs.map +4 -4
- package/dist/parquet-worker-url.js +5 -1
- package/dist/parquet-worker-url.js.map +1 -1
- package/dist/parquet-worker.js +289 -218
- package/dist/parquet-worker.js.map +4 -4
- package/dist/parquetjs/codecs/declare.d.ts +15 -0
- package/dist/parquetjs/codecs/declare.d.ts.map +1 -1
- package/dist/parquetjs/codecs/declare.js +10 -0
- package/dist/parquetjs/codecs/declare.js.map +1 -1
- package/dist/parquetjs/codecs/delta.d.ts.map +1 -1
- package/dist/parquetjs/codecs/delta.js +356 -7
- package/dist/parquetjs/codecs/delta.js.map +1 -1
- package/dist/parquetjs/codecs/index.d.ts.map +1 -1
- package/dist/parquetjs/codecs/index.js +4 -0
- package/dist/parquetjs/codecs/index.js.map +1 -1
- package/dist/parquetjs/codecs/plain.d.ts +1 -1
- package/dist/parquetjs/codecs/plain.d.ts.map +1 -1
- package/dist/parquetjs/codecs/plain.js +153 -12
- package/dist/parquetjs/codecs/plain.js.map +1 -1
- package/dist/parquetjs/codecs/rle.d.ts +4 -0
- package/dist/parquetjs/codecs/rle.d.ts.map +1 -1
- package/dist/parquetjs/codecs/rle.js +406 -3
- package/dist/parquetjs/codecs/rle.js.map +1 -1
- package/dist/parquetjs/compression.d.ts +9 -0
- package/dist/parquetjs/compression.d.ts.map +1 -1
- package/dist/parquetjs/compression.js +86 -67
- package/dist/parquetjs/compression.js.map +1 -1
- package/dist/parquetjs/encoder/dictionary-planner.d.ts.map +1 -1
- package/dist/parquetjs/encoder/dictionary-planner.js +5 -2
- package/dist/parquetjs/encoder/dictionary-planner.js.map +1 -1
- package/dist/parquetjs/encoder/parquet-encoder.d.ts +43 -1
- package/dist/parquetjs/encoder/parquet-encoder.d.ts.map +1 -1
- package/dist/parquetjs/encoder/parquet-encoder.js +691 -34
- package/dist/parquetjs/encoder/parquet-encoder.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts +29 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.js +85 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts +5 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnChunk.js +35 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts +35 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js +135 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts +10 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.js +73 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts +22 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js +111 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts +16 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js +57 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts +5 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/FileMetaData.js +35 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts +18 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js +62 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts +26 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.js +85 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/index.d.ts +6 -0
- package/dist/parquetjs/parquet-thrift/index.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/index.js +6 -0
- package/dist/parquetjs/parquet-thrift/index.js.map +1 -1
- package/dist/parquetjs/parser/decoders.d.ts +10 -1
- package/dist/parquetjs/parser/decoders.d.ts.map +1 -1
- package/dist/parquetjs/parser/decoders.js +318 -14
- package/dist/parquetjs/parser/decoders.js.map +1 -1
- package/dist/parquetjs/parser/encoded-pages.d.ts +24 -0
- package/dist/parquetjs/parser/encoded-pages.d.ts.map +1 -0
- package/dist/parquetjs/parser/encoded-pages.js +206 -0
- package/dist/parquetjs/parser/encoded-pages.js.map +1 -0
- package/dist/parquetjs/parser/parquet-reader.d.ts +88 -12
- package/dist/parquetjs/parser/parquet-reader.d.ts.map +1 -1
- package/dist/parquetjs/parser/parquet-reader.js +713 -66
- package/dist/parquetjs/parser/parquet-reader.js.map +1 -1
- package/dist/parquetjs/schema/declare.d.ts +22 -3
- package/dist/parquetjs/schema/declare.d.ts.map +1 -1
- package/dist/parquetjs/schema/declare.js.map +1 -1
- package/dist/parquetjs/schema/schema.d.ts.map +1 -1
- package/dist/parquetjs/schema/schema.js +10 -0
- package/dist/parquetjs/schema/schema.js.map +1 -1
- package/dist/parquetjs/schema/shred.d.ts.map +1 -1
- package/dist/parquetjs/schema/shred.js +219 -11
- package/dist/parquetjs/schema/shred.js.map +1 -1
- package/dist/parquetjs/schema/types.js +19 -21
- package/dist/parquetjs/schema/types.js.map +1 -1
- package/dist/parquetjs/schema/variant.d.ts +3 -0
- package/dist/parquetjs/schema/variant.d.ts.map +1 -0
- package/dist/parquetjs/schema/variant.js +248 -0
- package/dist/parquetjs/schema/variant.js.map +1 -0
- package/dist/parquetjs/utils/crc32.d.ts +3 -0
- package/dist/parquetjs/utils/crc32.d.ts.map +1 -0
- package/dist/parquetjs/utils/crc32.js +15 -0
- package/dist/parquetjs/utils/crc32.js.map +1 -0
- package/dist/parquetjs/utils/read-utils.d.ts +11 -1
- package/dist/parquetjs/utils/read-utils.d.ts.map +1 -1
- package/dist/parquetjs/utils/read-utils.js +21 -1
- package/dist/parquetjs/utils/read-utils.js.map +1 -1
- package/dist/unbundled.d.ts +2 -1
- package/dist/unbundled.d.ts.map +1 -1
- package/dist/unbundled.js +1 -0
- package/dist/unbundled.js.map +1 -1
- package/package.json +36 -13
- package/src/bundled.ts +10 -0
- package/src/delta-format.ts +12 -0
- package/src/delta-source-loader-types.ts +40 -0
- package/src/delta-source.ts +305 -0
- package/src/delta-types.ts +40 -0
- package/src/iceberg-rest-catalog.ts +122 -0
- package/src/iceberg-table-source.ts +1037 -0
- package/src/iceberg-types.ts +165 -0
- package/src/index.ts +59 -1
- package/src/lib/arrow/convert-schema-from-parquet.ts +113 -19
- package/src/lib/arrow/create-nested-arrow-vector.ts +116 -0
- package/src/lib/encoders/encode-table-to-parquet-js.ts +268 -7
- package/src/lib/geo/geoparquet-covering.ts +201 -0
- package/src/lib/geo/geospatial-metadata.ts +42 -15
- package/src/lib/parquet-bloom-filter-planner.ts +86 -0
- package/src/lib/parquet-bloom-filter.ts +345 -0
- package/src/lib/parquet-encryption.ts +344 -0
- package/src/lib/parquet-page-index.ts +180 -34
- package/src/lib/parquet-predicate.ts +52 -16
- package/src/lib/parquet-source-worker-decoder.ts +116 -20
- package/src/lib/parquet-source-worker-types.ts +25 -0
- package/src/lib/parsers/get-parquet-schema.ts +3 -1
- package/src/lib/parsers/parse-parquet-to-arrow-js.ts +397 -17
- package/src/lib/parsers/parse-parquet-to-arrow.ts +4 -5
- package/src/lib/parsers/parse-parquet-to-columns.ts +3 -1
- package/src/lib/parsers/parse-parquet-to-json.ts +18 -2
- package/src/lib/slice-parquet-batch.ts +32 -0
- package/src/lib/sources/parquet-range-file.ts +35 -29
- package/src/lib/utils/normalize-parquet-options.ts +17 -1
- package/src/parquet-dataset-source.ts +397 -85
- package/src/parquet-encoded-page-types.ts +122 -0
- package/src/parquet-js-loader-types.ts +1 -0
- package/src/parquet-js-loader.ts +2 -1
- package/src/parquet-js-writer.ts +30 -0
- package/src/parquet-loader-options.ts +11 -0
- package/src/parquet-source-capabilities.ts +18 -1
- package/src/parquet-source-loader-types.ts +10 -0
- package/src/parquet-source-loader.ts +1024 -52
- package/src/parquet-source-types.ts +197 -28
- package/src/parquet-worker-url.ts +6 -1
- package/src/parquetjs/codecs/declare.ts +27 -0
- package/src/parquetjs/codecs/delta.ts +466 -6
- package/src/parquetjs/codecs/index.ts +4 -0
- package/src/parquetjs/codecs/plain.ts +177 -11
- package/src/parquetjs/codecs/rle.ts +573 -3
- package/src/parquetjs/compression.ts +102 -76
- package/src/parquetjs/encoder/dictionary-planner.ts +7 -2
- package/src/parquetjs/encoder/parquet-encoder.ts +1016 -38
- package/src/parquetjs/parquet-thrift/BoundingBox.ts +108 -0
- package/src/parquetjs/parquet-thrift/ColumnChunk.ts +35 -0
- package/src/parquetjs/parquet-thrift/ColumnCryptoMetaData.ts +139 -0
- package/src/parquetjs/parquet-thrift/ColumnMetaData.ts +73 -0
- package/src/parquetjs/parquet-thrift/EncryptionAlgorithm.ts +127 -0
- package/src/parquetjs/parquet-thrift/FileCryptoMetaData.ts +60 -0
- package/src/parquetjs/parquet-thrift/FileMetaData.ts +35 -0
- package/src/parquetjs/parquet-thrift/GeospatialStatistics.ts +68 -0
- package/src/parquetjs/parquet-thrift/SizeStatistics.ts +98 -0
- package/src/parquetjs/parquet-thrift/index.ts +6 -0
- package/src/parquetjs/parser/decoders.ts +451 -26
- package/src/parquetjs/parser/encoded-pages.ts +278 -0
- package/src/parquetjs/parser/parquet-reader.ts +1112 -87
- package/src/parquetjs/schema/declare.ts +22 -2
- package/src/parquetjs/schema/schema.ts +10 -0
- package/src/parquetjs/schema/shred.ts +238 -11
- package/src/parquetjs/schema/types.ts +16 -25
- package/src/parquetjs/schema/variant.ts +313 -0
- package/src/parquetjs/utils/crc32.ts +15 -0
- package/src/parquetjs/utils/read-utils.ts +26 -1
- package/src/unbundled.ts +14 -0
|
@@ -106,6 +106,13 @@ export async function parseParquetFileToArrowWithJs(
|
|
|
106
106
|
file: ReadableFile,
|
|
107
107
|
options?: ParquetJSLoaderOptions
|
|
108
108
|
): Promise<ArrowTable> {
|
|
109
|
+
if (
|
|
110
|
+
!options?.parquet?.offset &&
|
|
111
|
+
options?.parquet?.limit === undefined &&
|
|
112
|
+
options?.parquet?.batchSize === undefined
|
|
113
|
+
) {
|
|
114
|
+
return await parseCompleteParquetFileToArrowWithJs(file, options);
|
|
115
|
+
}
|
|
109
116
|
const recordBatches: arrow.RecordBatch[] = [];
|
|
110
117
|
let schema: Schema | undefined;
|
|
111
118
|
|
|
@@ -121,13 +128,64 @@ export async function parseParquetFileToArrowWithJs(
|
|
|
121
128
|
return {shape: 'arrow-table', data: table, schema};
|
|
122
129
|
}
|
|
123
130
|
|
|
131
|
+
/** Parses complete row groups directly, bypassing batch slicing and wrapper reconstruction. */
|
|
132
|
+
async function parseCompleteParquetFileToArrowWithJs(
|
|
133
|
+
file: ReadableFile,
|
|
134
|
+
options?: ParquetJSLoaderOptions
|
|
135
|
+
): Promise<ArrowTable> {
|
|
136
|
+
await preloadCompressions(options);
|
|
137
|
+
const reader = new ParquetReader(file, {
|
|
138
|
+
preserveBinary: options?.parquet?.preserveBinary,
|
|
139
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp ?? true,
|
|
140
|
+
retainByteArrayViews: true,
|
|
141
|
+
useTypedValueBuffers: true,
|
|
142
|
+
useTypedLevelBuffers: true,
|
|
143
|
+
useArrowByteArrayBuffers: true,
|
|
144
|
+
verifyFooterSignature: options?.parquet?.verifyFooterSignature,
|
|
145
|
+
keyRetriever: options?.parquet?.keyRetriever,
|
|
146
|
+
aadPrefix: options?.parquet?.aadPrefix
|
|
147
|
+
});
|
|
148
|
+
const schema = projectSchema(await getSchemaFromParquetReader(reader), options?.parquet?.columns);
|
|
149
|
+
const arrowSchema = createParquetArrowSchema(schema);
|
|
150
|
+
const parquetSchema = await reader.getSchema();
|
|
151
|
+
const recordBatches: arrow.RecordBatch[] = [];
|
|
152
|
+
let onlyTable: ArrowTable | undefined;
|
|
153
|
+
|
|
154
|
+
for await (const rowGroup of reader.rowGroupIterator(getParquetIterationProps(options))) {
|
|
155
|
+
const table = convertRowGroupSliceToArrow(
|
|
156
|
+
schema,
|
|
157
|
+
arrowSchema,
|
|
158
|
+
parquetSchema,
|
|
159
|
+
rowGroup,
|
|
160
|
+
0,
|
|
161
|
+
rowGroup.rowCount
|
|
162
|
+
);
|
|
163
|
+
onlyTable = recordBatches.length === 0 ? table : undefined;
|
|
164
|
+
recordBatches.push(...table.data.batches);
|
|
165
|
+
}
|
|
166
|
+
if (onlyTable && recordBatches.length === onlyTable.data.batches.length) {
|
|
167
|
+
return onlyTable;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
shape: 'arrow-table',
|
|
171
|
+
schema,
|
|
172
|
+
data: recordBatches.length
|
|
173
|
+
? new arrow.Table(recordBatches)
|
|
174
|
+
: new arrow.Table(createParquetArrowSchema(schema), [])
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
124
178
|
/** Reads the projected loaders.gl schema when row selection produces no Arrow record batches. */
|
|
125
179
|
async function readProjectedSchema(
|
|
126
180
|
file: ReadableFile,
|
|
127
181
|
options?: ParquetJSLoaderOptions
|
|
128
182
|
): Promise<Schema> {
|
|
129
183
|
const reader = new ParquetReader(file, {
|
|
130
|
-
preserveBinary: options?.parquet?.preserveBinary
|
|
184
|
+
preserveBinary: options?.parquet?.preserveBinary,
|
|
185
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp ?? true,
|
|
186
|
+
verifyFooterSignature: options?.parquet?.verifyFooterSignature,
|
|
187
|
+
keyRetriever: options?.parquet?.keyRetriever,
|
|
188
|
+
aadPrefix: options?.parquet?.aadPrefix
|
|
131
189
|
});
|
|
132
190
|
return projectSchema(await getSchemaFromParquetReader(reader), options?.parquet?.columns);
|
|
133
191
|
}
|
|
@@ -147,9 +205,14 @@ export async function* parseParquetFileToArrowInBatchesWithJs(
|
|
|
147
205
|
|
|
148
206
|
const reader = new ParquetReader(file, {
|
|
149
207
|
preserveBinary: options?.parquet?.preserveBinary,
|
|
208
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp ?? true,
|
|
150
209
|
retainByteArrayViews: true,
|
|
151
210
|
useTypedValueBuffers: true,
|
|
152
|
-
useTypedLevelBuffers: true
|
|
211
|
+
useTypedLevelBuffers: true,
|
|
212
|
+
useArrowByteArrayBuffers: true,
|
|
213
|
+
verifyFooterSignature: options?.parquet?.verifyFooterSignature,
|
|
214
|
+
keyRetriever: options?.parquet?.keyRetriever,
|
|
215
|
+
aadPrefix: options?.parquet?.aadPrefix
|
|
153
216
|
});
|
|
154
217
|
const schema = projectSchema(await getSchemaFromParquetReader(reader), options?.parquet?.columns);
|
|
155
218
|
const arrowSchema = createParquetArrowSchema(schema);
|
|
@@ -298,6 +361,14 @@ function convertRowGroupSliceToArrow(
|
|
|
298
361
|
}
|
|
299
362
|
|
|
300
363
|
let fullColumn = materializeColumn(parquetSchema, rowGroup, field.name);
|
|
364
|
+
if (parquetField.fields && hasStandardNestedCollection(parquetField)) {
|
|
365
|
+
materializedRows ||= materializeRows(parquetSchema, rowGroup);
|
|
366
|
+
const normalizedValues = materializedRows
|
|
367
|
+
.slice(start, end)
|
|
368
|
+
.map(row => normalizeNestedParquetValue(row[field.name], parquetField));
|
|
369
|
+
vectors[field.name] = arrow.vectorFromArray(normalizedValues, field.type);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
301
372
|
if (!fullColumn && parquetField.fields) {
|
|
302
373
|
materializedRows ||= materializeRows(parquetSchema, rowGroup);
|
|
303
374
|
const fallbackTable: ObjectRowTable = {
|
|
@@ -331,6 +402,76 @@ function convertRowGroupSliceToArrow(
|
|
|
331
402
|
};
|
|
332
403
|
}
|
|
333
404
|
|
|
405
|
+
/** Detects standard collection wrappers that need normalization before Arrow conversion. */
|
|
406
|
+
function hasStandardNestedCollection(field: ParquetField): boolean {
|
|
407
|
+
if (field.logicalType?.type === 'LIST') {
|
|
408
|
+
const element = field.fields?.list?.fields?.element;
|
|
409
|
+
if (!element) return false;
|
|
410
|
+
// Nested repeated continuation is still handled by the legacy materializer;
|
|
411
|
+
// only normalize one-level collections here until that path is fully aligned.
|
|
412
|
+
if (element.logicalType?.type === 'LIST' || element.logicalType?.type === 'MAP') return false;
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
if (field.logicalType?.type === 'MAP') {
|
|
416
|
+
return Boolean(field.fields?.key_value?.fields?.key && field.fields.key_value.fields.value);
|
|
417
|
+
}
|
|
418
|
+
return Object.values(field.fields || {}).some(hasStandardNestedCollection);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/** Normalizes standard Parquet LIST/MAP wrapper groups before Arrow conversion. */
|
|
422
|
+
function normalizeNestedParquetValue(value: unknown, field: ParquetField): unknown {
|
|
423
|
+
if (value === undefined || value === null || !field.fields) {
|
|
424
|
+
return value;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (field.logicalType?.type === 'LIST') {
|
|
428
|
+
const listField = field.fields.list;
|
|
429
|
+
const elementField = listField?.fields?.element;
|
|
430
|
+
if (!listField || !elementField) {
|
|
431
|
+
return value;
|
|
432
|
+
}
|
|
433
|
+
const listValue = value && typeof value === 'object' ? Reflect.get(value, 'list') : undefined;
|
|
434
|
+
if (!Array.isArray(listValue)) {
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
437
|
+
return listValue.map(element =>
|
|
438
|
+
normalizeNestedParquetValue(
|
|
439
|
+
element && typeof element === 'object' ? Reflect.get(element, 'element') : element,
|
|
440
|
+
elementField
|
|
441
|
+
)
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (field.logicalType?.type === 'MAP') {
|
|
446
|
+
const entryField = field.fields.key_value;
|
|
447
|
+
const keyField = entryField?.fields?.key;
|
|
448
|
+
const valueField = entryField?.fields?.value;
|
|
449
|
+
if (!entryField || !keyField || !valueField) {
|
|
450
|
+
return value;
|
|
451
|
+
}
|
|
452
|
+
const entries =
|
|
453
|
+
value && typeof value === 'object' ? Reflect.get(value, 'key_value') : undefined;
|
|
454
|
+
if (!Array.isArray(entries)) {
|
|
455
|
+
return new Map();
|
|
456
|
+
}
|
|
457
|
+
return new Map(
|
|
458
|
+
entries.map(entry => [
|
|
459
|
+
Reflect.get(entry, 'key'),
|
|
460
|
+
normalizeNestedParquetValue(Reflect.get(entry, 'value'), valueField)
|
|
461
|
+
])
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (typeof value !== 'object' || Array.isArray(value) || ArrayBuffer.isView(value)) {
|
|
466
|
+
return value;
|
|
467
|
+
}
|
|
468
|
+
const normalized: Record<string, unknown> = {};
|
|
469
|
+
for (const [name, childField] of Object.entries(field.fields)) {
|
|
470
|
+
normalized[name] = normalizeNestedParquetValue(Reflect.get(value, name), childField);
|
|
471
|
+
}
|
|
472
|
+
return normalized;
|
|
473
|
+
}
|
|
474
|
+
|
|
334
475
|
/** Creates an exact Arrow Decimal128/256 vector from unscaled Parquet decimal values. */
|
|
335
476
|
function createDecimalArrowVector(
|
|
336
477
|
arrowType: arrow.DataType,
|
|
@@ -497,6 +638,19 @@ function createRawPrimitiveArrowVector(
|
|
|
497
638
|
start,
|
|
498
639
|
end
|
|
499
640
|
);
|
|
641
|
+
const expandedData = directData
|
|
642
|
+
? undefined
|
|
643
|
+
: createExpandedRawPrimitiveArrowArrayView(arrowType, parquetField, columnData, start, end);
|
|
644
|
+
if (expandedData) {
|
|
645
|
+
return new arrow.Vector([
|
|
646
|
+
arrow.makeData({
|
|
647
|
+
type: arrowType,
|
|
648
|
+
data: expandedData.data,
|
|
649
|
+
nullBitmap: expandedData.nullBitmap,
|
|
650
|
+
nullCount: expandedData.nullCount
|
|
651
|
+
} as any)
|
|
652
|
+
]);
|
|
653
|
+
}
|
|
500
654
|
const data = directData || createRawPrimitiveArrowArray(arrowType, parquetField, rowCount);
|
|
501
655
|
if (!data) {
|
|
502
656
|
return undefined;
|
|
@@ -536,6 +690,58 @@ function createRawPrimitiveArrowVector(
|
|
|
536
690
|
]);
|
|
537
691
|
}
|
|
538
692
|
|
|
693
|
+
/**
|
|
694
|
+
* Expands a full nullable primitive column in place into the decoder's row-capacity buffer.
|
|
695
|
+
*
|
|
696
|
+
* Parquet omits physical values for null rows, but the decoder allocates from the column's level
|
|
697
|
+
* count. Walking backwards makes the overlapping expansion safe while building Arrow validity.
|
|
698
|
+
*/
|
|
699
|
+
function createExpandedRawPrimitiveArrowArrayView(
|
|
700
|
+
arrowType: arrow.DataType,
|
|
701
|
+
parquetField: ParquetField,
|
|
702
|
+
columnData: ParquetColumnChunk,
|
|
703
|
+
start: number,
|
|
704
|
+
end: number
|
|
705
|
+
):
|
|
706
|
+
| {data: RawPrimitiveArrowArray; nullBitmap: Uint8Array | undefined; nullCount: number}
|
|
707
|
+
| undefined {
|
|
708
|
+
if (
|
|
709
|
+
parquetField.repetitionType !== 'OPTIONAL' ||
|
|
710
|
+
parquetField.rLevelMax !== 0 ||
|
|
711
|
+
start !== 0 ||
|
|
712
|
+
end !== columnData.count
|
|
713
|
+
) {
|
|
714
|
+
return undefined;
|
|
715
|
+
}
|
|
716
|
+
const compactData = getMatchingRawPrimitiveArrowArray(arrowType, parquetField, columnData.values);
|
|
717
|
+
if (!compactData) {
|
|
718
|
+
return undefined;
|
|
719
|
+
}
|
|
720
|
+
if (columnData.nullCount === 0 && compactData.length === end) {
|
|
721
|
+
return {data: compactData, nullBitmap: undefined, nullCount: 0};
|
|
722
|
+
}
|
|
723
|
+
const data = createRawPrimitiveCapacityView(compactData, end);
|
|
724
|
+
if (!data) {
|
|
725
|
+
return undefined;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const nullBitmap = new Uint8Array(Math.ceil(end / 8));
|
|
729
|
+
let valueIndex = compactData.length - 1;
|
|
730
|
+
let nullCount = 0;
|
|
731
|
+
for (let rowIndex = end - 1; rowIndex >= 0; rowIndex--) {
|
|
732
|
+
if (columnData.dlevels[rowIndex] === parquetField.dLevelMax) {
|
|
733
|
+
setRawPrimitiveArrowValue(data, rowIndex, compactData[valueIndex--]);
|
|
734
|
+
nullBitmap[rowIndex >> 3] |= 1 << (rowIndex & 7);
|
|
735
|
+
} else {
|
|
736
|
+
nullCount++;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
if (valueIndex !== -1) {
|
|
740
|
+
throw new Error(`Parquet column ${parquetField.name} has inconsistent definition levels`);
|
|
741
|
+
}
|
|
742
|
+
return {data, nullBitmap: nullCount ? nullBitmap : undefined, nullCount};
|
|
743
|
+
}
|
|
744
|
+
|
|
539
745
|
/** Reuses a typed decoded column as the Arrow value buffer for required primitive fields. */
|
|
540
746
|
function createRawPrimitiveArrowArrayView(
|
|
541
747
|
arrowType: arrow.DataType,
|
|
@@ -547,20 +753,29 @@ function createRawPrimitiveArrowArrayView(
|
|
|
547
753
|
if (parquetField.repetitionType !== 'REQUIRED') {
|
|
548
754
|
return undefined;
|
|
549
755
|
}
|
|
550
|
-
const values = columnData.values;
|
|
756
|
+
const values = getMatchingRawPrimitiveArrowArray(arrowType, parquetField, columnData.values);
|
|
757
|
+
return values?.subarray(start, end) as RawPrimitiveArrowArray | undefined;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/** Returns a decoded typed value buffer when it exactly matches the target Arrow representation. */
|
|
761
|
+
function getMatchingRawPrimitiveArrowArray(
|
|
762
|
+
arrowType: arrow.DataType,
|
|
763
|
+
parquetField: ParquetField,
|
|
764
|
+
values: ParquetColumnChunk['values']
|
|
765
|
+
): RawPrimitiveArrowArray | undefined {
|
|
551
766
|
if (
|
|
552
767
|
parquetField.primitiveType === 'FLOAT' &&
|
|
553
768
|
arrowType instanceof arrow.Float32 &&
|
|
554
769
|
values instanceof Float32Array
|
|
555
770
|
) {
|
|
556
|
-
return values
|
|
771
|
+
return values;
|
|
557
772
|
}
|
|
558
773
|
if (
|
|
559
774
|
parquetField.primitiveType === 'DOUBLE' &&
|
|
560
775
|
arrowType instanceof arrow.Float64 &&
|
|
561
776
|
values instanceof Float64Array
|
|
562
777
|
) {
|
|
563
|
-
return values
|
|
778
|
+
return values;
|
|
564
779
|
}
|
|
565
780
|
if (
|
|
566
781
|
parquetField.primitiveType === 'INT32' &&
|
|
@@ -569,7 +784,7 @@ function createRawPrimitiveArrowArrayView(
|
|
|
569
784
|
arrowType instanceof arrow.TimeMillisecond) &&
|
|
570
785
|
values instanceof Int32Array
|
|
571
786
|
) {
|
|
572
|
-
return values
|
|
787
|
+
return values;
|
|
573
788
|
}
|
|
574
789
|
if (
|
|
575
790
|
parquetField.primitiveType === 'INT64' &&
|
|
@@ -581,11 +796,46 @@ function createRawPrimitiveArrowArrayView(
|
|
|
581
796
|
arrowType instanceof arrow.TimestampNanosecond) &&
|
|
582
797
|
values instanceof BigInt64Array
|
|
583
798
|
) {
|
|
584
|
-
return values
|
|
799
|
+
return values;
|
|
800
|
+
}
|
|
801
|
+
if (
|
|
802
|
+
parquetField.primitiveType === 'INT96' &&
|
|
803
|
+
arrowType instanceof arrow.TimestampNanosecond &&
|
|
804
|
+
values instanceof BigInt64Array
|
|
805
|
+
) {
|
|
806
|
+
return values;
|
|
585
807
|
}
|
|
586
808
|
return undefined;
|
|
587
809
|
}
|
|
588
810
|
|
|
811
|
+
/** Creates a larger view over the unused capacity retained by a compact decoder buffer. */
|
|
812
|
+
function createRawPrimitiveCapacityView(
|
|
813
|
+
values: RawPrimitiveArrowArray,
|
|
814
|
+
length: number
|
|
815
|
+
): RawPrimitiveArrowArray | undefined {
|
|
816
|
+
if (values.buffer.byteLength - values.byteOffset < length * values.BYTES_PER_ELEMENT) {
|
|
817
|
+
return undefined;
|
|
818
|
+
}
|
|
819
|
+
if (values instanceof Float32Array) {
|
|
820
|
+
return new Float32Array(values.buffer, values.byteOffset, length);
|
|
821
|
+
}
|
|
822
|
+
if (values instanceof Float64Array) {
|
|
823
|
+
return new Float64Array(values.buffer, values.byteOffset, length);
|
|
824
|
+
}
|
|
825
|
+
if (values instanceof Int8Array) return new Int8Array(values.buffer, values.byteOffset, length);
|
|
826
|
+
if (values instanceof Int16Array) return new Int16Array(values.buffer, values.byteOffset, length);
|
|
827
|
+
if (values instanceof Int32Array) return new Int32Array(values.buffer, values.byteOffset, length);
|
|
828
|
+
if (values instanceof Uint8Array) return new Uint8Array(values.buffer, values.byteOffset, length);
|
|
829
|
+
if (values instanceof Uint16Array)
|
|
830
|
+
return new Uint16Array(values.buffer, values.byteOffset, length);
|
|
831
|
+
if (values instanceof Uint32Array)
|
|
832
|
+
return new Uint32Array(values.buffer, values.byteOffset, length);
|
|
833
|
+
if (values instanceof BigInt64Array) {
|
|
834
|
+
return new BigInt64Array(values.buffer, values.byteOffset, length);
|
|
835
|
+
}
|
|
836
|
+
return new BigUint64Array(values.buffer, values.byteOffset, length);
|
|
837
|
+
}
|
|
838
|
+
|
|
589
839
|
/** Allocates the Arrow typed array matching an unconverted physical Parquet primitive. */
|
|
590
840
|
function createRawPrimitiveArrowArray(
|
|
591
841
|
arrowType: arrow.DataType,
|
|
@@ -632,6 +882,9 @@ function createRawPrimitiveArrowArray(
|
|
|
632
882
|
) {
|
|
633
883
|
return new BigInt64Array(rowCount);
|
|
634
884
|
}
|
|
885
|
+
if (parquetField.primitiveType === 'INT96' && arrowType instanceof arrow.TimestampNanosecond) {
|
|
886
|
+
return new BigInt64Array(rowCount);
|
|
887
|
+
}
|
|
635
888
|
if (parquetField.primitiveType === 'INT64' && arrowType instanceof arrow.Uint64) {
|
|
636
889
|
return new BigUint64Array(rowCount);
|
|
637
890
|
}
|
|
@@ -667,6 +920,9 @@ function createRawByteArrowVector(
|
|
|
667
920
|
if (!columnData || !supportsRawByteArrowVector(arrowType, parquetField)) {
|
|
668
921
|
return undefined;
|
|
669
922
|
}
|
|
923
|
+
if (columnData.byteArrayData) {
|
|
924
|
+
return createBufferedByteArrowVector(arrowType, parquetField, columnData, start, end);
|
|
925
|
+
}
|
|
670
926
|
|
|
671
927
|
const rowCount = end - start;
|
|
672
928
|
const valueOffsets = new Int32Array(rowCount + 1);
|
|
@@ -709,17 +965,38 @@ function createRawByteArrowVector(
|
|
|
709
965
|
}
|
|
710
966
|
}
|
|
711
967
|
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
968
|
+
const contiguousData = getContiguousFixedByteArrayData(
|
|
969
|
+
parquetField,
|
|
970
|
+
columnData,
|
|
971
|
+
byteValues,
|
|
972
|
+
firstValueIndex,
|
|
973
|
+
valueIndex,
|
|
974
|
+
dataByteLength
|
|
975
|
+
);
|
|
976
|
+
const data = contiguousData || new Uint8Array(dataByteLength);
|
|
977
|
+
if (!contiguousData) {
|
|
978
|
+
const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
979
|
+
let dataOffset = 0;
|
|
980
|
+
for (let index = firstValueIndex; index < valueIndex; index++) {
|
|
981
|
+
const bytes = byteValues[index];
|
|
982
|
+
if (bytes.byteLength >= 4 && bytes.byteLength <= MAXIMUM_INLINE_BYTE_COPY_LENGTH) {
|
|
983
|
+
dataView.setUint32(
|
|
984
|
+
dataOffset,
|
|
985
|
+
bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24),
|
|
986
|
+
true
|
|
987
|
+
);
|
|
988
|
+
dataOffset += 4;
|
|
989
|
+
for (let byteIndex = 4; byteIndex < bytes.byteLength; byteIndex++) {
|
|
990
|
+
data[dataOffset++] = bytes[byteIndex];
|
|
991
|
+
}
|
|
992
|
+
} else if (bytes.byteLength <= MAXIMUM_INLINE_BYTE_COPY_LENGTH) {
|
|
993
|
+
for (let byteIndex = 0; byteIndex < bytes.byteLength; byteIndex++) {
|
|
994
|
+
data[dataOffset++] = bytes[byteIndex];
|
|
995
|
+
}
|
|
996
|
+
} else {
|
|
997
|
+
data.set(bytes, dataOffset);
|
|
998
|
+
dataOffset += bytes.byteLength;
|
|
719
999
|
}
|
|
720
|
-
} else {
|
|
721
|
-
data.set(bytes, dataOffset);
|
|
722
|
-
dataOffset += bytes.byteLength;
|
|
723
1000
|
}
|
|
724
1001
|
}
|
|
725
1002
|
|
|
@@ -749,6 +1026,105 @@ function createRawByteArrowVector(
|
|
|
749
1026
|
return undefined;
|
|
750
1027
|
}
|
|
751
1028
|
|
|
1029
|
+
/** Creates a flat Arrow Utf8/Binary vector from the decoder's compact physical byte buffer. */
|
|
1030
|
+
function createBufferedByteArrowVector(
|
|
1031
|
+
arrowType: arrow.DataType,
|
|
1032
|
+
parquetField: ParquetField,
|
|
1033
|
+
columnData: ParquetColumnChunk,
|
|
1034
|
+
start: number,
|
|
1035
|
+
end: number
|
|
1036
|
+
): arrow.Vector {
|
|
1037
|
+
const byteArrayData = columnData.byteArrayData!;
|
|
1038
|
+
const rowCount = end - start;
|
|
1039
|
+
const nullBitmap = parquetField.dLevelMax ? new Uint8Array(Math.ceil(rowCount / 8)) : undefined;
|
|
1040
|
+
let sourceValueIndex = 0;
|
|
1041
|
+
let nullCount = 0;
|
|
1042
|
+
|
|
1043
|
+
if (!nullBitmap) {
|
|
1044
|
+
sourceValueIndex = start;
|
|
1045
|
+
} else {
|
|
1046
|
+
for (let rowIndex = 0; rowIndex < start; rowIndex++) {
|
|
1047
|
+
if (columnData.dlevels[rowIndex] === parquetField.dLevelMax) sourceValueIndex++;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
const firstValueIndex = sourceValueIndex;
|
|
1051
|
+
const canReuseOffsets = !nullBitmap && start === 0 && end === columnData.count;
|
|
1052
|
+
const valueOffsets = canReuseOffsets ? byteArrayData.valueOffsets : new Int32Array(rowCount + 1);
|
|
1053
|
+
let dataByteLength = 0;
|
|
1054
|
+
|
|
1055
|
+
if (!canReuseOffsets) {
|
|
1056
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
1057
|
+
const sourceRowIndex = start + rowIndex;
|
|
1058
|
+
if (!nullBitmap || columnData.dlevels[sourceRowIndex] === parquetField.dLevelMax) {
|
|
1059
|
+
dataByteLength +=
|
|
1060
|
+
byteArrayData.valueOffsets[sourceValueIndex + 1] -
|
|
1061
|
+
byteArrayData.valueOffsets[sourceValueIndex];
|
|
1062
|
+
sourceValueIndex++;
|
|
1063
|
+
if (nullBitmap) nullBitmap[rowIndex >> 3] |= 1 << (rowIndex & 7);
|
|
1064
|
+
} else {
|
|
1065
|
+
nullCount++;
|
|
1066
|
+
}
|
|
1067
|
+
valueOffsets[rowIndex + 1] = dataByteLength;
|
|
1068
|
+
}
|
|
1069
|
+
} else {
|
|
1070
|
+
sourceValueIndex = end;
|
|
1071
|
+
dataByteLength = byteArrayData.valueOffsets[sourceValueIndex];
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
const firstByteOffset = byteArrayData.valueOffsets[firstValueIndex];
|
|
1075
|
+
const lastByteOffset = byteArrayData.valueOffsets[sourceValueIndex];
|
|
1076
|
+
const data = byteArrayData.data.subarray(firstByteOffset, lastByteOffset);
|
|
1077
|
+
return new arrow.Vector([
|
|
1078
|
+
arrow.makeData({
|
|
1079
|
+
type: arrowType,
|
|
1080
|
+
valueOffsets,
|
|
1081
|
+
data,
|
|
1082
|
+
nullBitmap: nullCount ? nullBitmap : undefined,
|
|
1083
|
+
nullCount
|
|
1084
|
+
} as any)
|
|
1085
|
+
]);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Reuses one PLAIN page's contiguous fixed-width payload as Arrow Binary data.
|
|
1090
|
+
*
|
|
1091
|
+
* A single FIXED_LEN_BYTE_ARRAY page has no length prefixes between physical values. The decoder
|
|
1092
|
+
* retains each value as a view into that page, so Arrow can retain the complete span instead of
|
|
1093
|
+
* allocating and copying every value into another buffer.
|
|
1094
|
+
*/
|
|
1095
|
+
function getContiguousFixedByteArrayData(
|
|
1096
|
+
parquetField: ParquetField,
|
|
1097
|
+
columnData: ParquetColumnChunk,
|
|
1098
|
+
byteValues: Uint8Array[],
|
|
1099
|
+
firstValueIndex: number,
|
|
1100
|
+
valueEndIndex: number,
|
|
1101
|
+
dataByteLength: number
|
|
1102
|
+
): Uint8Array | undefined {
|
|
1103
|
+
const valueCount = valueEndIndex - firstValueIndex;
|
|
1104
|
+
const typeLength = parquetField.typeLength;
|
|
1105
|
+
if (
|
|
1106
|
+
parquetField.primitiveType !== 'FIXED_LEN_BYTE_ARRAY' ||
|
|
1107
|
+
!typeLength ||
|
|
1108
|
+
columnData.pageHeaders.length !== 1 ||
|
|
1109
|
+
valueCount === 0 ||
|
|
1110
|
+
dataByteLength !== valueCount * typeLength
|
|
1111
|
+
) {
|
|
1112
|
+
return undefined;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
const firstValue = byteValues[firstValueIndex];
|
|
1116
|
+
const lastValue = byteValues[valueEndIndex - 1];
|
|
1117
|
+
if (
|
|
1118
|
+
firstValue.byteLength !== typeLength ||
|
|
1119
|
+
lastValue.byteLength !== typeLength ||
|
|
1120
|
+
firstValue.buffer !== lastValue.buffer ||
|
|
1121
|
+
lastValue.byteOffset + typeLength !== firstValue.byteOffset + dataByteLength
|
|
1122
|
+
) {
|
|
1123
|
+
return undefined;
|
|
1124
|
+
}
|
|
1125
|
+
return new Uint8Array(firstValue.buffer, firstValue.byteOffset, dataByteLength);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
752
1128
|
/** Returns whether one flat Parquet byte column maps directly to Arrow Utf8 or Binary. */
|
|
753
1129
|
function supportsRawByteArrowVector(
|
|
754
1130
|
arrowType: arrow.DataType,
|
|
@@ -760,6 +1136,10 @@ function supportsRawByteArrowVector(
|
|
|
760
1136
|
if (arrowType instanceof arrow.Binary) {
|
|
761
1137
|
return (
|
|
762
1138
|
(!parquetField.originalType ||
|
|
1139
|
+
parquetField.originalType === 'JSON' ||
|
|
1140
|
+
parquetField.originalType === 'BSON' ||
|
|
1141
|
+
parquetField.originalType === 'INTERVAL' ||
|
|
1142
|
+
parquetField.originalType === 'VARIANT' ||
|
|
763
1143
|
parquetField.originalType === 'GEOMETRY' ||
|
|
764
1144
|
parquetField.originalType === 'GEOGRAPHY') &&
|
|
765
1145
|
(parquetField.primitiveType === 'BYTE_ARRAY' ||
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
// eslint-disable
|
|
6
|
+
import {makeTableScanBatch} from '@loaders.gl/loader-utils';
|
|
6
7
|
import type {ReadableFile} from '@loaders.gl/loader-utils';
|
|
7
8
|
import type {ArrowTable, ArrowTableBatch, Schema} from '@loaders.gl/schema';
|
|
8
9
|
|
|
@@ -68,13 +69,11 @@ export async function* parseParquetFileToArrowInBatches(
|
|
|
68
69
|
schemaMetadata
|
|
69
70
|
);
|
|
70
71
|
schema ||= normalizedArrowTable.schema;
|
|
71
|
-
yield {
|
|
72
|
-
batchType: 'data',
|
|
72
|
+
yield makeTableScanBatch({
|
|
73
73
|
shape: 'arrow-table',
|
|
74
74
|
schema,
|
|
75
|
-
data: normalizedArrowTable.data
|
|
76
|
-
|
|
77
|
-
};
|
|
75
|
+
data: normalizedArrowTable.data
|
|
76
|
+
});
|
|
78
77
|
}
|
|
79
78
|
} finally {
|
|
80
79
|
parquetFile.free();
|
|
@@ -40,7 +40,9 @@ export async function* parseParquetFileInColumnarBatches(
|
|
|
40
40
|
): AsyncIterable<ColumnarTableBatch> {
|
|
41
41
|
await preloadCompressions(options);
|
|
42
42
|
|
|
43
|
-
const reader = new ParquetReader(file
|
|
43
|
+
const reader = new ParquetReader(file, {
|
|
44
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp
|
|
45
|
+
});
|
|
44
46
|
|
|
45
47
|
// Extract schema and geo metadata
|
|
46
48
|
const schema = await getSchemaFromParquetReader(reader);
|
|
@@ -25,7 +25,15 @@ export async function parseParquetFile(
|
|
|
25
25
|
await preloadCompressions(options);
|
|
26
26
|
|
|
27
27
|
const reader = new ParquetReader(file, {
|
|
28
|
-
preserveBinary: options?.parquet?.preserveBinary
|
|
28
|
+
preserveBinary: options?.parquet?.preserveBinary,
|
|
29
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp,
|
|
30
|
+
retainByteArrayViews: true,
|
|
31
|
+
useTypedValueBuffers: true,
|
|
32
|
+
useTypedLevelBuffers: true,
|
|
33
|
+
useArrowByteArrayBuffers: true,
|
|
34
|
+
verifyFooterSignature: options?.parquet?.verifyFooterSignature,
|
|
35
|
+
keyRetriever: options?.parquet?.keyRetriever,
|
|
36
|
+
aadPrefix: options?.parquet?.aadPrefix
|
|
29
37
|
});
|
|
30
38
|
|
|
31
39
|
const schema = await getSchemaFromParquetReader(reader);
|
|
@@ -78,7 +86,15 @@ export async function* parseParquetFileInBatches(
|
|
|
78
86
|
await preloadCompressions(options);
|
|
79
87
|
|
|
80
88
|
const reader = new ParquetReader(file, {
|
|
81
|
-
preserveBinary: options?.parquet?.preserveBinary
|
|
89
|
+
preserveBinary: options?.parquet?.preserveBinary,
|
|
90
|
+
int96AsTimestamp: options?.parquet?.int96AsTimestamp,
|
|
91
|
+
retainByteArrayViews: true,
|
|
92
|
+
useTypedValueBuffers: true,
|
|
93
|
+
useTypedLevelBuffers: true,
|
|
94
|
+
useArrowByteArrayBuffers: true,
|
|
95
|
+
verifyFooterSignature: options?.parquet?.verifyFooterSignature,
|
|
96
|
+
keyRetriever: options?.parquet?.keyRetriever,
|
|
97
|
+
aadPrefix: options?.parquet?.aadPrefix
|
|
82
98
|
});
|
|
83
99
|
|
|
84
100
|
const schema = await getSchemaFromParquetReader(reader);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {ParquetBatch} from '../parquet-source-types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Retains the leading rows of a Parquet batch while keeping source-position provenance aligned.
|
|
9
|
+
*
|
|
10
|
+
* This is used by physical readers, dataset orchestration, and table-format delete handling to
|
|
11
|
+
* implement one global post-filter limit without materializing row objects.
|
|
12
|
+
*/
|
|
13
|
+
export function sliceParquetBatch<BatchT extends ParquetBatch>(
|
|
14
|
+
batch: BatchT,
|
|
15
|
+
rowCount: number
|
|
16
|
+
): BatchT {
|
|
17
|
+
if (!Number.isSafeInteger(rowCount) || rowCount < 0 || rowCount > batch.length) {
|
|
18
|
+
throw new Error(`Parquet batch row count must be between zero and ${batch.length}`);
|
|
19
|
+
}
|
|
20
|
+
if (rowCount === batch.length) return batch;
|
|
21
|
+
const rowGroupRowIndices = batch.rowGroupRowIndices?.slice(0, rowCount);
|
|
22
|
+
const rowIndices = batch.rowIndices?.slice(0, rowCount);
|
|
23
|
+
return {
|
|
24
|
+
...batch,
|
|
25
|
+
data: batch.data.slice(0, rowCount),
|
|
26
|
+
length: rowCount,
|
|
27
|
+
rowCount,
|
|
28
|
+
rowGroupRowIndices,
|
|
29
|
+
rowIndices,
|
|
30
|
+
metadata: batch.metadata ? {...batch.metadata, rowCount} : batch.metadata
|
|
31
|
+
} as BatchT;
|
|
32
|
+
}
|