herringbone 0.7.0 → 0.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/MANUAL.md +36 -6
- data/README.md +7 -5
- data/lib/herringbone/active_record.rb +1 -1
- data/lib/herringbone/codecs/zstd.rb +774 -0
- data/lib/herringbone/compression.rb +35 -6
- data/lib/herringbone/inferring_writer.rb +1 -1
- data/lib/herringbone/reader/column_chunk_reader.rb +2 -0
- data/lib/herringbone/schema/merge.rb +1 -1
- data/lib/herringbone/schema.rb +95 -12
- data/lib/herringbone/types.rb +20 -12
- data/lib/herringbone/version.rb +1 -1
- data/lib/herringbone.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c59941b3e4ed776a03d3596bf8b9288dd852b89f49934dfb1110f6b29d527ab8
|
|
4
|
+
data.tar.gz: 13ef32e91a12a11d249be06834f0c33dfb70c9ebb7746d29d28844f9af180fa5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '083624f293ce5d1825c9f6998e46b6e58767e9bbec15d6adbbd1cb556ef3771d2a0426a41ba8f097a43b2b937bef55ce018a01925a7df2d9f9d8d36a1b4f8da9'
|
|
7
|
+
data.tar.gz: 38b917be5c728a3837d3eafae3e9f060708574f5c6249792219d17a410a4fe14683df46dfd4b922d3bf4503a327a2384105c950e06ca1523a7482c042629f367
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.9.0
|
|
6
|
+
|
|
7
|
+
- ZSTD files are read without the `zstd-ruby` gem, by a pure-Ruby decompressor; `zstd-ruby` is
|
|
8
|
+
still used when loaded, and still needed to write ZSTD.
|
|
9
|
+
|
|
10
|
+
## 0.8.0
|
|
11
|
+
|
|
12
|
+
- `Herringbone::MissingCodecError` explains over several lines which gem to install and that it has
|
|
13
|
+
to be required before the read or write, and names the column it could not decompress up front.
|
|
14
|
+
- `Herringbone::Schema#only(:id, :name)` and `#except(:ssn)` make a schema with some of the
|
|
15
|
+
top-level fields.
|
|
16
|
+
- `time` columns convert a `Time` to UTC when writing, as `timestamp` columns already did, instead
|
|
17
|
+
of storing its time of day in its own zone.
|
|
18
|
+
- **Breaking:** `local_timestamp` and `local_time` (`s.local_timestamp :opens_at`) write the wall
|
|
19
|
+
clock time without converting it to UTC, replacing the `utc: false` option, which now raises.
|
|
20
|
+
|
|
5
21
|
## 0.7.0
|
|
6
22
|
|
|
7
23
|
- `Herringbone.redact` and `Herringbone::Redaction#apply` take a `Herringbone::Reader` as well as an
|
data/MANUAL.md
CHANGED
|
@@ -19,6 +19,7 @@ The full reference for Herringbone. For a quick start, see the [README](README.m
|
|
|
19
19
|
- [SimpleWriter: coming from CSV](#simplewriter-coming-from-csv)
|
|
20
20
|
- [Statistics, page indexes and bloom filters](#statistics-page-indexes-and-bloom-filters)
|
|
21
21
|
- [Writing to S3](#writing-to-s3)
|
|
22
|
+
- [Writing to Google Cloud Storage](#writing-to-google-cloud-storage)
|
|
22
23
|
- [Encryption](#encryption)
|
|
23
24
|
- [Writing encrypted files](#writing-encrypted-files)
|
|
24
25
|
- [Which settings other tools read](#which-settings-other-tools-read)
|
|
@@ -54,7 +55,7 @@ Add these libraries to speed up and enable certain functionality:
|
|
|
54
55
|
|
|
55
56
|
```ruby
|
|
56
57
|
gem "snappy" # native Snappy, 2-3x faster reads and writes of typical files
|
|
57
|
-
gem "zstd-ruby" # ZSTD
|
|
58
|
+
gem "zstd-ruby" # writing ZSTD; reading falls back to pure Ruby, 30-100x slower
|
|
58
59
|
gem "brotli" # Brotli
|
|
59
60
|
gem "xxhash" # faster bloom filters
|
|
60
61
|
gem "numo-narray-alt" # read(as: :numo)
|
|
@@ -212,6 +213,17 @@ The block receives the schema builder, and the blocks of `struct`, `list` and `m
|
|
|
212
213
|
builder of their own, so the block can still call your methods and read your instance variables.
|
|
213
214
|
A block that takes no parameter raises `ArgumentError`.
|
|
214
215
|
|
|
216
|
+
`only` and `except` make a schema with some of the top-level fields, keeping their order, for
|
|
217
|
+
instance to write part of a file you are reading:
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
schema.only(:id, :name) # id and name
|
|
221
|
+
schema.except(:ssn) # every field but ssn
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
A name the schema has no top-level field for raises `ArgumentError`, and so does leaving out
|
|
225
|
+
every field.
|
|
226
|
+
|
|
215
227
|
### Writing with an inferred schema
|
|
216
228
|
|
|
217
229
|
`Herringbone.write(io, rows)` writes an Enumerable of rows in one go, inferring the schema from the
|
|
@@ -232,11 +244,17 @@ file and rename it.
|
|
|
232
244
|
### Column types
|
|
233
245
|
|
|
234
246
|
`boolean int8 int16 int32 int64 uint8 uint16 uint32 uint64 float double float16 string binary
|
|
235
|
-
json bson enum uuid date int96 time timestamp decimal fixed`, plus
|
|
247
|
+
json bson enum uuid date int96 time local_time timestamp local_timestamp decimal fixed`, plus
|
|
248
|
+
`struct`, `list` and `map`;
|
|
236
249
|
`s.column :name, :int32` declares one by name. Fields are nullable unless `null: false` is given;
|
|
237
250
|
list elements unless `element_null: false`, map values unless `value_null: false`. Nested lists:
|
|
238
|
-
`s.list :matrix do |matrix| matrix.list :element, :double end`.
|
|
239
|
-
(`:millis`, `:micros`, `:nanos`)
|
|
251
|
+
`s.list :matrix do |matrix| matrix.list :element, :double end`. The time and timestamp types take `unit:`
|
|
252
|
+
(`:millis`, `:micros`, `:nanos`).
|
|
253
|
+
|
|
254
|
+
`timestamp` stores instants: a `Time` in any zone is converted to UTC, so the file means the same
|
|
255
|
+
thing wherever it was written. `local_timestamp` stores the wall clock date and time as given, with
|
|
256
|
+
no zone, for values like "the shop opens at 09:00" that are not instants. `time` and `local_time`
|
|
257
|
+
do the same for a time of day.
|
|
240
258
|
|
|
241
259
|
`enum` is a string column. `values:` restricts what may be written, and also takes a Rails-style
|
|
242
260
|
Hash (`values: Order.statuses`), in which case both labels and stored integers are accepted and
|
|
@@ -250,8 +268,8 @@ Columns accept the values Ruby and Rails code usually has at hand:
|
|
|
250
268
|
| column | accepts |
|
|
251
269
|
|---|---|
|
|
252
270
|
| `date` | `Date`, `Time`/`DateTime` (their date), `"2024-05-01"` |
|
|
253
|
-
| `timestamp` | `Time`, `DateTime`, `ActiveSupport::TimeWithZone`, `Date` (midnight UTC), ISO-8601 strings, Integers in the column's unit |
|
|
254
|
-
| `time` | `Time` (its time of day, as Rails returns for `time` columns), `"13:45:30.25"`, Integers |
|
|
271
|
+
| `timestamp`, `local_timestamp` | `Time`, `DateTime`, `ActiveSupport::TimeWithZone`, `Date` (midnight UTC), ISO-8601 strings, Integers in the column's unit |
|
|
272
|
+
| `time`, `local_time` | `Time` (its time of day, in UTC for `time`, as Rails returns for `time` columns), `"13:45:30.25"`, Integers |
|
|
255
273
|
| `json` | Strings as-is, anything else through `JSON.generate` |
|
|
256
274
|
| `string`, `enum` | Strings, Symbols, anything with `to_s` |
|
|
257
275
|
| `boolean` | `true`/`false`, `1`/`0`, `"t"`/`"f"`, `"true"`/`"false"`, `"yes"`/`"no"` |
|
|
@@ -342,6 +360,18 @@ If the block raises, the SDK aborts the multipart upload and raises `Aws::S3::Mu
|
|
|
342
360
|
so no partial object is left. S3 allows at most 10,000 parts, which with the default 5MB parts caps
|
|
343
361
|
the file at about 48GB; raise `part_size:` for bigger files.
|
|
344
362
|
|
|
363
|
+
### Writing to Google Cloud Storage
|
|
364
|
+
|
|
365
|
+
`google-cloud-storage` needs the size of an upload up front, so it can't take a stream. Use
|
|
366
|
+
[gcs_put](https://github.com/julik/gcs_put), which streams into a resumable upload of unknown size:
|
|
367
|
+
|
|
368
|
+
```ruby
|
|
369
|
+
gcs_file = Google::Cloud::Storage.new.bucket("exports").file("orders.parquet", skip_lookup: true)
|
|
370
|
+
GCSPut.open_gcs_file(gcs_file) { |io| Herringbone.write(io, Order.all) }
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
If the block raises, the upload is never finalized and no object appears.
|
|
374
|
+
|
|
345
375
|
## Encryption
|
|
346
376
|
|
|
347
377
|
Herringbone reads and writes files encrypted with
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A pure-Ruby reader and writer for [Apache Parquet](https://parquet.apache.org/)
|
|
|
4
4
|
|
|
5
5
|
- No Thrift gem and no native extensions of its own: the Thrift compact protocol, all encodings
|
|
6
6
|
and the Snappy and LZ4 codecs are implemented in Ruby (ZSTD and Brotli use optional gems).
|
|
7
|
-
LZO
|
|
7
|
+
ZSTD and LZO (from Hadoop-era files) are also read in pure Ruby; writing ZSTD needs `zstd-ruby`
|
|
8
8
|
- Full nesting support (structs, lists, maps, any depth) via Dremel record shredding/assembly
|
|
9
9
|
- Reads files from parquet-mr, Arrow, Spark, Impala, DuckDB, Rust writers etc.
|
|
10
10
|
- Optimized reads with batches and pages
|
|
@@ -21,9 +21,9 @@ rules, combining files, type mapping and the inspector.
|
|
|
21
21
|
gem "herringbone"
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Optionally add `snappy` (faster), `zstd-ruby`
|
|
25
|
-
filters) or `numo-narray-alt` (`read(as: :numo)`). Herringbone uses
|
|
26
|
-
see [Optional gems](MANUAL.md#optional-gems).
|
|
24
|
+
Optionally add `snappy` (faster), `zstd-ruby` (writing ZSTD, much faster reading of it), `brotli`,
|
|
25
|
+
`xxhash` (faster bloom filters) or `numo-narray-alt` (`read(as: :numo)`). Herringbone uses
|
|
26
|
+
whichever of them are loaded, see [Optional gems](MANUAL.md#optional-gems).
|
|
27
27
|
|
|
28
28
|
## Exporting from Rails
|
|
29
29
|
|
|
@@ -46,7 +46,9 @@ end
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Any Enumerable of Hashes, Structs or Arrays works too; the schema is inferred from the first 1000
|
|
49
|
-
rows. See [ActiveRecord](MANUAL.md#activerecord) and [Writing to S3](MANUAL.md#writing-to-s3).
|
|
49
|
+
rows. See [ActiveRecord](MANUAL.md#activerecord) and [Writing to S3](MANUAL.md#writing-to-s3). For
|
|
50
|
+
Google Cloud Storage, use [gcs_put](https://github.com/julik/gcs_put), see
|
|
51
|
+
[Writing to Google Cloud Storage](MANUAL.md#writing-to-google-cloud-storage).
|
|
50
52
|
|
|
51
53
|
## Reading
|
|
52
54
|
|
|
@@ -128,7 +128,7 @@ module Herringbone
|
|
|
128
128
|
when :boolean then [:boolean, {}]
|
|
129
129
|
when :binary then [:binary, {}]
|
|
130
130
|
when :date then [:date, {}]
|
|
131
|
-
when :datetime, :timestamp, :timestamptz then [:timestamp, {unit: :micros
|
|
131
|
+
when :datetime, :timestamp, :timestamptz then [:timestamp, {unit: :micros}]
|
|
132
132
|
when :time then [:time, {unit: :micros}]
|
|
133
133
|
when :json, :jsonb then [:json, {}]
|
|
134
134
|
when :uuid then [:uuid, {}]
|