Hi,
I don't know if it has been resolved yet - and I cannot look in CodeCentral
at this time -> it is down again.
But, there seems to be a bug in TIBQuery when using multiple parameters with
the same name. Let me explain:
I've got this statement:
"select relatieid, naam, defaultlocatie, vbanr, bvhnr, telefoon, fax
from LEVERANCIER_naw
where (BVHNR = :bvh and :bvh > 0)
or (VBANR = :vba and :vba > 0)"
Here, you can see 4 parameters that are actually 2 - they should get the
same values. When deleting the two extra parameters from the Params property
(designtime), everything is well. Note: probably IBX should already see they
are the same and remove them automagically.
Next, I will prepare the statement. This will trigger the InternalPrepare
method that triggers TIBSQL.PreprocessSQL - below is a small part of that
method:
(ParamState was set by a piece of code before this - it means we're inside a
parameter parse part):
---8<---
ParamState:
begin
{ collect the name of the parameter }
if iCurParamState = ParamDefaultState then
begin
if cCurChar = '"' then
iCurParamState := ParamQuoteState
else if (cCurChar in ['A'..'Z', 'a'..'z', '0'..'9', '_', '$'])
then
sParamName := sParamName + cCurChar
else if FGenerateParamNames then
begin
sParamName := 'IBXParam' + IntToStr(iParamSuffix); {do not
localize}
Inc(iParamSuffix);
iCurState := DefaultState;
slNames.Add(sParamName);
sParamName := '';
end
---8<---
Note the 'slNames.Add' line - it adds the parameter name to a stringlist
variable. Yes, this one accepts duplicates.
In turn, the TIBQuery.SetParams will get triggered from which the part below
is a small piece:
procedure TIBQuery.SetParams;
---8<---
begin
for I := 0 to FParams.Count - 1 do
begin
if Params[i].IsNull then
SQLParams[i].IsNull := True
else begin
SQLParams[i].IsNull := False;
case Params[i].DataType of
---8<---
ftString, ftFixedChar:
SQLParams[i].AsString := Params[i].AsString;
ftBoolean, ftSmallint, ftWord:
SQLParams[i].AsShort := Params[i].AsSmallInt;
ftInteger:
----8<----
Here, you can see that this loop expects the SQLParams property to have the
same number of entries as the Params property. But, because of the multiple
parameters with the same name, the SQLParams thingy holds twice the amount
of entries (in my case). Of course, the copying of the values will go
terribly wrong here and half the parameters I'm using doesn't get filled at
all.
I tried to modify the creation of the stringlist to this:
slNames := TStringList.Create;
slNames.Sorted := True;
slNames.Duplicates := dupIgnore;
But that didn't work either (something about an unknown SQL type in
TIBXSQLDA.Initialize - don't know what I'm talking about here, so leaving it
be.
Anyway, it's easy to reproduce - hard to find - and there probably is a
better solution than my first try :)
Good luck!
--
Martijn Tonies
Upscene Productions
InterBase Workbench - The Developer Tool for InterBase
http://www.interbaseworkbench.com