@@ -28,6 +28,78 @@ struct ArrayMinMaxFunction {
2828 // Results refer to strings in the first argument.
2929 static constexpr int32_t reuse_strings_from_arg = 0 ;
3030
31+ template <typename TReturn, typename TInput>
32+ bool call (TReturn& out, const TInput& array) {
33+ // Result is null if array is empty.
34+ if (array.size () == 0 ) {
35+ return false ;
36+ }
37+
38+ if (!array.mayHaveNulls ()) {
39+ // Input array does not have nulls.
40+ auto currentValue = *array[0 ];
41+ for (auto i = 1 ; i < array.size (); i++) {
42+ update (currentValue, array[i].value ());
43+ }
44+ assign (out, currentValue);
45+ return true ;
46+ }
47+
48+ // Try to find the first non-null element.
49+ auto it = array.begin ();
50+ while (it != array.end () && !it->has_value ()) {
51+ ++it;
52+ }
53+ // If array contains only NULL elements, return NULL.
54+ if (it == array.end ()) {
55+ return false ;
56+ }
57+
58+ // Now 'it' point to the first non-null element.
59+ auto currentValue = it->value ();
60+ ++it;
61+ while (it != array.end ()) {
62+ if (it->has_value ()) {
63+ update (currentValue, it->value ());
64+ }
65+ ++it;
66+ }
67+
68+ assign (out, currentValue);
69+ return true ;
70+ }
71+
72+ bool call (
73+ out_type<Orderable<T1 >>& out,
74+ const arg_type<Array<Orderable<T1 >>>& array) {
75+ // Result is null if array is empty.
76+ if (array.size () == 0 ) {
77+ return false ;
78+ }
79+
80+ int currentIndex = -1 ;
81+ for (auto i = 0 ; i < array.size (); i++) {
82+ if (array[i].has_value ()) {
83+ if (currentIndex == -1 ) {
84+ currentIndex = i;
85+ } else {
86+ auto currentValue = array[currentIndex].value ();
87+ auto candidateValue = array[i].value ();
88+ if (compare (currentValue, candidateValue)) {
89+ currentIndex = i;
90+ }
91+ }
92+ }
93+ }
94+ if (currentIndex == -1 ) {
95+ // If array contains only NULL elements, return NULL.
96+ return false ;
97+ }
98+ out.copy_from (array[currentIndex].value ());
99+ return true ;
100+ }
101+
102+ private:
31103 template <typename T>
32104 void update (T& currentValue, const T& candidateValue) {
33105 // NaN is greater than any non-NaN elements for double/float type.
@@ -66,45 +138,18 @@ struct ArrayMinMaxFunction {
66138 out.setNoCopy (value);
67139 }
68140
69- template <typename TReturn, typename TInput>
70- bool call (TReturn& out, const TInput& array) {
71- // Result is null if array is empty.
72- if (array.size () == 0 ) {
73- return false ;
74- }
75-
76- if (!array.mayHaveNulls ()) {
77- // Input array does not have nulls.
78- auto currentValue = *array[0 ];
79- for (auto i = 1 ; i < array.size (); i++) {
80- update (currentValue, array[i].value ());
81- }
82- assign (out, currentValue);
83- return true ;
84- }
85-
86- // Try to find the first non-null element.
87- auto it = array.begin ();
88- while (it != array.end () && !it->has_value ()) {
89- ++it;
90- }
91- // If array contains only NULL elements, return NULL.
92- if (it == array.end ()) {
93- return false ;
94- }
141+ bool compare (
142+ exec::GenericView currentValue,
143+ exec::GenericView candidateValue) {
144+ static constexpr CompareFlags kFlags = {
145+ .nullHandlingMode = CompareFlags::NullHandlingMode::kNullAsValue };
95146
96- // Now 'it' point to the first non-null element.
97- auto currentValue = it->value ();
98- ++it;
99- while (it != array.end ()) {
100- if (it->has_value ()) {
101- update (currentValue, it->value ());
102- }
103- ++it;
147+ auto compareResult = candidateValue.compare (currentValue, kFlags ).value ();
148+ if constexpr (isMax) {
149+ return compareResult > 0 ;
150+ } else {
151+ return compareResult < 0 ;
104152 }
105-
106- assign (out, currentValue);
107- return true ;
108153 }
109154};
110155
0 commit comments