0

I would like to dynamically load and display into a TVirtualStringTree, data from some different SQL tables. This mean that the header and the content of each column will contain each time different type of data.

My problem is how to optimize in regards of memory usage, the definition of the record and the pointer for this case.

My thinking was to do it like this:

type
  TDataType = (dtUnknown, dtString, dtInteger, dtText, dtFloat, dtDateTime, dtDate, dtTime, dtBoolean);

  TData = record
    DataType: TDataType;
    AsString: String;
    AsInteger: Integer;
    AsText: TStrings;
    AsWord: Word;
    AsDateTime: TDateTime;
    AsDate: TDate;
    AsTime: TTime;
    AsBoolean: Boolean;
  end;
  TTreeData = array of TData;

  PTreeData= ^TTreeData;

In practice only 2 fields from the record will contained data: DataType (all the time) and a second field, depends by the DataType defined (e.g AsString, AsInteger). Will be also the others fields allocated as memory when Node will be initialized? Also I don't like the fact the DataType is allocated to each node. There must be a simple way to optimize this record.

Please some suggestions.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
REALSOFO
  • 852
  • 9
  • 37
  • I'm pretty sure there's a data-aware descendant of that component already. Have you looked for that yet? It might prove more effective than attempting to reinvent that feature yourself. – Rob Kennedy Apr 16 '16 at 20:14
  • Here's a data-aware version of VTV: https://github.com/TurboPack/VirtualTreeView – Johan Apr 16 '16 at 20:32
  • Is it data-aware? I can see only usual TVirtualStringTree/TVirtualDrawTree here, no new components and no new properties. – Andrew Apr 17 '16 at 05:48
  • there was someone's contribution long ago - but it was never maintained for what I remember – Arioch 'The Apr 18 '16 at 16:30
  • you may use TValue datatype - http://docwiki.embarcadero.com/Libraries/XE2/en/System.Rtti.TValue (there are also a number of optimized 3rd party implementation of it, like `TOmniValue`) . Also for older Delphi you may use `Variant` datatype http://docwiki.embarcadero.com/RADStudio/Seattle/en/Variant_Types – Arioch 'The Apr 18 '16 at 16:33
  • For the moment, I will just use `String`. All others can be converted from `String` data type. – REALSOFO Apr 19 '16 at 04:19

1 Answers1

0

When I need to do something like this I use a case statement in the TData record.

Something like

type
   TData = record
      case DataType: TDataType of
       dtUnknown:
         (AsUnknown: ???);
       dtString:
         (AsString: string);  // this is incorrect, string (and some others are not allowed)
       dtInteger:
         (AsInteger: Integer);

       ... and so on

         end;
      end;

http://docwiki.embarcadero.com/RADStudio/Seattle/en/Structured_Types#Variant_Parts_in_Records

Have a look at TVarRec. Delphi uses open arrays TVarRec when implementing 'array of const' variables ans in the Format statement.

You probably only need two columns in the VirtualStringTree. One for the type and other for the value (represented as a string)

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
Graeme
  • 9
  • 1
  • @Arioch Your edit, adding `DataType: TDataType` as a separate field before the variant part is incorrect. It is not needed and certainly can not be the same as *`tag: ordinalType`* part. I'll remove it. – Tom Brunberg May 16 '16 at 17:17
  • @Greme Regarding the data types in variant parts of records: *The types must not be long strings, dynamic arrays, variants (that is, Variant types), or interfaces, nor can they be structured types that contain long strings, dynamic arrays, variants, or interfaces; but they can be pointers to these types.* Ref. the docs. IOW, `AsString: string` is not valid. – Tom Brunberg May 16 '16 at 17:23
  • @TomBrunberg if you remove the variable `Datatype` then you don't have it and better not use it in the `case`, to keep code clean `case TDataType of...`. But mnore importantly, the topicstarter's structure is "tagged record" - like DFM or EMBL records it starts with the type marker, and the tail is type-dependent. You structure is "random record", it has no type marker. When the topicstarter would parse his data stream, he would read the `TDataType` tag and then branch for the rest of the record. When you would parse you would have to call `random(High(TDatatype)` instead to parse the stream. – Arioch 'The May 16 '16 at 17:27
  • 1
    @Arioch'The From the docs: *The tag, if there is one, functions as an extra field (of type ordinalType) in the non-variant part of the record.* That is why your addition of the same field created an error. Specifically, once more note that the `tag` variable is optional and often omitted, but if it exists as it did already before your edit, it serves the same purpose as your addition. So there is no "random record" the DataType field exists and tells what type the record represents. – Tom Brunberg May 16 '16 at 17:58