eugenegujing opened a new pull request, #7761:
URL: https://github.com/apache/texera/pull/7761

   ### What changes were proposed in this PR?
   
   `pytexera/udf/examples/join_operator.py` — the shipped hash-join example and 
the only dual-input example operator — emits a match with `yield left_tuple + 
tuple_`, but `core.models.Tuple` implements no `__add__`/`__radd__`, so every 
join match raises `TypeError: unsupported operand type(s) for +: 'Tuple' and 
'Tuple'`. The only output-producing branch of the example has never worked; a 
user who copies this example into a dual-input Python UDF gets a crash on the 
first match.
   
   This PR replaces the `+` with an explicit dict merge:
   
   ```python
   # join and output; on duplicate column names the
   # probe (right) side's value wins
   yield {**left_tuple.as_dict(), **tuple_.as_dict()}
   ```
   
   Yielding a plain dict is the established idiom in the sibling examples 
(`generator_operator_integer.py` / `generator_operator_binary.py` already do 
it). The merge implies a collision policy — on duplicate column names the probe 
(right) side's value wins, while left columns keep their order and position — 
and the new comment records that decision explicitly instead of hiding it. 
   
   ### Any related issues, documentation, discussions?
   
   Closes #7759
   
   ### How was this PR tested?
   
   `join_operator.py` was the only example operator without a spec. This PR 
adds `amber/src/test/python/pytexera/udf/examples/test_join_operator.py`, 
written before the fix (TDD) — the three match-producing tests fail with the 
exact TypeError against the unfixed code. 12 tests total:
   
   - one match emits exactly one merged tuple containing all columns from both 
sides
   - a probe tuple with no matching key emits nothing
   - duplicate build-side keys emit one merged output per stored left tuple, in 
insertion order
   - two build rows × two probe rows on the same key emit four merged outputs
   - build-side (port 0) tuples emit nothing
   - probing an empty build side emits nothing
   - on colliding column names the probe side's value wins (asserted via a 
shared non-key column, since the `key` values are equal on any match by 
definition)
   - merged output column order: left columns keep their order and position 
(collided columns included), probe-only columns are appended
   - `None` keys join each other (pins the current behavior, which diverges 
from SQL NULL semantics — `None` is an ordinary hashable dict key in Python)
   - an emitted output does not alias the stored build-side data (mutating an 
output cannot corrupt later matches)
   - an `int` key matches an equal `float` key (Python cross-type numeric 
equality); an `int` key does not match its string form
   
   Run with:
   
   ```
   cd amber && pytest src/test/python/pytexera/udf/examples/ -v
   ```
   
   → 23 passed (12 new + 11 pre-existing example tests). The spec was also 
mutation-checked: reverting the fix, swapping the merge order, probing only the 
first match, making the build branch yield, type-strict key matching, skipping 
`None` keys, and an aliasing stored-dict implementation each cause the intended 
test(s) to fail. The end-to-end behavior was additionally verified in the UI 
with a two-source workflow feeding a `DualInputPortsPythonUDFV2`: the verbatim 
example code crashes with the TypeError above, and the fixed code emits the 
expected single merged row.
   
   ### Was this PR authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Claude Fable 5)


-- 
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