You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by GitBox <gi...@apache.org> on 2022/07/18 17:19:12 UTC

[GitHub] [arrow-rs] tustvold commented on a diff in pull request #2097: Support skip_values in DictionaryDecoder

tustvold commented on code in PR #2097:
URL: https://github.com/apache/arrow-rs/pull/2097#discussion_r923621973


##########
parquet/src/arrow/array_reader/byte_array_dictionary.rs:
##########
@@ -459,7 +481,75 @@ mod tests {
                 None,
                 Some("1"),
                 Some("2"),
-                None
+                None,
+            ]
+        )
+    }
+
+    #[test]
+    fn test_dictionary_preservation_skip() {
+        let data_type = utf8_dictionary();
+
+        let data: Vec<_> = vec!["0", "1", "0", "1", "2", "1", "2"]
+            .into_iter()
+            .map(ByteArray::from)
+            .collect();
+        let (dict, encoded) = encode_dictionary(&data);
+
+        let column_desc = utf8_column();
+        let mut decoder = DictionaryDecoder::<i32, i32>::new(&column_desc);
+
+        decoder
+            .set_dict(dict, 3, Encoding::RLE_DICTIONARY, false)
+            .unwrap();
+
+        decoder
+            .set_data(Encoding::RLE_DICTIONARY, encoded, 14, Some(data.len()))
+            .unwrap();
+
+        let mut output = DictionaryBuffer::<i32, i32>::default();
+        assert_eq!(decoder.skip_values(1).unwrap(), 1);
+        assert_eq!(decoder.read(&mut output, 0..2).unwrap(), 2);
+
+        let mut valid = vec![false, false, false, true, false, true];
+        let valid_buffer = Buffer::from_iter(valid.iter().cloned());
+        output.pad_nulls(0, 2, valid.len(), valid_buffer.as_slice());
+
+        assert!(matches!(output, DictionaryBuffer::Dict { .. }));
+
+        assert_eq!(decoder.skip_values(1).unwrap(), 1);
+        assert_eq!(decoder.read(&mut output, 0..3).unwrap(), 3);

Review Comment:
   I think it should be 2..5 if anything, you've only read 2 values



##########
parquet/src/arrow/array_reader/byte_array_dictionary.rs:
##########
@@ -368,16 +368,38 @@ where
                             dict_offsets,
                             dict_values,
                         )?;
-
+                        *max_remaining_values -= len;
                         Ok(len)
                     }
                 }
             }
         }
     }
 
-    fn skip_values(&mut self, _num_values: usize) -> Result<usize> {
-        Err(nyi_err!("https://github.com/apache/arrow-rs/issues/1792"))
+    fn skip_values(&mut self, num_values: usize) -> Result<usize> {
+        match self.decoder.as_mut().expect("decoder not set in DictionaryDecoder.") {
+            MaybeDictionaryDecoder::Fallback(decoder) => {
+                decoder.skip_without_dict(num_values)
+            }
+            MaybeDictionaryDecoder::Dict {
+                decoder,
+                max_remaining_values, } => {
+                let to_skip = num_values.min(*max_remaining_values);
+
+                let dict = self
+                    .dict
+                    .as_ref()
+                    .ok_or_else(|| general_err!("missing dictionary page for column"))?;
+
+                if dict.is_empty() {

Review Comment:
   I'm not sure why this check is necessary, removing the corresponding check from read, doesn't seem to fail any tests



##########
parquet/src/arrow/array_reader/byte_array_dictionary.rs:
##########
@@ -459,7 +481,75 @@ mod tests {
                 None,
                 Some("1"),
                 Some("2"),
-                None
+                None,
+            ]
+        )
+    }
+
+    #[test]
+    fn test_dictionary_preservation_skip() {
+        let data_type = utf8_dictionary();
+
+        let data: Vec<_> = vec!["0", "1", "0", "1", "2", "1", "2"]
+            .into_iter()
+            .map(ByteArray::from)
+            .collect();
+        let (dict, encoded) = encode_dictionary(&data);
+
+        let column_desc = utf8_column();
+        let mut decoder = DictionaryDecoder::<i32, i32>::new(&column_desc);
+
+        decoder
+            .set_dict(dict, 3, Encoding::RLE_DICTIONARY, false)
+            .unwrap();
+
+        decoder
+            .set_data(Encoding::RLE_DICTIONARY, encoded, 14, Some(data.len()))
+            .unwrap();
+
+        let mut output = DictionaryBuffer::<i32, i32>::default();
+        assert_eq!(decoder.skip_values(1).unwrap(), 1);
+        assert_eq!(decoder.read(&mut output, 0..2).unwrap(), 2);
+
+        let mut valid = vec![false, false, false, true, false, true];
+        let valid_buffer = Buffer::from_iter(valid.iter().cloned());
+        output.pad_nulls(0, 2, valid.len(), valid_buffer.as_slice());
+
+        assert!(matches!(output, DictionaryBuffer::Dict { .. }));
+
+        assert_eq!(decoder.skip_values(1).unwrap(), 1);
+        assert_eq!(decoder.read(&mut output, 0..3).unwrap(), 3);
+
+        valid.extend_from_slice(&[false, false, false, true, false, true, true, false]);

Review Comment:
   I think these tests would be easier to follow if they didn't include the null padding logic, which seems unnecessary for testing the skip behaviour



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org