SEPURI-SAI-KRISHNA opened a new issue, #45082:
URL: https://github.com/apache/superset/issues/45082

   ### Bug description
   
   `_append_columns` splits a `columns` mapping into an overwrite half and an 
append half by asking whether the source and target names match. A rename can 
land on a label that is already in the frame, and that case goes down the 
append path, so the result carries two columns under the same name.
   
   #45018 fixed the mixed-mapping case of this (#45017) by introducing that 
split. This is the residual: @EnxDev raised it in review on #45018 and I 
recorded it on #45017, which auto-closed as completed when #45018 merged, so it 
is filed here on its own.
   
   Reproduction on current master:
   
   ```python
   from pandas import DataFrame
   from superset.utils.pandas_postprocessing.utils import _append_columns
   
   base_df = DataFrame({"y": [1, 2], "z": [3, 4]})
   append_df = DataFrame({"y": [10, 20]})
   _append_columns(base_df, append_df, {"y": "z"})
   #    y  z   z
   # 0  1  3  10
   # 1  2  4  20
   ```
   
   `base_df` already has a `z`, so the mapping renames onto an existing column. 
Because `y != z`, the pair is appended instead of overwriting, and 
`columns.duplicated().any()` is true.
   
   Expected: the mapping overwrites `z`, giving `['y', 'z']` with `z` holding 
`[10, 20]`.
   
   A duplicate label makes `df["z"]` return a DataFrame where every caller 
expects a Series, which is the same failure mode as #45017: downstream 
operations that do a per-column operation raise, and the chart data response 
carries two fields with the same name.
   
   Reached through any operation that passes a user-supplied mapping to 
`_append_columns`, which is `cum`, `diff` and `rolling`, plus `geohash_decode`, 
`geohash_encode` and `geodetic_parse` where the new column is named after one 
that already exists.
   
   ### How to reproduce the bug
   
   1. Create a chart whose query result has columns `y` and `z`.
   2. Add a `cum` post-processing operation with `columns: {"y": "z"}`.
   3. The response carries two `z` columns.
   
   ### Screenshots/recordings
   
   _No response_
   
   ### Superset version
   
   master / latest-dev
   
   ### Python version
   
   3.11
   
   ### Node version
   
   Not applicable
   
   ### Browser
   
   Not applicable
   
   ### Additional context
   
   On #45018 I suggested keying the split on `value in base_df.columns` and 
said it subsumes the matching case, "since a `{"y": "y"}` target is present by 
definition". That is wrong, and I am correcting it here before anyone builds on 
it.
   
   It holds for `cum`, `diff` and `rolling`, where `@validate_column_args` 
guarantees the mapping's keys are columns of `base_df`. It does not hold for 
the geography operations, where the keys are `append_df`'s column names: 
`geodetic_parse` passes `{"latitude": "latitude"}` whenever the caller keeps 
the default column name, and `latitude` is not in `base_df` at all. Keying on 
presence alone would send that down the append path, and `pd.concat` unions the 
index rather than aligning, so a frame without a 0-based index gains a row per 
parsed row:
   
   ```python
   base_df = DataFrame({"city": ["A", "B"]}, index=[5, 6])
   append_df = DataFrame({"latitude": [41.1, 40.7]})
   # presence-keyed split: 4 rows instead of 2
   ```
   
   Both halves of the condition are needed. An entry should be appended only 
when its target is a label the result does not already have, meaning the target 
differs from the source **and** is not already in `base_df`. Measured over 1152 
mappings across four index shapes, that condition changes behaviour only where 
a target already exists, with no column reordering and no case where the row 
count moves except where the old code was producing both a duplicate label and 
extra rows.
   
   ### Checklist
   
   - [x] I have searched Superset docs and Slack and didn't find a solution to 
my problem.
   - [x] I have searched the GitHub issue tracker and didn't find a similar bug 
report.
   - [x] I have checked Superset's logs for errors and if I found a relevant 
Python stacktrace, I included it here as text or in a screenshot.
   


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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to