fix: exclude non-editable/alias columns from Query Tool row UPDATE#10171
fix: exclude non-editable/alias columns from Query Tool row UPDATE#10171kundansable wants to merge 2 commits into
Conversation
The added (INSERT) branch of save_changed_data() already filtered out columns that aren't backed by a real table column (added for pgadmin-org#9939 / pgadmin-org#10015), but the updated (UPDATE) branch did not. Editing a row that includes an aliased/expression column (e.g. first_name || ' ' || last_name AS the_name) sent that alias into the generated UPDATE's SET clause, which fails with "column ... does not exist" even though the grid already marks the column read-only. Apply the same editable-columns guard to the updated branch, and skip the row entirely if nothing editable remains after filtering. Fixes pgadmin-org#10103
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe updated save path captures each row identifier before removing tracking fields, filters row data to editable table columns, skips rows without editable fields, and records updates using the preserved identifier. ChangesUpdate filtering
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
web/pgadmin/tools/sqleditor/utils/save_changed_data.py (1)
180-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd regression coverage for updated rows with read-only aliases.
Please add or verify tests covering:
- an updated row containing both an editable column and an alias/computed column;
- a row containing only a non-editable alias.
Assert that the editable value is persisted and the alias-only row produces no
UPDATE.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/pgadmin/tools/sqleditor/utils/save_changed_data.py` around lines 180 - 194, Extend the regression tests covering the save-changed-data flow around the data filtering logic to include a row with both an editable column and a non-editable alias, asserting the editable value is persisted, and a row containing only the alias, asserting no UPDATE is generated or executed. Reuse the existing test fixtures and assertions for updated rows and SQL persistence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@web/pgadmin/tools/sqleditor/utils/save_changed_data.py`:
- Around line 180-194: Extend the regression tests covering the
save-changed-data flow around the data filtering logic to include a row with
both an editable column and a non-editable alias, asserting the editable value
is persisted, and a row containing only the alias, asserting no UPDATE is
generated or executed. Reuse the existing test fixtures and assertions for
updated rows and SQL persistence.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d701b2fa-7918-4e34-9c15-30690aac3d3f
📒 Files selected for processing (1)
web/pgadmin/tools/sqleditor/utils/save_changed_data.py
|
Consistency review: added-row vs updated-row column filtering Nice fix for #10103 — filtering non-editable columns out of One thing worth double-checking: the added-row path explicitly strips the tracking keys before filtering: # lines 113-115
data.pop(client_primary_key, None)
data.pop('is_row_copied', None)
...
data = {
k: v for k, v in data.items()
if k in columns_info and columns_info[k].get('is_editable', True)
}The updated-row path (this PR, lines 179-183) relies solely on the data = changed_data[of_type][each_row]['data']
data = {
k: v for k, v in data.items()
if k in columns_info and columns_info[k].get('is_editable', True)
}I traced Two things I'd still flag:
Not blocking, just wanted these on record in case someone hits it while extending this code path later. |
Per @asheshv's review on PR pgadmin-org#10171: 1. The added-row path explicitly pops the client_primary_key/ is_row_copied tracking keys before filtering to editable columns; the updated-row path relied implicitly on the columns_info filter to drop them, since neither key is ever present on an updated-row payload today. Mirror the explicit pops for symmetry, so this path isn't silently relying on that assumption if a future change starts tagging updated rows the same way (e.g. multi-row copy-paste into existing rows). 2. 'row_id' was read via data.get(client_primary_key) on the already-filtered dict, so it was always None - dead weight now, and actively wrong once point 1 makes the filtering explicit rather than incidental. Capture row_id from the row's data before it's popped/filtered, so a failed update's error report can identify which row failed.
Summary
Fixes #10103 — editing a row in the Query Tool result grid fails to save with
column "..." does not existwhen the query includes an aliased/computed column (e.g.first_name || ' ' || last_name AS the_name), even though that column is already shown as read-only (lock icon) in the grid.Root Cause
save_changed_data()has two code paths —added(INSERT) andupdated(UPDATE). Theaddedpath already filters the outgoing payload down to real, editable table columns (fixed for #9939 in #10015), using the samecolumns_info[...]['is_editable']metadata that drives the grid's lock icon. Theupdatedpath never got the equivalent filter, so an edited row that includes an alias/expression column sends that alias straight into the generatedUPDATE ... SETclause — and Postgres rejects it because there's no such real column.Fix
Apply the same editable-columns guard to the
updatedbranch: drop any key from the changed-row payload that isn't a real, editable table column, and skip the row entirely if nothing editable remains after filtering (avoiding an empty/invalidSETclause).Test Steps
first_namefromJohntoJaneon the existing row.first_nameis updated. Nocolumn "the_name" ... does not existerror.Summary by CodeRabbit