marsupilami wrote: ↑05.06.2020, 08:52Hello aehimself,
to me it seems like Eginhugeist already applied your patches in revision 6609 / 1d1ab16.
Best regards,
Jan
7.3.0-1d1ab16e works for the test case but unfortunately it does not work for real life. In reality my database table contains 5 versions of the same field:
FIELD
FIELD_1
FIELD_2
FIELD_3
FIELD_4
@Eginhugeis't checkin fails at the burned-in 2 cycles from this perspective. Enumerates first table's fields fine. While enumerating the second (self-joined) table, it looks like this (talking about the flow of TZAbstractResultSetMetadata.GetColumnLabel):
- ColumnName is set to "FIELD"
- First FOR cycle, pass 1 / 2. Second FOR cycle goes through the existing fields, and finds a field named "FIELD" already. It increases N with one.
- Second FOR exits, ColumnName is being changed to "FIELD_1". First FOR exits.
- First FOR cycle, pass 2 / 2. Second FOR cycle goes through the existing fields, and finds a field named "FIELD_1" already. It increases N with one.
- Second FOR exits, ColumnName is being changed to "FIELD_2". First FOR exists.
- First FOR has no more cycles. Final determined field name is FIELD_2.
At a later stage, CreateField is called with this name, which will throw an exception, as FIELD_2 exists too.
This can be changed to an "endless" loop, until field name is not found:
Code: Select all
// for B := False to True do begin //we need two loops to have a unique columnlabel
Repeat
b := False;
//see test TestDuplicateColumnNames or
//https://zeoslib.sourceforge.io/viewtopic.php?f=50&t=120692
for J := 0 to I - 1 do
if TZColumnInfo(ColumnsInfo[J]).ColumnLabel = ColumnName then
Begin
Inc(N);
b := True;
End;
if N > 0 then
ColumnName := OrgLabel + '_' + ZFastCode.IntToStr(N);
Until Not b;
Or we can use my first advised solution, checking if the original OR the next possible field name exists. I don't know which would have less resource footprint.
Edit: I was looking at how PL/SQL is handling this. It is not adding _1 to the end of the field name, simply two fields named "FIELD" shows up in the resultset. I started to wonder. What if we use random names (DB Guids / field positions, whatever) for Field.FieldName and set Field.DisplayName to the original field name? Grids would show the field name as it is in the database and we still could create the dataset. Question is, how much extra work it would mean to fix .FieldByName and all the other methods.
Just an idea, though.