Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2008-09

Using TSdfDataset

10 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I am trying to use TSdfDataset, but without success. I get the following crash:

Breakpoint 1, 0x0000f386 in fpc_raiseexception ()
(gdb) bt
#0 0x0000f386 in fpc_raiseexception ()
#1 0x001e0009 in DB_TFIELD_$__GETASVARIANT$$VARIANT () #2 0x0002dd4d in TMAINFORM__CREATE (AOWNER=0x134d010, vmt=0x1, this=0x1363900) at app.pas:204
#3 0x0002b563 in TAPPLICATION__CREATEFORM (INSTANCECLASS=<incomplete type>, REFERENCE=void, this=0x134d010) at application.inc:1749 #4 0x00001da4 in PASCALMAIN () at turbocircuit.dpr:47 #5 0x0001bb15 in SYSTEM_FPC_SYSTEMMAIN$LONGINT$PPCHAR$PPCHAR () #6 0x00001d42 in _start ()
#7 0x00001c69 in start ()

For SQLite I just activate the dataset and everything works. For TSdfDataset it didn't work, so I tryed manually setting the fields in my dataset, but it still doesn't work, and the crash appears in a rather strange place, as the main form has no database code. It's in a units initalization code instead:

constructor TComponentsDatabase.Create;
var
  MyField: TField;
begin
  inherited Create;
  FDataset := TSdfDataset.Create(nil);
  FDataset.FileName := vConfigurations.ComponentsDBFile;
//  FDataset.TableName := STR_DB_COMPONENTS_TABLE;
//  FDataset.PrimaryKey := STR_DB_COMPONENTS_ID;
  MyField := TField.Create(nil);
  MyField.FieldName := 'ID';
  MyField.SetFieldType(ftInteger);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'NAMEEN';
  MyField.SetFieldType(ftString);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'NAMEPT';
  MyField.SetFieldType(ftString);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'HEIGHT';
  MyField.SetFieldType(ftString);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'WIDTH';
  MyField.SetFieldType(ftInteger);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'PINS';
  MyField.SetFieldType(ftInteger);
  FDataset.Fields.Add(MyField);
  MyField := TField.Create(nil);
  MyField.FieldName := 'DRAWINGCODE';
  MyField.SetFieldType(ftMemo);
  FDataset.Fields.Add(MyField);
  FDataset.Active := True;
end;

Any ideas how to get TSdfDataset working?

thanks,

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

Umm, there do is db code there, but it's inside some other routine, which does not show in the backtrace somehow:

procedure TComponentsDatabase.FillStringListWithNames(AStringList: TStrings);
var
  i: Integer;
begin
  AStringList.Clear;
  for i := 1 to FDataset.RecordCount do
  begin
    FDataset.RecNo := i;
    AStringList.Add(FDataset.FieldByName(STR_DB_COMPONENTS_NAMEEN).Value);
  end;
end;

The same code worked fine with sqlite, any ideas?

thanks,

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

Now I got it a bit further. It seams that it doesn't crash if I set FirstLineAsSchema to true, but it also shows wrong value.

Here is my database file:

ID,NAMEEN,NAMEPT,HEIGHT,WIDTH,PINS,DRAWINGCODE
1,resistor,resistor,1,1,1,LINE
2,capacitor,capacitor,1,1,1,LINE

When listing the value of the NAMEEN field it will show: NAMEEN, resistor, resistor (yes, resistor again!)

The correct should be: resistor, capacitor

Any ideas? Every time I work with databases it's really frustrating =/

constructor TComponentsDatabase.Create;
begin
  inherited Create;
  FDataset := TSdfDataset.Create(nil);
  FDataset.FileName := vConfigurations.ComponentsDBFile;
//  FDataset.TableName := STR_DB_COMPONENTS_TABLE;
//  FDataset.PrimaryKey := STR_DB_COMPONENTS_ID;
  // Adds field definitions
{  FDataset.FieldDefs.Add('ID', ftString);
  FDataset.FieldDefs.Add('NAMEEN', ftString);
  FDataset.FieldDefs.Add('NAMEPT', ftString);
  FDataset.FieldDefs.Add('HEIGHT', ftString);
  FDataset.FieldDefs.Add('WIDTH', ftString);
  FDataset.FieldDefs.Add('PINS', ftString);
  FDataset.FieldDefs.Add('DRAWINGCODE', ftString);}
  FDataset.Delimiter := ',';
  FDataset.FirstLineAsSchema := True;
  FDataset.Active := True;
end;
destructor TComponentsDatabase.Destroy;
begin
  FDataset.Free;
  inherited Destroy;
end;
procedure TComponentsDatabase.FillStringListWithNames(AStringList: TStrings);
var
  i: Integer;
  CurField: TField;
begin
  AStringList.Clear;
  for i := 1 to FDataset.RecordCount do
  begin
    FDataset.RecNo := i;
    CurField := FDataset.FieldByName(STR_DB_COMPONENTS_NAMEEN);
    AStringList.Add(CurField.Value);
  end;
end;
Howard Page-Clark
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 26 lines
Here is my database file: ID,NAMEEN,NAMEPT,HEIGHT,WIDTH,PINS,DRAWINGCODE 1,resistor,resistor,1,1,1,LINE 2,capacitor,capacitor,1,1,1,LINE When listing the value of the NAMEEN field it will show: NAMEEN, resistor, resistor (yes, resistor again!) The correct should be: resistor, capacitor procedure TComponentsDatabase.FillStringListWithNames(AStringList: TStrings); var i: Integer; CurField: TField; begin AStringList.Clear; for i := 1 to FDataset.RecordCount do begin FDataset.RecNo := i; CurField := FDataset.FieldByName(STR_DB_COMPONENTS_NAMEEN); AStringList.Add(CurField.Value); end; end;

Try this:

procedure TComponentsDatabase.FillStringListWithNames(AStringList:
TStrings);
var
  i : Integer;
  CurField: TField;
begin
  AStringList.Clear;
  CurField := FDataset.FieldByName(STR_DB_COMPONENTS_NAMEEN);
  FDataset.First;
  while not FDataset.EOF do
   begin
    AStringList.Add(CurField.Value);
    FDataset.CursorPosChanged;
    FDataset.Next;
   end;
end;

Yours

Howard

Felipe Monteiro de Carvalho
to Howard Page-Clark

Thanks! It works!

But I am confused as to why the previous code didn't work, specially considering that it worked perfectly with the sqlite dataset.

I assume that RecNo does not work with the Sdf dataset.

Felipe Monteiro de Carvalho
Michael Van Canneyt
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 6 lines
Thanks! It works! But I am confused as to why the previous code didn't work, specially considering that it worked perfectly with the sqlite dataset. I assume that RecNo does not work with the Sdf dataset.

RecNo or MoveTo is never guaranteed to work. The only guaranteed navigation methods are Prior, Next First and last, and normally Bookmark.

And even so, on unidirectional datasets, only next and last may work.

Michael.

Graeme Geldenhuys
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote

Hi Felipe,

I've never heard or seen TSdfDataset or TFixedDataset - other than from your recent postings. From the wiki page, it looks like the data is stored in a simple CSV file. So does the TxxxDataset class simply act as a wrapper to the CSV file? Is that correct?

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Felipe Monteiro de Carvalho
to Graeme Geldenhuys
Graeme Geldenhuys wrote
I've never heard or seen TSdfDataset or TFixedDataset - other than from your recent postings. From the wiki page, it looks like the data is stored in a simple CSV file. So does the TxxxDataset class simply act as a wrapper to the CSV file? Is that correct?

For TSdfDataset you can choose the separator, so it's not necessarely a comma, but yes, if using commas it will be a CSV file, with the addition of having the names of the fields in the first row.

For TFixedDataset I added an example in the wiki. It's a completely different format.

Felipe Monteiro de Carvalho