Recent

Author Topic: How to create fields programatically?  (Read 3530 times)

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
How to create fields programatically?
« on: September 01, 2012, 07:58:15 pm »
I wanted to try something from a previous post here, but I chose to do it in a simple command line program and I've faced a problem I don't have in a Lazarus-managed GUI programs. I have to create all objects manually, but I've find out I have no idea how to create a TField instance!

I've tried this according to the FCL documentation:
Code: [Select]
DataSet.Fields.Add(Field);
Also this, simply using the constructor, as usual:
Code: [Select]
Field := TField.Create(nil);
Whatever I did, either I got an access violation (SIGSEGV on Linux) or if I did not and then tried using the field in the dataset's Fields[n] property, I got an "index out of bounds" error even with the index being zero.

I've checke the documentation, FCL docs do have TFields documented, but it is very brief and nothing of it works in this example. The only information I found on the wiki, in the documentation about databases, is a redlink with a promise there will be explained how to programatically create fields, but so far nobody has written it.

So to recap once again, nothing that works in a GUI Lazarus app works here, and also I couldn't do it properly in the way objecs are usally managed.  So, obviously there is another step required, or is something done differently . Could somebody explain how is it done? Then perhaps we could finally complete the above mentioned wiki documentation :)

EDIT: The dataset used was TMemDataset, so it is possible it affects the required steps...
« Last Edit: September 01, 2012, 11:33:25 pm by TurboRascal »
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: How to create fields programatically?
« Reply #1 on: September 02, 2012, 01:39:17 am »
Code: [Select]
  MemDataset1.FieldDefs.Add('FirstName',ftstring, 40);
  MemDataset1.FieldDefs.Add('LastName',ftstring, 60);
  MemDataset1.FieldDefs.Add('HomePhone',ftstring, 20);
  MemDataset1.CreateTable;

In short you create field definitions and the fields are created for you when the dataset is activated or created.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: How to create fields programatically?
« Reply #2 on: September 03, 2012, 01:51:09 pm »
Code: [Select]
  MemDataset1.FieldDefs.Add('FirstName',ftstring, 40);
  MemDataset1.FieldDefs.Add('LastName',ftstring, 60);
  MemDataset1.FieldDefs.Add('HomePhone',ftstring, 20);
  MemDataset1.CreateTable;

In short you create field definitions and the fields are created for you when the dataset is activated or created.

Thank you, this works fine without using TField. Obviously the FieldDefs does that which was previously automatically done for me. I do get an error, but perhaps it's a bug in my svn snapshot. I'll check with a fresh one and then with 1.0 if it fails, to make sure what the problem is.

I'm still not sure how to properly initialize and use TField from scratch though... Any hints?
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: How to create fields programatically?
« Reply #3 on: September 03, 2012, 02:09:54 pm »
The following is the CreateField as found in the TFieldDef class (removed the debug staff for clarity)
Quote
Code: [Select]
Function TFieldDef.CreateField(AOwner: TComponent): TField;

Var TheField : TFieldClass;

begin
  TheField:=GetFieldClass;
  if TheField=Nil then
    DatabaseErrorFmt(SUnknownFieldType,[FName]);
  Result:=Thefield.Create(AOwner);
  Try
    Result.Size:=FSize;
    Result.Required:=FRequired;
    Result.FFieldName:=FName;
    Result.FDisplayLabel:=DisplayName;
    Result.FFieldNo:=Self.FieldNo;
    Result.SetFieldType(DataType);
    Result.FReadOnly:= (faReadOnly in Attributes);
    Result.Dataset:=TFieldDefs(Collection).Dataset;
    If (Result is TFloatField) then
      TFloatField(Result).Precision:=FPrecision;
    if (Result is TBCDField) then
      TBCDField(Result).Precision:=FPrecision;
    if (Result is TFmtBCDField) then
      TFmtBCDField(Result).Precision:=FPrecision;
  except
    Result.Free;
    Raise;
  end;

end;

As far as I can see you need to set all field's properties especially fieldname, size etc before you set the field's dataset and add it to the dataset's fields collection before the dataset is opened/activated.

Regards
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: How to create fields programatically?
« Reply #4 on: September 03, 2012, 05:12:32 pm »
Great, thanks! I'll add this to the wiki to resolve the red link ;)
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

 

TinyPortal © 2005-2018