jonasdedden commented on PR #51611:
URL: https://github.com/apache/arrow/pull/51611#issuecomment-6395800659

   Since the type issues kept coming one at a time, I fuzzed `list_contains` 
for results that change when only the representation of the same data changes. 
This covered about 30 value types * 30 query types:
   - **Values:** dictionary encoding, plain/large/view layouts, child offsets, 
garbage values under null lists or between views.
   - **Lists:** list, large list, list view and fixed-size list layouts, slices 
and chunks.
   - **Queries:** scalar vs array queries, dictionary encoding and chunks.
   - **Code paths:** scalar lists vs repeated lists.
   - **Checks:** same-type results are compared against searching the decoded 
lists, and type errors must not depend on the data.
   
   Against an older build it finds all the issues raised in review so far. 
Against c47a14b it found these:
   
   - **Binary views vs other binary layouts:** `equal` can't compare `string` 
with `string_view`, so `list<string>` with a `string_view` query raised, while 
a `string` query worked. Views are now compared as their large types, like 
float16 as float32.
   - **Temporal dictionaries without casts:** the cast check looked at the 
dictionary type, which accepts every cast. So a dictionary of durations against 
timestamps returned a result for null queries (`[False]`) and raised 
`ArrowInvalid` otherwise, while plain durations raise `NotImplemented`. It now 
checks the decoded type.
   - **All-null dictionary queries:** queries of a `null`-typed dictionary, or 
a dictionary with only null entries, weren't recognized as null queries. They 
raised against values that `equal` can't compare, like structs, while a plain 
null query works. Null queries are now detected after decoding dictionaries.
   - **Null-typed dictionaries segfaulted:** `dict_util` read the validity 
bitmap of a `null`-typed dictionary, which has none. This crashed 
`list_contains` with null queries on a scalar list of such values, and on 
`main` it already crashes `pc.is_null` and `pc.is_valid`. Fixed in 
`dict_util.cc` in its own commit (abc2fa2); the rest is in 260a708.
   
   <details>
   <summary>Reproduction</summary>
   
   ```python
   import datetime as dt
   import pyarrow as pa
   import pyarrow.compute as pc
   
   
   def show(label, call):
       try:
           print(f"{label}: {call().to_pylist()}", flush=True)
       except pa.ArrowException as e:
           print(f"{label}: {type(e).__name__}: {str(e)[:80]}", flush=True)
   
   
   # 1. Binary views vs the other binary layouts
   strings = pa.array([["x"], ["y"]])
   show("1a. list<string> vs string query, expect [True, False]",
        lambda: pc.list_contains(strings, pa.scalar("x")))
   show("1b. list<string> vs string_view query, expect [True, False]",
        lambda: pc.list_contains(strings, pa.scalar("x", pa.string_view())))
   
   # 2. Temporal dictionaries vs durations, which timestamps don't cast to
   timestamps = pa.array([[dt.datetime(2020, 1, 1)]], 
pa.list_(pa.timestamp("s")))
   durations = pa.array([None], pa.duration("s"))
   show("2a. duration null query, expect NotImplemented",
        lambda: pc.list_contains(timestamps, durations))
   show("2b. dictionary duration null query, expect NotImplemented",
        lambda: pc.list_contains(timestamps, durations.dictionary_encode()))
   show("2c. dictionary duration query, expect NotImplemented",
        lambda: pc.list_contains(timestamps, pa.array([dt.timedelta(1)], 
pa.duration("s"))
                                 .dictionary_encode()))
   
   # 3. All-null dictionary queries vs values "equal" can't compare
   structs = pa.array([[{"a": 1}, None]])
   show("3a. null query, expect [True]", lambda: pc.list_contains(structs, 
None))
   show("3b. dict<null> null query, expect [True]",
        lambda: pc.list_contains(structs, pa.DictionaryArray.from_arrays(
            pa.array([0], pa.int8()), pa.nulls(1))))
   
   # 4. Null-typed dictionaries (last, as this segfaults)
   null_dict = pa.DictionaryArray.from_arrays(pa.array([0, 0], pa.int16()), 
pa.nulls(1))
   show("4a. scalar list of dict<null>, null queries, expect [True, True]",
        lambda: pc.list_contains(pa.ListArray.from_arrays([0, 2], null_dict)[0],
                                 pa.array([None, None], pa.int64())))
   show("4b. is_null(dict<null>), expect [True, True]", lambda: 
pc.is_null(null_dict))
   ```
   
   On c47a14b:
   ```
   1a. list<string> vs string query, expect [True, False]: [True, False]
   1b. list<string> vs string_view query, expect [True, False]: 
ArrowNotImplementedError: Function 'equal' has no kernel matching input types 
(string, string_view)
   2a. duration null query, expect NotImplemented: ArrowNotImplementedError: 
Unsupported cast from duration[s] to timestamp[s]
   2b. dictionary duration null query, expect NotImplemented: [False]
   2c. dictionary duration query, expect NotImplemented: ArrowInvalid: Cast 
type timestamp[s] incompatible with dictionary type duration[s]
   3a. null query, expect [True]: [True]
   3b. dict<null> null query, expect [True]: ArrowNotImplementedError: Function 
'equal' has no kernel matching input types (struct<a: int64>, struct<a:
   Segmentation fault
   ```
   
   With abc2fa2 and 260a708, every line prints its expected result.
   </details>
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to