Subject Re: [IBO] Subtle Bug in RequestLive setting
Author Larry Baddock
Hi, Helen.
Thanks for the prompt reply.

> First of all, you shouldn't be trying to set and unset RequestLive once a
> query is prepared. RequestLive, if true, has one job, which is to
> automatically construct the XxxxxSQL property statements (Insert, Update
> and Delete statements) for a dataset, and only IF
>
> a) no custom XxxxxSQL strings are already in those properties
> b) it is an updatable dataset (single table query, no aggregates, joins or
> unions)
> c) KeyLinks are accurate
>
> If RequestLive is false at prepare time, it is finished with. However,
> what I can't tell you is whether meddling with the property *after* the
> Prepare causes something to get stuffed further down the line.

That's great. Thanks for letting me know. There is nothing about this in the
help file - maybe putting the above in will help lots of people down the
line.

> OK, the next thing you need to make this get treated as a binary string
> and be passed "raw" - that is, unmodified by trimming and what-have-you -
> is to make sure that it is passed in quotes. As you have it, Delphi
> interprets the #0 as a null, the terminator for an array of PChar. It
> therefore treats the preceding chars as the string and discards the rest.
> Enclose the string in quotes and cast it as a string:
>
> q.ParamByName('UOID').AsRawString:=QuotedStr(#55#56#57#0#58#59);
I'm afraid not. Delphi does NOT chop the string at the 0 char. I am using
strings everywhere for this stuff already - I just wrote it out in the style
above to make the example easy to read. I really don't have #1#2#3#4 strings
hardcoded anywhere.

> In fact, you shouldn't actually need AsRawString. A string of OCTETS is
> still a string. You only need to take the necessary care to ensure that
> Delphi doesn't mess with it - as happens when you pass it around unquoted.
I would like to see an example of this happening, without explicitly using
PChar(whatever) in the code, or using PChar style routines. Delphi strings
do NOT get chopped anywhere, for any reason other than you asking for it to
be done (Which you could, of course, do implicitly, by using any of the
PChar stuff without understanding the operation of them).

Try it for yourself:
----------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
s,t,u:String;
begin
s:=#55#56#57#0#58#59;
t:=s;
u:=s+t;
edit1.text:=IntToStr(length(t))+' '+IntToStr(length(u));
end;
----------------------------------------------------
After pushing the button, edit1 will have the value '6 12' in it, as it
should be. Nothing gets silently chopped.

> Not certain, but you might even have to go to greater lengths and
> construct the string byte-by-byte, by concatenating the bytes. But try
> QuotedStr as that's what QuotedStr does itself.
Not necessary (see above), and No, It doesn't.
from Sysutils.pas:
-------------------------------------------
function QuotedStr(const S: string): string;
var
I: Integer;
begin
Result := S;
for I := Length(Result) downto 1 do
if Result[I] = '''' then Insert('''', Result, I);
Result := '''' + Result + '''';
end;
-------------------------------------------
It uses plain old delphi strings, just like I do.

> Yup. Because you made it so.
Nope - I didn't. See above. Somewhere in the bowels of IBO, it was done. If
delphi chopped strings when it felt like it at the 0, virtually nothing in
an app that has been running for a year already would work. I agree,
however, that I am (or, rather, was) using requestlive incorrectly, due to
lack of understanding.

> Or, rather, study up what RequestLive is actually meant to be/do.
I'd love to. The problem seems to be the documentation, or lack thereof, in
this case. Do users have to buy additional documentation to get this
information?

>I can't tell from your code what you were trying to achieve there.
Yes, this is a long story, which probably originates with my
misunderstanding of things, possibly linked to scant documentation.
Basically, a long time ago, I discovered that there were quite a few
operations that would not work on datasets if the requestlive was not set to
true. This is probably still the case. (Maybe you don't need the requestlive
to be true, but you have to set other stuff that I haven't, which a
requestlive change implicitly does). IIRC, one of the operations was a
delete, to remove a row. Changing requestlive to true, and it worked. I
guess that I just assumed at this point that all the really cool toys, like
append, edit, etc. would not work correctly unless requestlive was set to
true. Guess I was wrong, as I have now removed the requestlive to true from
the code, and can now 'append' quite happily. Haven't tried deleting yet
like this - will try and let you know at some stage.

> The other bad thing about making RequestLive a run-time decision at
> execution level is that you totally lose the benefit of reusing a prepared
> statement.
No, you don't. You would only lose the benefit if you kept toggling it from
true to false to true to false to........etc, which would mean a reprepare.
If someone else set the Requestlive to true 3 hours ago on the query you
have just asked a cache for, and you don't unset it, you're fine.

Thanks again for your prompt reply - I now have a slightly better
understanding of the requestlive property.

Kind regards
Larry