AnyDAC
ContentsIndexHome
PreviousUpNext
Sorting, Searching, Locating, Filtering Questions

The list of questions and answers related to sorting, searching, locating, filtering datasets.

Group
Links
QS1: Dataset sorts non-English strings incorrectly. Or - I am getting "[AnyDAC][DatS]-2. Object [] is not found". What is wrong ?

A: To fix the issue, do the following:

  • open AnyDAC\Source\uAD.inc;
  • find the lines:

 

{$define AnyDAC_NOLOCALE_DATA}   // define, to use binary data comparision
{$define AnyDAC_NOLOCALE_META}   // define, to use binary metadata comparison

 

  • comment them out;
  • save the file and recompile your application.

Note: if you are only working with English (ASCII) texts, then ensure that the above lines are uncommented. That speedups sort and locate operations considerably. 

 

QS2: Is it necessary to create Index for ordering data?

A: You does not need to define Indexes, if you just need to order data. IndexFieldNames will work for you. Indexes allows to define the views, which are mix or filtering and ordering. Note, Indexes and IndexDefs are mutually exclusive for all AnyDAC datasets. That means - either you should fill Indexes or IndexDefs, but not both. 

 

QS3: Can lookup fields be used in index definitions?

A: No, you cannot. But you can use in indexes internal calculated fields. For that add persistent fields, then add fkInternalCalc field, create OnCalcFields event handlers and calculate this field in event handler. For example: 

 

procedure TForm21.ADTable1CalcFields(DataSet: TDataSet);
begin
  DataSet.FieldByName('f_calc').AsString :=
    ADMemTable2.Lookup('code',
      DataSet.FieldByName('f_code').AsInteger, 'name');
end;

 

QS4: Can calculated fields be used in index definitions ?

A: Current AnyDAC release does not support fields with FieldKind = fkCalculated in Locate, Lookup, IndexFieldNames, etc. The workaround is to use fkInternalCalc fields. 

 

QS5: When I call the FindNearest method at runtime I'm receiving an error message stating that there is no active index.

A: The index must be selected, not just active. For that: 

- set Indexes[i].Selected := True 

- or set ADTable1.IndexFieldName := <name of your index> 

 

QS6: Ho to define different character collation for TADDataset indexing ?

A: In general there are 3 options:

  • To assign LCID to TADMemTable.Table.Locale. AnyDAC uses CompareStringA and CompareStringW with SORT_STRINGSORT flag. The default collation is DBMS independent. It is LOCALE_USER_DEFAULT. See Win API docu for details.
  • To change source code - uADDatSManager, TADDatSRow.CompareData and implement your own comparision algorythm.
  • Register custom function with expression evaluator. See uADStanExpr for registration details. Then you can use this function at TADMemTable.Indexes[..].Expression. For example: Expression := 'MySort(Name)'.

In future we will implement custom collations. That will be usefull as for SQLite driver as for cases, like yours. 

 

QS7: How to order data in such way: COL1 descending, COL2 ascending ?

A: IndexFieldNames := 'col_1:D;col_2'; 

Also, check help file, chapter "TADDataSet.IndexFieldNames property". 

 

QS8: ADQuery.Locate raises "Function sequence error" with SQL Server. What is wrong ?

A: It looks like ADQuery was opened after an explicit transaction start, then a transaction was commited. And then you are calling ADQuery.Locate. But not yet all records were fetched from ADQuery, but Locate imlicitly calls FetchAll. And it gives this error on SQL Server. 

To avoid it do:

  • set ADQuery.FetchOption.Mode = fmAll for this specific ADQuery
  • call FetchAll for this ADQuery before calling Commit.

This is SQL Server behaviour - invalidate open cursors after Commit / Rollback. 

 

QS9: What is the best way to implement Lookup tables ? Lookup tables seems to be big cause to why opening/loading is slow.

A: If you does not need all records on the client, then use TADQuery with SELECT ... WHERE .... 

 

QS10: If you have any tips on how to handle lookup fields to get best performance?

A: Then set TADQuery.IndexFieldNames to LookupKeyFields, then AnyDAC will use client index to locate record in a lookup dataset. 

If the number of unique key values in not high, then set LookupCache to True. 

 

QS11: I am failing to filter by the DateTime value. What is wrong ?

Q: I am using Delphi 2007 with AnyDac 2.0.11.895 on a Postgres database. When I try to filter on a DateTime field I can't seem to get an exact match with a value passed to it like this: 

 

created_date = '8/10/2009 14:42:14'           // or even...
created_date = '8/10/2009 14:42:14.247'     // ... the exact time with milisec

 

Instead I have to end up using something like this: 

 

created_date >= '8/10/2009 14:42:14' AND created_date < '8/10/2009 14:42:15' or
created_date >= '8/10/2009 14:42:14.000' AND created_date <= '8/10/2009 14:42:14.999'

 

But isn't pretty code. 

 

A: The problem is that DBMS or DBMS API may round the time value. While a programmer expects to see the .247 as a fractional part, it may be .246 or how else. That is not AnyDAC failure, but it is how a DBMS is working. 

 

You can round the time value to the seconds and compare that value with a constant without a fractional part: 

 

uses
  uADStanExprFuncs
...
  ADQuery1.Filter = 'TimeStampDiff(''second'', created_date,
    convert(''timestamp'', ''8/10/2009 14:42:14'')) = 0';
What do you think about this topic? Send feedback!