From 4a4c070f1d447c12de754db423b9d6c3ee225c68 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 28 Jun 2023 18:36:58 -0700 Subject: [PATCH] More lazily advance ptr over arrays Array iteration was using the wrong tempo for advancing pointers, so arrays with leading nulls sometimes would advance too far. --- pgrx/src/datum/array.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pgrx/src/datum/array.rs b/pgrx/src/datum/array.rs index c9ae4fd28..e27a233cb 100644 --- a/pgrx/src/datum/array.rs +++ b/pgrx/src/datum/array.rs @@ -626,9 +626,13 @@ impl<'a, T: FromDatum> Iterator for ArrayIterator<'a, T> { fn next(&mut self) -> Option { let Self { array, curr, ptr } = self; let Some(is_null) = array.null_slice.get(*curr) else { return None }; - let element = unsafe { array.bring_it_back_now(*ptr, is_null) }; *curr += 1; - if let Some(false) = array.null_slice.get(*curr) { + + let element = unsafe { array.bring_it_back_now(*ptr, is_null) }; + if !is_null { + // SAFETY: This has to not move for nulls, as they occupy 0 data bytes, + // and it has to move only after unpacking a non-null varlena element, + // as the iterator starts by pointing to the first non-null element! *ptr = unsafe { array.one_hop_this_time(*ptr) }; } Some(element) @@ -679,9 +683,13 @@ impl<'a, T: FromDatum> Iterator for ArrayIntoIterator<'a, T> { fn next(&mut self) -> Option { let Self { array, curr, ptr } = self; let Some(is_null) = array.null_slice.get(*curr) else { return None }; - let element = unsafe { array.bring_it_back_now(*ptr, is_null) }; *curr += 1; - if let Some(false) = array.null_slice.get(*curr) { + + let element = unsafe { array.bring_it_back_now(*ptr, is_null) }; + if !is_null { + // SAFETY: This has to not move for nulls, as they occupy 0 data bytes, + // and it has to move only after unpacking a non-null varlena element, + // as the iterator starts by pointing to the first non-null element! *ptr = unsafe { array.one_hop_this_time(*ptr) }; } Some(element)