shashank created CAMEL-25302:
--------------------------------

             Summary: camel-google-sheets - the 
google-sheets:application-x-struct data type gives the custom column names to 
the wrong columns when the range does not start at column A (values lost or 
repeated), and miscomputes columns beyond ZZ
                 Key: CAMEL-25302
                 URL: https://issues.apache.org/jira/browse/CAMEL-25302
             Project: Camel
          Issue Type: Bug
          Components: camel-google-sheets
            Reporter: shashank


The data type {{google-sheets:application-x-struct}} 
({{GoogleSheetsJsonStructDataTypeTransformer}}, used by the google-sheets 
source and sink Kamelets) maps the columns of a range to JSON property names. 
With {{columnNames}} ("Optional custom column names that map to cell 
coordinates based on their position", Kamelet property) the k-th name should be 
the name of the k-th column of the range. 
{{CellCoordinate.getColumnName(columnIndex, columnStartIndex, columnNames)}} 
picks the name with

{code:java}
index = columnIndex % columnStartIndex;   // when columnStartIndex > 0
{code}

which is the position only for a range that starts at column A. For other 
ranges:

* range {{B2:D3}}, names {{name,age,city}}: every column is named {{name}}. 
Reading, the JSON object of a row is {{\{"name":"Oslo"\}}} instead of 
{{\{"name":"Ann","age":"31","city":"Oslo"\}}} (the later columns overwrite the 
earlier ones). Writing, the row {{\{"name":"Ann","age":31,"city":"Oslo"\}}} is 
sent as {{[Ann, Ann, Ann]}}: the sheet gets the first value in every column;
* range {{C1:E1}}, names {{name,age}}: {{name, age, name}} instead of {{name, 
age, E}};
* with the default {{columnNames}} ({{A}}) and a range from column B on, every 
column is named {{A}} and a read row keeps only its last value.

Separately, the A1 column letters are wrong from three letters on: 
{{getColumnIndex("AAA1")}} is 52 instead of 702 (it adds {{(letter + 1) * 26}} 
for every letter but the last), and {{getColumnName(702)}} throws 
{{ArrayIndexOutOfBoundsException}} (it writes at most one overflow letter). 
Google Sheets has columns up to ZZZ.

h3. Reproduction

* {{GoogleSheetsJsonStructDataTypeTransformerTest}}: three new tests, all fail 
on main: read of a {{ValueRange}} for {{Sheet1!B2:D3}} with names 
{{name,age,city}}; split read of {{C1:E1}} with names {{name,age}}; write of a 
JSON row for {{B1:D1}} ({{expected: <[Ann, 31, Oslo]> but was: <[Ann, Ann, 
Ann]>}}).
* New {{CellCoordinateTest}}: names by position for ranges starting at A, B and 
C (fails on main), three-letter columns {{AAA}}/{{XFD}} and the range 
{{ZZ1:AAB2}} (fails), name/index round trip for all 18278 columns up to ZZZ 
(fails at 702), and a control for one and two letters (passes on main). It also 
pins the default names {{A}} for a range starting at B ({{A}}, {{C}}, {{D}}).

h3. Proposed fix

* Position of a column in the range: {{columnIndex - columnStartIndex}}; 
columns after the last custom name keep their A1 name, as today for ranges 
starting at A.
* Column letters as a number in bijective base 26 (A=1 .. Z=26, AA=27, ...), 
for both directions. Names and indexes up to ZZ are unchanged.

For ranges that start at column A the names are exactly as today, so all 
existing tests pass (camel-google-sheets: 33 tests).

The default column names: the Kamelets pass {{columnNames=A}} when the user 
sets none. With the fix the first column of any range takes the first name, so 
with the default it is still named {{A}}, as today: a single column range such 
as {{B:B}} is read as {{\{"A": ...\}}} and written from the property {{A}} 
before and after the fix, so such working setups keep working. The other 
columns of a wider range keep their A1 name ({{B2:D3}}: {{A}}, {{C}}, {{D}}) 
instead of all being named {{A}}. Treating the default {{A}} as "no custom 
names" would give nicer names ({{B}}, {{C}}, {{D}}) but would rename the column 
of every {{B:B}} setup that works today, so the fix keeps the positional rule 
that the Kamelet property describes. (The column naming of 
{{application-x-struct}} is not described in the Camel documentation, only in 
the Kamelet property descriptions.)

No upgrade note: the output changes only where main repeats a name inside the 
range. For a range starting at column {{s > 0}}, the fix and main can differ 
only from column {{2s}} on, and there main gives column {{s}} and column {{2s}} 
the same name (Lean theorem {{fix_eq_main_or_main_repeats}}), so such a row 
lost a value when read and repeated one when written. Ranges at most {{s}} 
columns wide, and all ranges starting at A, are named as before.

Found with a Lean 4 model of {{getColumnName}} and of the column letter 
arithmetic: the property "the k-th column of the range gets the k-th custom 
name" fails for every row of a range starting at column B (all columns get the 
first name, theorem {{main_from_B_all_first}}) and holds for the fix for every 
start column ({{fix_by_position}}); the property "index and name are inverse" 
fails for every three-letter column ({{main_wrong_three}}, {{main_name_fails}}) 
and is proved for the fix for every column ({{fix_roundtrip}}), which names the 
columns A..ZZ as today ({{fix_eq_main_name}}).

Affected: 4.14.x, 4.18.x and main (same code since the transformers moved from 
the Kamelet utils to Camel, CAMEL-20087).

Duplicate check (2026-10-03): JIRA text "google-sheets" with "column" / 
"columnNames" (CAMEL-20678, CAMEL-12967: other problems), "CellCoordinate" 
(none). GitHub pull requests "google-sheets column", "CellCoordinate": none.

_Filed with Claude Code on behalf of allthingssecurity._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to