Reputation: 1837
I use the TField.origin property to dynamically build a where clause for SQL queries.
So if I have a query such as;
select
p.firstname,
p.lastname,
g.description
from
people p
inner join groups g
I can set the origin of the firstname field to;
FirstNameField.origin = 'p.firstname';
Then use this in the where clause of dynamic queries such as;
SQLWhere = 'where ' + FirstNameField.origin + ' = ''' + MyValue + ''' ';
(obviously i have additional code to prevent against SQL injection).
I do this all the time and it works great. However when trying to track down a bug, I noticed I have one dataset that keeps reseting the value of the origin for example back to;
people.firstname
instead of;
p.firstname
I tracked it down to when the dataset is closed and then reopened. However I do this all the time, so I can't understand why one dataset has different behaviour.
My question is how can I prevent the origin value from getting reset?
Upvotes: 1
Views: 230
Reputation: 30715
The code below is from D7's IBCustomDataSet unit (the code is more complex in later XEx versions).
It's this code which sets the Origin
property of an IBX TField.
TIBCustomDataSet.CreateFields will get called when the dataset calls its InternalOpen
method if its FDefaultFields
field is True. It will be True if on entry to InternalOpen
the FieldCount
of the dataset is zero. FieldCount
will be zero if no fields have
been created in advance, either in user-code or in the IDE using the Fields editor
on the dataset. InternalOpen
is called by TDataSet.Open via its OpenCursor
method.
So the way to avoid 'CreateFields' being executed and the dataset fields' Origin
properties being reset as a consequence is to use either of these methods (IDE or user code)
to create the fields prior to opening the dataset. In other words, if you set the Origin
property by either of these methods, that should avoid it getting reset.
procedure TIBCustomDataSet.CreateFields;
var
FieldAliasName, RelationName : String;
i : Integer;
f : TField;
begin
inherited;
for i := 0 to FQSelect.Current.Count - 1 do
with FQSelect.Current[i].Data^ do
begin
{ Get the field name }
SetString(FieldAliasName, aliasname, aliasname_length);
SetString(RelationName, relname, relname_length);
f := FindField(FieldAliasname);
if Assigned(f) then
begin
if (RelationName <> '') and (FieldAliasName <> '') then
f.Origin := RelationName + '.' + FieldAliasName;
end;
end;
end;
Update The implementation of TIBCustomDataSet.InternalOpen was evidently changed between XE4 and XE6 so that CreateFields is now called unconditionally (i.e. regardless of whether DefaultFields is True). Therefore, having already-existing TFields will not avoid CreateFields being called and therefore the Origin properties being reset.
Upvotes: 3