Skip to main content

compact_thrift_parquet/
format.rs

1#![allow(non_snake_case)]
2use compact_thrift_runtime::thrift;
3use crate::encodings::EncodingSet;
4use crate::path_in_schema::PathInSchema;
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements.  See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership.  The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License.  You may obtain a copy of the License at
13 *
14 *     http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied.  See the License for the
20 * specific language governing permissions and limitations
21 * under the License.
22 */
23
24thrift! {
25/**
26 * Types supported by Parquet.  These types are intended to be used in combination
27 * with the encodings to control the on disk storage format.
28 * For example INT16 is not included as a type since a good encoding of INT32
29 * would handle this.
30 */
31enum Type {
32  BOOLEAN = 0;
33  INT32 = 1;
34  INT64 = 2;
35  INT96 = 3;  // deprecated, only used by legacy implementations.
36  FLOAT = 4;
37  DOUBLE = 5;
38  BYTE_ARRAY = 6;
39  FIXED_LEN_BYTE_ARRAY = 7;
40}
41
42/**
43 * DEPRECATED: Common types used by frameworks(e.g. hive, pig) using parquet.
44 * ConvertedType is superseded by LogicalType.  This enum should not be extended.
45 *
46 * See LogicalTypes.md for conversion between ConvertedType and LogicalType.
47 */
48enum ConvertedType {
49  /** a BYTE_ARRAY actually contains UTF8 encoded chars */
50  UTF8 = 0;
51
52  /** a map is converted as an optional field containing a repeated key/value pair */
53  MAP = 1;
54
55  /** a key/value pair is converted into a group of two fields */
56  MAP_KEY_VALUE = 2;
57
58  /** a list is converted into an optional field containing a repeated field for its
59    * values */
60  LIST = 3;
61
62  /** an enum is converted into a BYTE_ARRAY field */
63  ENUM = 4;
64
65  /**
66   * A decimal value.
67   *
68   * This may be used to annotate BYTE_ARRAY or FIXED_LEN_BYTE_ARRAY primitive
69   * types. The underlying byte array stores the unscaled value encoded as two's
70   * complement using big-endian byte order (the most significant byte is the
71   * zeroth element). The value of the decimal is the value * 10^{-scale}.
72   *
73   * This must be accompanied by a (maximum) precision and a scale in the
74   * SchemaElement. The precision specifies the number of digits in the decimal
75   * and the scale stores the location of the decimal point. For example 1.23
76   * would have precision 3 (3 total digits) and scale 2 (the decimal point is
77   * 2 digits over).
78   */
79  DECIMAL = 5;
80
81  /**
82   * A Date
83   *
84   * Stored as days since Unix epoch, encoded as the INT32 physical type.
85   *
86   */
87  DATE = 6;
88
89  /**
90   * A time
91   *
92   * The total number of milliseconds since midnight.  The value is stored
93   * as an INT32 physical type.
94   */
95  TIME_MILLIS = 7;
96
97  /**
98   * A time.
99   *
100   * The total number of microseconds since midnight.  The value is stored as
101   * an INT64 physical type.
102   */
103  TIME_MICROS = 8;
104
105  /**
106   * A date/time combination
107   *
108   * Date and time recorded as milliseconds since the Unix epoch.  Recorded as
109   * a physical type of INT64.
110   */
111  TIMESTAMP_MILLIS = 9;
112
113  /**
114   * A date/time combination
115   *
116   * Date and time recorded as microseconds since the Unix epoch.  The value is
117   * stored as an INT64 physical type.
118   */
119  TIMESTAMP_MICROS = 10;
120
121
122  /**
123   * An unsigned integer value.
124   *
125   * The number describes the maximum number of meaningful data bits in
126   * the stored value. 8, 16 and 32 bit values are stored using the
127   * INT32 physical type.  64 bit values are stored using the INT64
128   * physical type.
129   *
130   */
131  UINT_8 = 11;
132  UINT_16 = 12;
133  UINT_32 = 13;
134  UINT_64 = 14;
135
136  /**
137   * A signed integer value.
138   *
139   * The number describes the maximum number of meaningful data bits in
140   * the stored value. 8, 16 and 32 bit values are stored using the
141   * INT32 physical type.  64 bit values are stored using the INT64
142   * physical type.
143   *
144   */
145  INT_8 = 15;
146  INT_16 = 16;
147  INT_32 = 17;
148  INT_64 = 18;
149
150  /**
151   * An embedded JSON document
152   *
153   * A JSON document embedded within a single UTF8 column.
154   */
155  JSON = 19;
156
157  /**
158   * An embedded BSON document
159   *
160   * A BSON document embedded within a single BYTE_ARRAY column.
161   */
162  BSON = 20;
163
164  /**
165   * An interval of time
166   *
167   * This type annotates data stored as a FIXED_LEN_BYTE_ARRAY of length 12
168   * This data is composed of three separate little endian unsigned
169   * integers.  Each stores a component of a duration of time.  The first
170   * integer identifies the number of months associated with the duration,
171   * the second identifies the number of days associated with the duration
172   * and the third identifies the number of milliseconds associated with
173   * the provided duration.  This duration of time is independent of any
174   * particular timezone or date.
175   */
176  INTERVAL = 21;
177}
178
179/**
180 * Representation of Schemas
181 */
182enum FieldRepetitionType {
183  /** This field is required (can not be null) and each row has exactly 1 value. */
184  REQUIRED = 0;
185
186  /** The field is optional (can be null) and each row has 0 or 1 values. */
187  OPTIONAL = 1;
188
189  /** The field is repeated and can contain 0 or more values */
190  REPEATED = 2;
191}
192
193/**
194 * A structure for capturing metadata for estimating the unencoded,
195 * uncompressed size of data written. This is useful for readers to estimate
196 * how much memory is needed to reconstruct data in their memory model and for
197 * fine grained filter pushdown on nested structures (the histograms contained
198 * in this structure can help determine the number of nulls at a particular
199 * nesting level and maximum length of lists).
200 */
201struct SizeStatistics {
202   /**
203    * The number of physical bytes stored for BYTE_ARRAY data values assuming
204    * no encoding. This is exclusive of the bytes needed to store the length of
205    * each byte array. In other words, this field is equivalent to the `(size
206    * of PLAIN-ENCODING the byte array values) - (4 bytes * number of values
207    * written)`. To determine unencoded sizes of other types readers can use
208    * schema information multiplied by the number of non-null and null values.
209    * The number of null/non-null values can be inferred from the histograms
210    * below.
211    *
212    * For example, if a column chunk is dictionary-encoded with dictionary
213    * ["a", "bc", "cde"], and a data page contains the indices [0, 0, 1, 2],
214    * then this value for that data page should be 7 (1 + 1 + 2 + 3).
215    *
216    * This field should only be set for types that use BYTE_ARRAY as their
217    * physical type.
218    */
219   1: optional i64 unencoded_byte_array_data_bytes;
220   /**
221    * When present, there is expected to be one element corresponding to each
222    * repetition (i.e. size=max repetition_level+1) where each element
223    * represents the number of times the repetition level was observed in the
224    * data.
225    *
226    * This field may be omitted if max_repetition_level is 0 without loss
227    * of information.
228    **/
229   2: optional list<i64> repetition_level_histogram;
230   /**
231    * Same as repetition_level_histogram except for definition levels.
232    *
233    * This field may be omitted if max_definition_level is 0 or 1 without
234    * loss of information.
235    **/
236   3: optional list<i64> definition_level_histogram;
237}
238
239/**
240 * Bounding box for GEOMETRY or GEOGRAPHY type in the representation of min/max
241 * value pair of coordinates from each axis.
242 */
243struct BoundingBox {
244  1: required double xmin;
245  2: required double xmax;
246  3: required double ymin;
247  4: required double ymax;
248  5: optional double zmin;
249  6: optional double zmax;
250  7: optional double mmin;
251  8: optional double mmax;
252}
253
254/** Statistics specific to Geometry and Geography logical types */
255struct GeospatialStatistics {
256  /** A bounding box of geospatial instances */
257  1: optional BoundingBox bbox;
258  /** Geospatial type codes of all instances, or an empty list if not known */
259  2: optional list<i32> geospatial_types;
260}
261
262/**
263 * Statistics per row group and per page
264 * All fields are optional.
265 */
266struct Statistics {
267   /**
268    * DEPRECATED: min and max value of the column. Use min_value and max_value.
269    *
270    * Values are encoded using PLAIN encoding, except that variable-length byte
271    * arrays do not include a length prefix.
272    *
273    * These fields encode min and max values determined by signed comparison
274    * only. New files should use the correct order for a column's logical type
275    * and store the values in the min_value and max_value fields.
276    *
277    * To support older readers, these may be set when the column order is
278    * signed.
279    */
280   1: optional binary max;
281   2: optional binary min;
282   /**
283    * Count of null values in the column.
284    *
285    * Writers SHOULD always write this field even if it is zero (i.e. no null value)
286    * or the column is not nullable.
287    * Readers MUST distinguish between null_count not being present and null_count == 0.
288    * If null_count is not present, readers MUST NOT assume null_count == 0.
289    */
290   3: optional i64 null_count;
291   /** count of distinct values occurring */
292   4: optional i64 distinct_count;
293   /**
294    * Lower and upper bound values for the column, determined by its ColumnOrder.
295    *
296    * These may be the actual minimum and maximum values found on a page or column
297    * chunk, but can also be (more compact) values that do not exist on a page or
298    * column chunk. For example, instead of storing "Blart Versenwald III", a writer
299    * may set min_value="B", max_value="C". Such more compact values must still be
300    * valid values within the column's logical type.
301    *
302    * Values are encoded using PLAIN encoding, except that variable-length byte
303    * arrays do not include a length prefix.
304    */
305   5: optional binary max_value;
306   6: optional binary min_value;
307   /** If true, max_value is the actual maximum value for a column */
308   7: optional bool is_max_value_exact;
309   /** If true, min_value is the actual minimum value for a column */
310   8: optional bool is_min_value_exact;
311}
312
313/** Empty structs to use as logical type annotations */
314struct StringType {}  // allowed for BYTE_ARRAY, must be encoded with UTF-8
315struct UUIDType {}    // allowed for FIXED[16], must be encoded as raw UUID bytes
316struct MapType {}     // see LogicalTypes.md
317struct ListType {}    // see LogicalTypes.md
318struct EnumType {}    // allowed for BYTE_ARRAY, must be encoded with UTF-8
319struct DateType {}    // allowed for INT32
320struct Float16Type {} // allowed for FIXED[2], must be encoded as raw FLOAT16 bytes (see LogicalTypes.md)
321
322/**
323 * Logical type to annotate a column that is always null.
324 *
325 * Sometimes when discovering the schema of existing data, values are always
326 * null and the physical type can't be determined. This annotation signals
327 * the case where the physical type was guessed from all null values.
328 */
329struct NullType {}    // allowed for any physical type, only null values stored
330
331/**
332 * Decimal logical type annotation
333 *
334 * Scale must be zero or a positive integer less than or equal to the precision.
335 * Precision must be a non-zero positive integer.
336 *
337 * To maintain forward-compatibility in v1, implementations using this logical
338 * type must also set scale and precision on the annotated SchemaElement.
339 *
340 * Allowed for physical types: INT32, INT64, FIXED_LEN_BYTE_ARRAY, and BYTE_ARRAY.
341 */
342struct DecimalType {
343  1: required i32 scale
344  2: required i32 precision
345}
346
347/** Time units for logical types */
348struct MilliSeconds {}
349struct MicroSeconds {}
350struct NanoSeconds {}
351union TimeUnit {
352  1: MilliSeconds MILLIS
353  2: MicroSeconds MICROS
354  3: NanoSeconds NANOS
355}
356
357/**
358 * Timestamp logical type annotation
359 *
360 * Allowed for physical types: INT64
361 */
362struct TimestampType {
363  1: required bool isAdjustedToUTC
364  2: required TimeUnit unit
365}
366
367/**
368 * Time logical type annotation
369 *
370 * Allowed for physical types: INT32 (millis), INT64 (micros, nanos)
371 */
372struct TimeType {
373  1: required bool isAdjustedToUTC
374  2: required TimeUnit unit
375}
376
377/**
378 * Integer logical type annotation
379 *
380 * bitWidth must be 8, 16, 32, or 64.
381 *
382 * Allowed for physical types: INT32, INT64
383 */
384struct IntType {
385  1: required i8 bitWidth
386  2: required bool isSigned
387}
388
389/**
390 * Embedded JSON logical type annotation
391 *
392 * Allowed for physical types: BYTE_ARRAY
393 */
394struct JsonType {
395}
396
397/**
398 * Embedded BSON logical type annotation
399 *
400 * Allowed for physical types: BYTE_ARRAY
401 */
402struct BsonType {
403}
404
405/**
406 * Embedded Variant logical type annotation
407 */
408struct VariantType {
409  // The version of the variant specification that the variant was
410  // written with.
411  1: optional i8 specification_version
412}
413
414/** Edge interpolation algorithm for Geography logical type */
415enum EdgeInterpolationAlgorithm {
416  SPHERICAL = 0;
417  VINCENTY = 1;
418  THOMAS = 2;
419  ANDOYER = 3;
420  KARNEY = 4;
421}
422
423/**
424 * Embedded Geometry logical type annotation
425 *
426 * Geospatial features in the Well-Known Binary (WKB) format and edges interpolation
427 * is always linear/planar.
428 *
429 * A custom CRS can be set by the crs field. If unset, it defaults to "OGC:CRS84",
430 * which means that the geometries must be stored in longitude, latitude based on
431 * the WGS84 datum.
432 *
433 * Allowed for physical type: BYTE_ARRAY.
434 *
435 * See Geospatial.md for details.
436 */
437struct GeometryType {
438  1: optional string crs;
439}
440
441/**
442 * Embedded Geography logical type annotation
443 *
444 * Geospatial features in the WKB format with an explicit (non-linear/non-planar)
445 * edges interpolation algorithm.
446 *
447 * A custom geographic CRS can be set by the crs field, where longitudes are
448 * bound by [-180, 180] and latitudes are bound by [-90, 90]. If unset, the CRS
449 * defaults to "OGC:CRS84".
450 *
451 * An optional algorithm can be set to correctly interpret edges interpolation
452 * of the geometries. If unset, the algorithm defaults to SPHERICAL.
453 *
454 * Allowed for physical type: BYTE_ARRAY.
455 *
456 * See Geospatial.md for details.
457 */
458struct GeographyType {
459  1: optional string crs;
460  2: optional EdgeInterpolationAlgorithm algorithm;
461}
462
463/**
464 * LogicalType annotations to replace ConvertedType.
465 *
466 * To maintain compatibility, implementations using LogicalType for a
467 * SchemaElement must also set the corresponding ConvertedType (if any)
468 * from the following table.
469 */
470union LogicalType {
471  1:  StringType STRING       // use ConvertedType UTF8
472  2:  MapType MAP             // use ConvertedType MAP
473  3:  ListType LIST           // use ConvertedType LIST
474  4:  EnumType ENUM           // use ConvertedType ENUM
475  5:  DecimalType DECIMAL     // use ConvertedType DECIMAL + SchemaElement.{scale, precision}
476  6:  DateType DATE           // use ConvertedType DATE
477
478  // use ConvertedType TIME_MICROS for TIME(isAdjustedToUTC = *, unit = MICROS)
479  // use ConvertedType TIME_MILLIS for TIME(isAdjustedToUTC = *, unit = MILLIS)
480  7:  TimeType TIME
481
482  // use ConvertedType TIMESTAMP_MICROS for TIMESTAMP(isAdjustedToUTC = *, unit = MICROS)
483  // use ConvertedType TIMESTAMP_MILLIS for TIMESTAMP(isAdjustedToUTC = *, unit = MILLIS)
484  8:  TimestampType TIMESTAMP
485
486  // 9: reserved for INTERVAL
487  10: IntType INTEGER         // use ConvertedType INT_* or UINT_*
488  11: NullType UNKNOWN        // no compatible ConvertedType
489  12: JsonType JSON           // use ConvertedType JSON
490  13: BsonType BSON           // use ConvertedType BSON
491  14: UUIDType UUID           // no compatible ConvertedType
492  15: Float16Type FLOAT16     // no compatible ConvertedType
493  16: VariantType VARIANT     // no compatible ConvertedType
494  17: GeometryType GEOMETRY   // no compatible ConvertedType
495  18: GeographyType GEOGRAPHY // no compatible ConvertedType
496}
497
498/**
499 * Represents a element inside a schema definition.
500 *  - if it is a group (inner node) then type is undefined and num_children is defined
501 *  - if it is a primitive type (leaf) then type is defined and num_children is undefined
502 * the nodes are listed in depth first traversal order.
503 */
504struct SchemaElement {
505  /** Data type for this field. Not set if the current element is a non-leaf node */
506  1: optional Type type_;
507
508  /** If type is FIXED_LEN_BYTE_ARRAY, this is the byte length of the values.
509    * Otherwise, if specified, this is the maximum bit length to store any of the values.
510    * (e.g. a low cardinality INT col could have this set to 3).  Note that this is
511    * in the schema, and therefore fixed for the entire file.
512   */
513  2: optional i32 type_length;
514
515  /** repetition of the field. The root of the schema does not have a repetition_type.
516    * All other nodes must have one */
517  3: optional FieldRepetitionType repetition_type;
518
519  /** Name of the field in the schema */
520  4: required string name;
521
522  /** Nested fields.  Since thrift does not support nested fields,
523    * the nesting is flattened to a single list by a depth-first traversal.
524    * The children count is used to construct the nested relationship.
525    * This field is not set when the element is a primitive type
526   */
527  5: optional i32 num_children;
528
529  /**
530   * DEPRECATED: When the schema is the result of a conversion from another model.
531   * Used to record the original type to help with cross conversion.
532   *
533   * This is superseded by logicalType.
534   */
535  6: optional ConvertedType converted_type;
536
537  /**
538   * DEPRECATED: Used when this column contains decimal data.
539   * See the DECIMAL converted type for more details.
540   *
541   * This is superseded by using the DecimalType annotation in logicalType.
542   */
543  7: optional i32 scale
544  8: optional i32 precision
545
546  /** When the original schema supports field ids, this will save the
547    * original field id in the parquet schema
548   */
549  9: optional i32 field_id;
550
551  /**
552   * The logical type of this SchemaElement
553   *
554   * LogicalType replaces ConvertedType, but ConvertedType is still required
555   * for some logical types to ensure forward-compatibility in format v1.
556   */
557  10: optional LogicalType logicalType
558}
559
560/**
561 * Encodings supported by Parquet.  Not all encodings are valid for all types.  These
562 * enums are also used to specify the encoding of definition and repetition levels.
563 * See the accompanying doc for the details of the more complicated encodings.
564 */
565enum Encoding {
566  /** Default encoding.
567    * BOOLEAN - 1 bit per value. 0 is false; 1 is true.
568    * INT32 - 4 bytes per value.  Stored as little-endian.
569    * INT64 - 8 bytes per value.  Stored as little-endian.
570    * FLOAT - 4 bytes per value.  IEEE. Stored as little-endian.
571    * DOUBLE - 8 bytes per value.  IEEE. Stored as little-endian.
572    * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes.
573    * FIXED_LEN_BYTE_ARRAY - Just the bytes.
574   */
575  PLAIN = 0;
576
577  /** Group VarInt encoding for INT32/INT64.
578    * This encoding is deprecated. It was never used
579   */
580  //  GROUP_VAR_INT = 1;
581
582  /**
583   * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the
584   * plain type.
585   * in a data page use RLE_DICTIONARY instead.
586   * in a Dictionary page use PLAIN instead
587   */
588  PLAIN_DICTIONARY = 2;
589
590  /** Group packed run length encoding. Usable for definition/repetition levels
591    * encoding and Booleans (on one bit: 0 is false; 1 is true.)
592   */
593  RLE = 3;
594
595  /** Bit packed encoding.  This can only be used if the data has a known max
596    * width.  Usable for definition/repetition levels encoding.
597   */
598  BIT_PACKED = 4;
599
600  /** Delta encoding for integers. This can be used for int columns and works best
601    * on sorted data
602   */
603  DELTA_BINARY_PACKED = 5;
604
605  /** Encoding for byte arrays to separate the length values and the data. The lengths
606    * are encoded using DELTA_BINARY_PACKED
607   */
608  DELTA_LENGTH_BYTE_ARRAY = 6;
609
610  /** Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED.
611    * Suffixes are stored as delta length byte arrays.
612   */
613  DELTA_BYTE_ARRAY = 7;
614
615  /** Dictionary encoding: the ids are encoded using the RLE encoding
616   */
617  RLE_DICTIONARY = 8;
618
619  /** Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY).
620       K byte-streams are created where K is the size in bytes of the data type.
621       The individual bytes of a value are scattered to the corresponding stream and
622       the streams are concatenated.
623       This itself does not reduce the size of the data but can lead to better compression
624       afterwards.
625
626       Added in 2.8 for FLOAT and DOUBLE.
627       Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11.
628   */
629  BYTE_STREAM_SPLIT = 9;
630}
631
632/**
633 * Supported compression algorithms.
634 *
635 * Codecs added in format version X.Y can be read by readers based on X.Y and later.
636 * Codec support may vary between readers based on the format version and
637 * libraries available at runtime.
638 *
639 * See Compression.md for a detailed specification of these algorithms.
640 */
641enum CompressionCodec {
642  UNCOMPRESSED = 0;
643  SNAPPY = 1;
644  GZIP = 2;
645  LZO = 3;
646  BROTLI = 4;  // Added in 2.4
647  LZ4 = 5;     // DEPRECATED (Added in 2.4)
648  ZSTD = 6;    // Added in 2.4
649  LZ4_RAW = 7; // Added in 2.9
650}
651
652enum PageType {
653  DATA_PAGE = 0;
654  INDEX_PAGE = 1;
655  DICTIONARY_PAGE = 2;
656  DATA_PAGE_V2 = 3;
657}
658
659/**
660 * Enum to annotate whether lists of min/max elements inside ColumnIndex
661 * are ordered and if so, in which direction.
662 */
663enum BoundaryOrder {
664  UNORDERED = 0;
665  ASCENDING = 1;
666  DESCENDING = 2;
667}
668
669/** Data page header */
670struct DataPageHeader {
671  /**
672   * Number of values, including NULLs, in this data page.
673   *
674   * If a OffsetIndex is present, a page must begin at a row
675   * boundary (repetition_level = 0). Otherwise, pages may begin
676   * within a row (repetition_level > 0).
677   **/
678  1: required i32 num_values
679
680  /** Encoding used for this data page **/
681  2: required Encoding encoding
682
683  /** Encoding used for definition levels **/
684  3: required Encoding definition_level_encoding;
685
686  /** Encoding used for repetition levels **/
687  4: required Encoding repetition_level_encoding;
688
689  /** Optional statistics for the data in this page **/
690  5: optional Statistics statistics;
691}
692
693struct IndexPageHeader {
694  // TODO
695}
696
697/**
698 * The dictionary page must be placed at the first position of the column chunk
699 * if it is partly or completely dictionary encoded. At most one dictionary page
700 * can be placed in a column chunk.
701 **/
702struct DictionaryPageHeader {
703  /** Number of values in the dictionary **/
704  1: required i32 num_values;
705
706  /** Encoding using this dictionary page **/
707  2: required Encoding encoding
708
709  /** If true, the entries in the dictionary are sorted in ascending order **/
710  3: optional bool is_sorted;
711}
712
713/**
714 * New page format allowing reading levels without decompressing the data
715 * Repetition and definition levels are uncompressed
716 * The remaining section containing the data is compressed if is_compressed is true
717 **/
718struct DataPageHeaderV2 {
719  /** Number of values, including NULLs, in this data page. **/
720  1: required i32 num_values
721  /** Number of NULL values, in this data page.
722       Number of non-null = num_values - num_nulls which is also the number of values in the data section **/
723  2: required i32 num_nulls
724  /**
725   * Number of rows in this data page. Every page must begin at a
726   * row boundary (repetition_level = 0): rows must **not** be
727   * split across page boundaries when using V2 data pages.
728   **/
729  3: required i32 num_rows
730  /** Encoding used for data in this page **/
731  4: required Encoding encoding
732
733  // repetition levels and definition levels are always using RLE (without size in it)
734
735  /** Length of the definition levels */
736  5: required i32 definition_levels_byte_length;
737  /** Length of the repetition levels */
738  6: required i32 repetition_levels_byte_length;
739
740  /**  Whether the values are compressed.
741  Which means the section of the page between
742  definition_levels_byte_length + repetition_levels_byte_length + 1 and compressed_page_size (included)
743  is compressed with the compression_codec.
744  If missing it is considered compressed */
745  7: optional bool is_compressed = true;
746
747  /** Optional statistics for the data in this page **/
748  8: optional Statistics statistics;
749}
750
751/** Block-based algorithm type annotation. **/
752struct SplitBlockAlgorithm {}
753/** The algorithm used in Bloom filter. **/
754union BloomFilterAlgorithm {
755  /** Block-based Bloom filter. **/
756  1: SplitBlockAlgorithm BLOCK;
757}
758
759/** Hash strategy type annotation. xxHash is an extremely fast non-cryptographic hash
760* algorithm. It uses 64 bits version of xxHash.
761 **/
762struct XxHash {}
763
764/**
765 * The hash function used in Bloom filter. This function takes the hash of a column value
766 * using plain encoding.
767 **/
768union BloomFilterHash {
769  /** xxHash Strategy. **/
770  1: XxHash XXHASH;
771}
772
773/**
774 * The compression used in the Bloom filter.
775 **/
776struct Uncompressed {}
777union BloomFilterCompression {
778  1: Uncompressed UNCOMPRESSED;
779}
780
781/**
782 * Bloom filter header is stored at beginning of Bloom filter data of each column
783 * and followed by its bitset.
784 **/
785struct BloomFilterHeader {
786  /** The size of bitset in bytes **/
787  1: required i32 numBytes;
788  /** The algorithm for setting bits. **/
789  2: required BloomFilterAlgorithm algorithm;
790  /** The hash function used for Bloom filter. **/
791  3: required BloomFilterHash hash;
792  /** The compression used in the Bloom filter **/
793  4: required BloomFilterCompression compression;
794}
795
796struct PageHeader {
797  /** the type of the page: indicates which of the *_header fields is set **/
798  1: required PageType type_
799
800  /** Uncompressed page size in bytes (not including this header) **/
801  2: required i32 uncompressed_page_size
802
803  /** Compressed (and potentially encrypted) page size in bytes, not including this header **/
804  3: required i32 compressed_page_size
805
806  /** The 32-bit CRC checksum for the page, to be be calculated as follows:
807    *
808    * - The standard CRC32 algorithm is used (with polynomial 0x04C11DB7,
809    *   the same as in e.g. GZip).
810    * - All page types can have a CRC (v1 and v2 data pages, dictionary pages,
811    *   etc.).
812    * - The CRC is computed on the serialization binary representation of the page
813    *   (as written to disk), excluding the page header. For example, for v1
814    *   data pages, the CRC is computed on the concatenation of repetition levels,
815    *   definition levels and column values (optionally compressed, optionally
816    *   encrypted).
817    * - The CRC computation therefore takes place after any compression
818    *   and encryption steps, if any.
819    *
820    * If enabled, this allows for disabling checksumming in HDFS if only a few
821    * pages need to be read.
822   */
823  4: optional i32 crc
824
825  // Headers for page specific data.  One only will be set.
826  5: optional DataPageHeader data_page_header;
827  6: optional IndexPageHeader index_page_header;
828  7: optional DictionaryPageHeader dictionary_page_header;
829  8: optional DataPageHeaderV2 data_page_header_v2;
830}
831
832/**
833 * Wrapper struct to store key values
834 */
835 struct KeyValue {
836  1: required string key
837  2: optional string value
838}
839
840/**
841 * Sort order within a RowGroup of a leaf column
842 */
843struct SortingColumn {
844  /** The ordinal position of the column (in this row group) **/
845  1: required i32 column_idx
846
847  /** If true, indicates this column is sorted in descending order. **/
848  2: required bool descending
849
850  /** If true, nulls will come before non-null values, otherwise,
851    * nulls go at the end. */
852  3: required bool nulls_first
853}
854
855/**
856 * statistics of a given page type and encoding
857 */
858struct PageEncodingStats {
859
860  /** the page type (data/dic/...) **/
861  1: required PageType page_type;
862
863  /** encoding of the page **/
864  2: required Encoding encoding;
865
866  /** number of pages of this type with this encoding **/
867  3: required i32 count;
868
869}
870
871/**
872 * Description for column metadata
873 */
874struct ColumnMetaData {
875  /** Type of this column **/
876  1: required Type type_
877
878  /** Set of all encodings used for this column. The purpose is to validate
879    * whether we can decode those pages. **/
880  2: required EncodingSet encodings
881
882  /** Path in schema.
883    * Redundant and thus skipped during reading. **/
884  3: required PathInSchema path_in_schema
885
886  /** Compression codec **/
887  4: required CompressionCodec codec
888
889  /** Number of values in this column **/
890  5: required i64 num_values
891
892  /** total byte size of all uncompressed pages in this column chunk (including the headers) **/
893  6: required i64 total_uncompressed_size
894
895  /** total byte size of all compressed, and potentially encrypted, pages
896    *  in this column chunk (including the headers) **/
897  7: required i64 total_compressed_size
898
899  /** Optional key/value metadata **/
900  8: optional list<KeyValue> key_value_metadata
901
902  /** Byte offset from beginning of file to first data page **/
903  9: required i64 data_page_offset
904
905  // /** Byte offset from beginning of file to root index page **/
906  // not used for anything
907  // 10: optional i64 index_page_offset
908
909  /** Byte offset from the beginning of file to first (only) dictionary page **/
910  11: optional i64 dictionary_page_offset
911
912  /** optional statistics for this column chunk */
913  12: optional Statistics statistics;
914
915  /** Set of all encodings used for pages in this column chunk.
916    * This information can be used to determine if all data pages are
917    * dictionary encoded for example **/
918  13: optional list<PageEncodingStats> encoding_stats;
919
920  /** Byte offset from beginning of file to Bloom filter data. **/
921  14: optional i64 bloom_filter_offset;
922
923  /** Size of Bloom filter data including the serialized header, in bytes.
924    * Added in 2.10 so readers may not read this field from old files and
925    * it can be obtained after the BloomFilterHeader has been deserialized.
926    * Writers should write this field so readers can read the bloom filter
927    * in a single I/O.
928   */
929  15: optional i32 bloom_filter_length;
930
931  /**
932   * Optional statistics to help estimate total memory when converted to in-memory
933   * representations. The histograms contained in these statistics can
934   * also be useful in some cases for more fine-grained nullability/list length
935   * filter pushdown.
936   */
937  16: optional SizeStatistics size_statistics;
938
939  /** Optional statistics specific for Geometry and Geography logical types */
940  17: optional Box<GeospatialStatistics> geospatial_statistics;
941}
942
943struct EncryptionWithFooterKey {
944}
945
946struct EncryptionWithColumnKey {
947  /** Column path in schema **/
948  1: required list<string> path_in_schema
949
950  /** Retrieval metadata of column encryption key **/
951  2: optional binary key_metadata
952}
953
954union ColumnCryptoMetaData {
955  1: EncryptionWithFooterKey ENCRYPTION_WITH_FOOTER_KEY
956  2: EncryptionWithColumnKey ENCRYPTION_WITH_COLUMN_KEY
957}
958
959struct ColumnChunk {
960  /** File where column data is stored.  If not set, assumed to be same file as
961     * metadata.  This path is relative to the current file.
962     **/
963  1: optional string file_path
964
965  /** Deprecated: Byte offset in file_path to the ColumnMetaData
966    *
967    * Past use of this field has been inconsistent, with some implementations
968    * using it to point to the ColumnMetaData and some using it to point to
969    * the first page in the column chunk. In many cases, the ColumnMetaData at this
970    * location is wrong. This field is now deprecated and should not be used.
971    * Writers should set this field to 0 if no ColumnMetaData has been written outside
972    * the footer.
973   */
974  2: required i64 file_offset = 0
975
976  /** Column metadata for this chunk. Some writers may also replicate this at the
977    * location pointed to by file_path/file_offset.
978    * Note: while marked as optional, this field is in fact required by most major
979    * Parquet implementations. As such, writers MUST populate this field.
980    **/
981  3: optional ColumnMetaData meta_data
982
983  /** File offset of ColumnChunk's OffsetIndex **/
984  4: optional i64 offset_index_offset
985
986  /** Size of ColumnChunk's OffsetIndex, in bytes **/
987  5: optional i32 offset_index_length
988
989  /** File offset of ColumnChunk's ColumnIndex **/
990  6: optional i64 column_index_offset
991
992  /** Size of ColumnChunk's ColumnIndex, in bytes **/
993  7: optional i32 column_index_length
994
995  /** Crypto metadata of encrypted columns **/
996  8: optional Box<ColumnCryptoMetaData> crypto_metadata
997
998  /** Encrypted column metadata for this chunk **/
999  9: optional binary encrypted_column_metadata
1000}
1001
1002struct RowGroup {
1003  /** Metadata for each column chunk in this row group.
1004    * This list must have the same order as the SchemaElement list in FileMetaData.
1005    **/
1006  1: required list<ColumnChunk> columns
1007
1008  /** Total byte size of all the uncompressed column data in this row group **/
1009  2: required i64 total_byte_size
1010
1011  /** Number of rows in this row group **/
1012  3: required i64 num_rows
1013
1014  /** If set, specifies a sort ordering of the rows in this RowGroup.
1015    * The sorting columns can be a subset of all the columns.
1016   */
1017  4: optional list<SortingColumn> sorting_columns
1018
1019  /** Byte offset from beginning of file to first page (data or dictionary)
1020    * in this row group **/
1021  5: optional i64 file_offset
1022
1023  /** Total byte size of all compressed (and potentially encrypted) column data
1024    *  in this row group **/
1025  6: optional i64 total_compressed_size
1026
1027  /** Row group ordinal in the file **/
1028  7: optional i16 ordinal
1029}
1030
1031/** Empty struct to signal the order defined by the physical or logical type */
1032struct TypeDefinedOrder {}
1033
1034/**
1035 * Union to specify the order used for the min_value and max_value fields for a
1036 * column. This union takes the role of an enhanced enum that allows rich
1037 * elements (which will be needed for a collation-based ordering in the future).
1038 *
1039 * Possible values are:
1040 * * TypeDefinedOrder - the column uses the order defined by its logical or
1041 *                      physical type (if there is no logical type).
1042 *
1043 * If the reader does not support the value of this union, min and max stats
1044 * for this column should be ignored.
1045 */
1046union ColumnOrder {
1047
1048  /**
1049   * The sort orders for logical types are:
1050   *   UTF8 - unsigned byte-wise comparison
1051   *   INT8 - signed comparison
1052   *   INT16 - signed comparison
1053   *   INT32 - signed comparison
1054   *   INT64 - signed comparison
1055   *   UINT8 - unsigned comparison
1056   *   UINT16 - unsigned comparison
1057   *   UINT32 - unsigned comparison
1058   *   UINT64 - unsigned comparison
1059   *   DECIMAL - signed comparison of the represented value
1060   *   DATE - signed comparison
1061   *   FLOAT16 - signed comparison of the represented value (*)
1062   *   TIME_MILLIS - signed comparison
1063   *   TIME_MICROS - signed comparison
1064   *   TIMESTAMP_MILLIS - signed comparison
1065   *   TIMESTAMP_MICROS - signed comparison
1066   *   INTERVAL - undefined
1067   *   JSON - unsigned byte-wise comparison
1068   *   BSON - unsigned byte-wise comparison
1069   *   ENUM - unsigned byte-wise comparison
1070   *   LIST - undefined
1071   *   MAP - undefined
1072   *   VARIANT - undefined
1073   *   GEOMETRY - undefined
1074   *   GEOGRAPHY - undefined
1075   *
1076   * In the absence of logical types, the sort order is determined by the physical type:
1077   *   BOOLEAN - false, true
1078   *   INT32 - signed comparison
1079   *   INT64 - signed comparison
1080   *   INT96 (only used for legacy timestamps) - undefined
1081   *   FLOAT - signed comparison of the represented value (*)
1082   *   DOUBLE - signed comparison of the represented value (*)
1083   *   BYTE_ARRAY - unsigned byte-wise comparison
1084   *   FIXED_LEN_BYTE_ARRAY - unsigned byte-wise comparison
1085   *
1086   * (*) Because the sorting order is not specified properly for floating
1087   *     point values (relations vs. total ordering) the following
1088   *     compatibility rules should be applied when reading statistics:
1089   *     - If the min is a NaN, it should be ignored.
1090   *     - If the max is a NaN, it should be ignored.
1091   *     - If the min is +0, the row group may contain -0 values as well.
1092   *     - If the max is -0, the row group may contain +0 values as well.
1093   *     - When looking for NaN values, min and max should be ignored.
1094   *
1095   *     When writing statistics the following rules should be followed:
1096   *     - NaNs should not be written to min or max statistics fields.
1097   *     - If the computed max value is zero (whether negative or positive),
1098   *       `+0.0` should be written into the max statistics field.
1099   *     - If the computed min value is zero (whether negative or positive),
1100   *       `-0.0` should be written into the min statistics field.
1101   */
1102  1: TypeDefinedOrder TYPE_ORDER;
1103}
1104
1105struct PageLocation {
1106  /** Offset of the page in the file **/
1107  1: required i64 offset
1108
1109  /**
1110   * Size of the page, including header. Sum of compressed_page_size and header
1111   * length
1112   */
1113  2: required i32 compressed_page_size
1114
1115  /**
1116   * Index within the RowGroup of the first row of the page. When an
1117   * OffsetIndex is present, pages must begin on row boundaries
1118   * (repetition_level = 0).
1119   */
1120  3: required i64 first_row_index
1121}
1122
1123/**
1124 * Optional offsets for each data page in a ColumnChunk.
1125 *
1126 * Forms part of the page index, along with ColumnIndex.
1127 *
1128 * OffsetIndex may be present even if ColumnIndex is not.
1129 */
1130struct OffsetIndex {
1131  /**
1132   * PageLocations, ordered by increasing PageLocation.offset. It is required
1133   * that page_locations[i].first_row_index < page_locations[i+1].first_row_index.
1134   */
1135  1: required list<PageLocation> page_locations
1136  /**
1137   * Unencoded/uncompressed size for BYTE_ARRAY types.
1138   *
1139   * See documention for unencoded_byte_array_data_bytes in SizeStatistics for
1140   * more details on this field.
1141   */
1142  2: optional list<i64> unencoded_byte_array_data_bytes
1143}
1144
1145/**
1146 * Optional statistics for each data page in a ColumnChunk.
1147 *
1148 * Forms part the page index, along with OffsetIndex.
1149 *
1150 * If this structure is present, OffsetIndex must also be present.
1151 *
1152 * For each field in this structure, <field>[i] refers to the page at
1153 * OffsetIndex.page_locations[i]
1154 */
1155struct ColumnIndex {
1156  /**
1157   * A list of Boolean values to determine the validity of the corresponding
1158   * min and max values. If true, a page contains only null values, and writers
1159   * have to set the corresponding entries in min_values and max_values to
1160   * byte[0], so that all lists have the same length. If false, the
1161   * corresponding entries in min_values and max_values must be valid.
1162   */
1163  1: required list<bool> null_pages
1164
1165  /**
1166   * Two lists containing lower and upper bounds for the values of each page
1167   * determined by the ColumnOrder of the column. These may be the actual
1168   * minimum and maximum values found on a page, but can also be (more compact)
1169   * values that do not exist on a page. For example, instead of storing ""Blart
1170   * Versenwald III", a writer may set min_values[i]="B", max_values[i]="C".
1171   * Such more compact values must still be valid values within the column's
1172   * logical type. Readers must make sure that list entries are populated before
1173   * using them by inspecting null_pages.
1174   */
1175  2: required list<binary> min_values
1176  3: required list<binary> max_values
1177
1178  /**
1179   * Stores whether both min_values and max_values are ordered and if so, in
1180   * which direction. This allows readers to perform binary searches in both
1181   * lists. Readers cannot assume that max_values[i] <= min_values[i+1], even
1182   * if the lists are ordered.
1183   */
1184  4: required BoundaryOrder boundary_order
1185
1186  /**
1187   * A list containing the number of null values for each page
1188   *
1189   * Writers SHOULD always write this field even if no null values
1190   * are present or the column is not nullable.
1191   * Readers MUST distinguish between null_counts not being present
1192   * and null_count being 0.
1193   * If null_counts are not present, readers MUST NOT assume all
1194   * null counts are 0.
1195   */
1196  5: optional list<i64> null_counts
1197
1198  /**
1199   * Contains repetition level histograms for each page
1200   * concatenated together.  The repetition_level_histogram field on
1201   * SizeStatistics contains more details.
1202   *
1203   * When present the length should always be (number of pages *
1204   * (max_repetition_level + 1)) elements.
1205   *
1206   * Element 0 is the first element of the histogram for the first page.
1207   * Element (max_repetition_level + 1) is the first element of the histogram
1208   * for the second page.
1209   **/
1210   6: optional list<i64> repetition_level_histograms;
1211   /**
1212    * Same as repetition_level_histograms except for definitions levels.
1213    **/
1214   7: optional list<i64> definition_level_histograms;
1215}
1216
1217struct AesGcmV1 {
1218  /** AAD prefix **/
1219  1: optional binary aad_prefix
1220
1221  /** Unique file identifier part of AAD suffix **/
1222  2: optional binary aad_file_unique
1223
1224  /** In files encrypted with AAD prefix without storing it,
1225    * readers must supply the prefix **/
1226  3: optional bool supply_aad_prefix
1227}
1228
1229struct AesGcmCtrV1 {
1230  /** AAD prefix **/
1231  1: optional binary aad_prefix
1232
1233  /** Unique file identifier part of AAD suffix **/
1234  2: optional binary aad_file_unique
1235
1236  /** In files encrypted with AAD prefix without storing it,
1237    * readers must supply the prefix **/
1238  3: optional bool supply_aad_prefix
1239}
1240
1241union EncryptionAlgorithm {
1242  1: AesGcmV1 AES_GCM_V1
1243  2: AesGcmCtrV1 AES_GCM_CTR_V1
1244}
1245
1246/**
1247 * Description for file metadata
1248 */
1249struct FileMetaData {
1250  /** Version of this file **/
1251  1: required i32 version
1252
1253  /** Parquet schema for this file.  This schema contains metadata for all the columns.
1254    * The schema is represented as a tree with a single root.  The nodes of the tree
1255    * are flattened to a list by doing a depth-first traversal.
1256    * The column metadata contains the path in the schema for that column which can be
1257    * used to map columns to nodes in the schema.
1258    * The first element is the root **/
1259  2: required list<SchemaElement> schema;
1260
1261  /** Number of rows in this file **/
1262  3: required i64 num_rows
1263
1264  /** Row groups in this file **/
1265  4: required list<RowGroup> row_groups
1266
1267  /** Optional key/value metadata **/
1268  5: optional list<KeyValue> key_value_metadata
1269
1270  /** String for application that wrote this file.  This should be in the format
1271    * <Application> version <App Version> (build <App Build Hash>).
1272    * e.g. impala version 1.0 (build 6cf94d29b2b7115df4de2c06e2ab4326d721eb55)
1273    **/
1274  6: optional string created_by
1275
1276  /**
1277   * Sort order used for the min_value and max_value fields in the Statistics
1278   * objects and the min_values and max_values fields in the ColumnIndex
1279   * objects of each column in this file. Sort orders are listed in the order
1280   * matching the columns in the schema. The indexes are not necessary the same
1281   * though, because only leaf nodes of the schema are represented in the list
1282   * of sort orders.
1283   *
1284   * Without column_orders, the meaning of the min_value and max_value fields
1285   * in the Statistics object and the ColumnIndex object is undefined. To ensure
1286   * well-defined behaviour, if these fields are written to a Parquet file,
1287   * column_orders must be written as well.
1288   *
1289   * The obsolete min and max fields in the Statistics object are always sorted
1290   * by signed comparison regardless of column_orders.
1291   */
1292  7: optional list<ColumnOrder> column_orders;
1293
1294  /**
1295   * Encryption algorithm. This field is set only in encrypted files
1296   * with plaintext footer. Files with encrypted footer store algorithm id
1297   * in FileCryptoMetaData structure.
1298   */
1299  8: optional EncryptionAlgorithm encryption_algorithm
1300
1301  /**
1302   * Retrieval metadata of key used for signing the footer.
1303   * Used only in encrypted files with plaintext footer.
1304   */
1305  9: optional binary footer_signing_key_metadata
1306}
1307
1308/** Crypto metadata for files with encrypted footer **/
1309struct FileCryptoMetaData {
1310  /**
1311   * Encryption algorithm. This field is only used for files
1312   * with encrypted footer. Files with plaintext footer store algorithm id
1313   * inside footer (FileMetaData structure).
1314   */
1315  1: required EncryptionAlgorithm encryption_algorithm
1316
1317  /** Retrieval metadata of key used for encryption of footer,
1318    *  and (possibly) columns **/
1319  2: optional binary key_metadata
1320}
1321}
1322