Subject | Re: [IBO] IBOQuery: How to create TField for selected fieldsat runtime? |
---|---|
Author | dirknaudts |
Post date | 2005-02-08T11:12:49Z |
Hi Chuck,
here's a example of what you might do to make those fields get an
ongettext handler at runtime.
Mind you this does cost you an extra query (empty result set tough)
The makepersistent procedure needs to be called in the before open
event of the iboquery.
Also make sure you assign the afterclose handler, to get rid of those
runtime created fields again.
hth,
Dirk Naudts.
----
...
qry: TIBOQuery;
Db: TIBODatabase;
...
procedure TForm1.MakePersistent(qry: Tiboquery);
type
Rfielddata = record
FieldName: string;
datatype: Tfieldtype;
end;
var
p, i: integer;
sqlstr: string;
tmpqry: Tiboquery;
fldarr: array of Rfielddata;
begin
// add where 0=1 to your query
tmpqry := Tiboquery.Create(nil);
try
tmpqry.IB_Connection := qry.IB_Connection;
sqlstr := qry.SQL.Text;
p := Pos('WHERE', uppercase(sqlstr));
if p > 0 then
sqlstr := stringreplace(uppercase(sqlstr), 'WHERE', 'WHERE 0=1
and ', [])
else
begin
p := Pos('ORDER', uppercase(sqlstr));
if p > 0 then
sqlstr := stringreplace(uppercase(sqlstr), 'ORDER', 'WHERE
0=1 ORDER ', [])
else
sqlstr := sqlstr + ' WHERE 0=1 ';
// Add more tests for Unions, group by etc if you please
end;
tmpqry.sql.Text := sqlstr;
tmpqry.Open;
setlength(fldarr, tmpqry.FieldCount);
for i := 0 to tmpqry.fieldcount - 1 do
begin
fldarr[i].FieldName := tmpqry.Fields[i].FieldName;
fldarr[i].datatype := tmpqry.Fields[i].DataType;
end;
tmpqry.Close;
finally
freeandnil(tmpqry);
end;
for i := 0 to Length(fldarr) - 1 do
begin
case fldarr[i].DataType of
ftinteger:
begin
with TIntegerfield.Create(qry) do
begin
Name := qry.Name + fldarr[i].FieldName;
FieldName := fldarr[i].FieldName;
DataSet := qry;
ongettext := GetIntvalue;
end;
end;
ftstring:
begin
with Tstringfield.Create(qry) do
begin
Name := qry.Name + fldarr[i].FieldName;
FieldName := fldarr[i].FieldName;
DataSet := qry;
ongettext := GetStrvalue;
end;
end;
// Add datatype as you need them
end;
end;
qry.FieldDefs.Update;
// Remove where 0=1 clause
end;
procedure TForm1.qryBeforeOpen(DataSet: TDataSet);
begin
makepersistent(qry);
end;
procedure TForm1.qryAfterClose(DataSet: TDataSet);
var i: integer;
fld: TField;
begin
for i := qry.ComponentCount - 1 downto 0 do
begin
if qry.Components[i] is TField then
begin
fld := TField(qry.Components[i]);
freeandnil(fld);
end;
end;
end;
--- In IBObjects@yahoogroups.com, Chuck Belanger <phytotech@l...>
wrote:
here's a example of what you might do to make those fields get an
ongettext handler at runtime.
Mind you this does cost you an extra query (empty result set tough)
The makepersistent procedure needs to be called in the before open
event of the iboquery.
Also make sure you assign the afterclose handler, to get rid of those
runtime created fields again.
hth,
Dirk Naudts.
----
...
qry: TIBOQuery;
Db: TIBODatabase;
...
procedure TForm1.MakePersistent(qry: Tiboquery);
type
Rfielddata = record
FieldName: string;
datatype: Tfieldtype;
end;
var
p, i: integer;
sqlstr: string;
tmpqry: Tiboquery;
fldarr: array of Rfielddata;
begin
// add where 0=1 to your query
tmpqry := Tiboquery.Create(nil);
try
tmpqry.IB_Connection := qry.IB_Connection;
sqlstr := qry.SQL.Text;
p := Pos('WHERE', uppercase(sqlstr));
if p > 0 then
sqlstr := stringreplace(uppercase(sqlstr), 'WHERE', 'WHERE 0=1
and ', [])
else
begin
p := Pos('ORDER', uppercase(sqlstr));
if p > 0 then
sqlstr := stringreplace(uppercase(sqlstr), 'ORDER', 'WHERE
0=1 ORDER ', [])
else
sqlstr := sqlstr + ' WHERE 0=1 ';
// Add more tests for Unions, group by etc if you please
end;
tmpqry.sql.Text := sqlstr;
tmpqry.Open;
setlength(fldarr, tmpqry.FieldCount);
for i := 0 to tmpqry.fieldcount - 1 do
begin
fldarr[i].FieldName := tmpqry.Fields[i].FieldName;
fldarr[i].datatype := tmpqry.Fields[i].DataType;
end;
tmpqry.Close;
finally
freeandnil(tmpqry);
end;
for i := 0 to Length(fldarr) - 1 do
begin
case fldarr[i].DataType of
ftinteger:
begin
with TIntegerfield.Create(qry) do
begin
Name := qry.Name + fldarr[i].FieldName;
FieldName := fldarr[i].FieldName;
DataSet := qry;
ongettext := GetIntvalue;
end;
end;
ftstring:
begin
with Tstringfield.Create(qry) do
begin
Name := qry.Name + fldarr[i].FieldName;
FieldName := fldarr[i].FieldName;
DataSet := qry;
ongettext := GetStrvalue;
end;
end;
// Add datatype as you need them
end;
end;
qry.FieldDefs.Update;
// Remove where 0=1 clause
end;
procedure TForm1.qryBeforeOpen(DataSet: TDataSet);
begin
makepersistent(qry);
end;
procedure TForm1.qryAfterClose(DataSet: TDataSet);
var i: integer;
fld: TField;
begin
for i := qry.ComponentCount - 1 downto 0 do
begin
if qry.Components[i] is TField then
begin
fld := TField(qry.Components[i]);
freeandnil(fld);
end;
end;
end;
--- In IBObjects@yahoogroups.com, Chuck Belanger <phytotech@l...>
wrote:
> Thanks, Carlos!or will the
>
> That may just be the information I need. I'll read it later.
>
> Do you think I should be adding the code to a BeforePrepare event?
> AfterPrepare event still work.wrote:
>
> Chuck
>
> tre955 wrote:
>
> > --- In IBObjects@yahoogroups.com, Chuck Belanger <phytotech@l...>
> > >
> > > What I still need is the same ability to dynamically assign
> > OnGetText event to a
> > > non-persistent TField of the IBOQuery.
> > >
> >
> > Chuck,
> >
> > Can this TI help put you on the right track?
> >
> > Creating & Deleting TFields at run-time
> > http://community.borland.com/article/0,1410,15707,00.html
> >
> > HTH,
> > Carlos