Board index » delphi » TQuery.Locate Doesn't work as expected

TQuery.Locate Doesn't work as expected

Hello,

Working with TQuery.locate I found the following strange behaviour.

Value1,Value2: integer;
Query.Locate('field1;field2', VarArrayOf([value1,value2]),[]) This Works
as expected

Where as:
Query.Locate('field1', VarArrayOf([value1]),[])

givesthe following error:

"Invalid variant type conversion"

Changing it to:
Query.Locate('field1;field1', VarArrayOf([value1,value1]),[])

Works without giving an error

This also works :

Locate('field1',value1,[])

I didn't see any documentation on the last variation

is this a bug or a feature Why can't I use VarArray's with length 1
We also tried to pass our own variant Array with length 1

Can anyone shine a light on this matter
Thanks

Sjef van der Velde

 

Re:TQuery.Locate Doesn't work as expected


This one got me too. Try

     Query.Locate('field1', Variant(value1),[])

"J. van der Velde" wrote:

Quote
> Hello,

> Working with TQuery.locate I found the following strange behaviour.

> Value1,Value2: integer;
> Query.Locate('field1;field2', VarArrayOf([value1,value2]),[]) This Works
> as expected

> Where as:
> Query.Locate('field1', VarArrayOf([value1]),[])

> givesthe following error:

> "Invalid variant type conversion"

> Changing it to:
> Query.Locate('field1;field1', VarArrayOf([value1,value1]),[])

> Works without giving an error

> This also works :

> Locate('field1',value1,[])

> I didn't see any documentation on the last variation

> is this a bug or a feature Why can't I use VarArray's with length 1
> We also tried to pass our own variant Array with length 1

> Can anyone shine a light on this matter
> Thanks

> Sjef van der Velde

--
Ken Bailey
Falmouth Software Works Ltd.

Re:TQuery.Locate Doesn't work as expected


Hello!

Quote
>Value1,Value2: integer;
>Query.Locate('field1;field2', VarArrayOf([value1,value2]),[]) This Works
>as expected

>Where as:
>Query.Locate('field1', VarArrayOf([value1]),[])

>givesthe following error:

>"Invalid variant type conversion"

>Changing it to:
>Query.Locate('field1;field1', VarArrayOf([value1,value1]),[])

>Works without giving an error

[...]
>is this a bug or a feature Why can't I use VarArray's with length 1
>We also tried to pass our own variant Array with length 1

Well, this is a very interesting "feature" ;-> in the DbClient.pas (same in
DbTables.pas); take a look at this piece of source of the
...DataSet.LocateRecord(...) function:

[...]
      if FieldCount = 1 then
        TField(Fields.First).Value := KeyValues
      else
        for I := 0 to FieldCount - 1 do
          TField(Fields[I]).Value := KeyValues[I];
[...]

You sure can have a VarArray with the length of one, but the LocateRecord
function (which is called by the Locate function) expects an VarArray only,
if you have more than one KeyField; if you have only one KeyField
(FieldCount = 1) then it assigns the Value of KeyValues without index,
expecting a valid type, like a varInteger or varBoolean or varString or
else, but sure not a varArray!
The right code matching the documentation should be

      if FieldCount = 1 then
        TField(Fields.First).Value := KeyValues[0]

or even better, delete the whole if..then..else statement and only use the
else part (having a for..to..do loop from 0 to 0, if there is only one
KeyField), but as a workaround, you can just pass a single Variant, if you
have only
one KeyField, as you mentioned:

Quote
>This also works :

>Locate('field1',value1,[])

>I didn't see any documentation on the last variation

Hope that helps, see you

christoph
--
Christoph Roeper
Tel +49 241 963 2683
eMail christ...@interware-gmbh.de
eMail ro...@earthling.net
   | Interware GmbH
   | Dennewartstrasse 27
   | D-52068 Aachen
   | Tel +49 241 963 2680
   | Fax +49 241 963 2688
   | eMail i...@interware-gmbh.de

Re:TQuery.Locate Doesn't work as expected


Hi Christoph,

Thanks for sorting that out.
It Would be nice if the doc's represented this behavoir.

It Seems that someone at Borland/Inprise has outwithed him/herself

Sjef

Quote
Christoph Roeper wrote:
> >Query.Locate('field1', VarArrayOf([value1]),[])
> >givesthe following error:
> >"Invalid variant type conversion"
> >is this a bug or a feature Why can't I use VarArray's with length 1

> Well, this is a very interesting "feature" ;-> in the DbClient.pas (same in
> DbTables.pas); take a look at this piece of source of the
> ...DataSet.LocateRecord(...) function:

> [...]
>       if FieldCount = 1 then
>         TField(Fields.First).Value := KeyValues
>       else
>         for I := 0 to FieldCount - 1 do
>           TField(Fields[I]).Value := KeyValues[I];
> [...]

Re:TQuery.Locate Doesn't work as expected


[extracted from help topic for TBDEDataSet.Locate (D4UP2)]

KeyValues is a variant that specifies the values to match in the key fields.
If KeyFields lists a single field, KeyValues specifies the value for that
field on the desired record. To specify multiple search values, pass a
variant array as KeyValues, or construct a variant array on the fly using
the VarArrayOf routine.

[end of extract]

I know posting info from help is annoying, but the behavior you describe
seems to be clearly documented in that paragraph.  A variant array should
only be used when specifying multiple search values.

V/R
Russell L. Smith

J. van der Velde wrote in message <3663B3C8.C41A4...@skzl.nl>...

Quote
>I didn't see any documentation on the last variation

Re:TQuery.Locate Doesn't work as expected


Shouldn't need to cast as variant; will be done implicitly.

V/R
Russell L. Smith

Quote
Ken Bailey wrote in message <3663F3C3.8AEBC...@maine.rr.com>...
>     Query.Locate('field1', Variant(value1),[])

Re:TQuery.Locate Doesn't work as expected


Russell,

I am ashamed (and so is my colleague)
Completely overlooked that bit of critical information.
Still, reading the answer from Cristoph Roeper one asks himself: Why bother to
make the difference between the two situations.
An Array of 1 value is still an array.
or do we now get in an endless thread of filosophing about 'to be or not to be
something'

Kind regards and thanks for sorting me out
Sjef van der Velde

Quote
"Russell L. Smith" wrote:
> [extracted from help topic for TBDEDataSet.Locate (D4UP2)]

> I know posting info from help is annoying, but the behavior you describe
> seems to be clearly documented in that paragraph.  A variant array should
> only be used when specifying multiple search values.

> >I didn't see any documentation on the last variation

Re:TQuery.Locate Doesn't work as expected


This drove me crazy when I was learning Delphi - the same behavior is
present in TTable.locate.

What really got me is that all the Delphi "Database" manuals and books
devote a maximum of 1 page to the locate method!

Using the book's indexes:

Database Developer's Guide (1 page)

Delphi Database Development (no pages that I can find)

Dephi Developers Guide (1/2 page)

Mastering Delphi 3 (1/2 page).

As  far as I'm concerned, there are NO books that cover database development
in any meaningful way - like enough information to actually write a simple
multi-user application in the real world.

Bless the newsgroups!

Re:TQuery.Locate Doesn't work as expected


I suspect the answer lies in the internal storage of variants.  If you look
at the documentation for the VarType function, note that varArray is its own
type.  For example, a variant containing an integer is type varInteger.  A
variant containing an array is type varArray, even if it only contains a
single integer.

I think that Microsoft "owns" the structure of variants.

V/R
Russell L. Smith

J. van der Velde wrote in message <3664E921.85752...@skzl.nl>...

Quote
>Still, reading the answer from Cristoph Roeper one asks himself: Why bother
to
>make the difference between the two situations.
>An Array of 1 value is still an array.

Re:TQuery.Locate Doesn't work as expected


Quote
> Bless the newsgroups!

Hear Hear

Sjef van der Velde

Re:TQuery.Locate Doesn't work as expected


Quote
>I suspect the answer lies in the internal storage of variants.

It's more likely that the developers were trying to do us a favor by
allowing us to pass a scalar if we were locating on a single field (which is
how locate is probably used 95+ percent of the time).  There's no reason why
they couldn't have required we pass a variant array in either case.  For
that matter, there's no reason why they couldn't have added an extra check
to allow a single field lookup to work regardless of whether the variant was
passed as a scalar or an array.

-- Mark

Re:TQuery.Locate Doesn't work as expected


Hear hear.

Quote
Mark Pauker wrote in message <746m4f$sr...@forums.borland.com>...
>For
>that matter, there's no reason why they couldn't have added an extra check
>to allow a single field lookup to work regardless of whether the variant
was
>passed as a scalar or an array.

Other Threads