Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (2)


Create You Own Custom Dataset!...Component available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Create you own Custom DataSet!
Product:
Delphi 5.x (or higher)
Category:
Database-VCL
Skill Level:
Scoring:
Last Update:
10/29/2002
Search Keys:
delphi delphi3000 article borland vcl code-snippet DATA SET DATA-SET hybridgraf tutorial custom
Times Scored:
4
Visits:
10358
Uploader: William Anthony Amaral B
Company: HybridGRAF Interactive
Reference: N/A
Component Download: http://www.taxisairport.com/dhype/downloads/cds1.rar
 
Question/Problem/Abstract:
How to create a custom DataSet
Answer:



Create you own Custom DataSet!
by William Anthony

Have you ever needed/wanted to create your own personal Database, well this is the place for you!
[HybridSPOT] is proud to present a multi-part series on just that, starting with the TDataSet Component
we will create a new and powerful OPEN-SOURCE Database Engine.

This tutorial will teach you about the basics of Developing a TDataSet,
and trust me it isn't such a simple task. -_-

the TDataSet Structure
The Naked Truth


TNAKEDDataSet = class(TDataSet)
protected
function AllocRecordBuffer: PChar; override;
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
function GetCanModify: Boolean; override;
function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
function IsCursorOpen: Boolean; override;

{ THESE THREE WE CAN LEAVE OUT }
function GetRecNo: Integer; override;
function GetRecordCount: Integer; override;
function GetRecordSize: Word; override;

procedure FreeRecordBuffer(var Buffer: PChar); override;
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
procedure InternalClose; override;
procedure InternalFirst; override;
procedure InternalGotoBookmark(Bookmark: Pointer); override;
procedure InternalHandleException; override;
procedure InternalInitFieldDefs; override;
procedure InternalInitRecord(Buffer: PChar); override;
procedure InternalLast; override;
procedure InternalOpen; override;
procedure InternalPost; override;
procedure InternalSetToRecord(Buffer: PChar); override;
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
procedure SetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean); override;

public
property BufferCount;
property Buffers;
property Fields;
property FieldValues;

function GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; override;
published
property Active;
property AfterCancel;
property AfterClose;
property AfterDelete;
property AfterEdit;
property AfterInsert;
property AfterOpen;
property AfterPost;
property AfterRefresh;
property AfterScroll;
property BeforeCancel;
property BeforeClose;
property BeforeDelete;
property BeforeEdit;
property BeforeInsert;
property BeforeOpen;
property BeforePost;
property BeforeRefresh;
property BeforeScroll;
property CanModify;
property FieldDefs;
property Filter;
property FilterOptions;
property ObjectView default False;
property OnCalcFields;
property OnDeleteError;
property OnEditError;
property OnNewRecord;
property OnPostError;
property RecNo;
property RecordCount;
property RecordSize;
property State;
end;

Well it looks a bit BULKY but that's what it needs in the REAL WORLD

the Abstract Functions
In earlier versions of Delphi this class had LOTS of abstract procedures, now it contains but a few:

InternalOpen
Type Abstract
Use Generate Fields
Bind Fields
Open the Source of Data (File - Memory - Other)

InternalClose
Type Abstract
Use Un-Bind Fields
Close the Source of Data (File - Memory - Other)

IsCursorOpen
Type Abstract Function  
Use Return DataSet Active Status (is dataset open)

InternalHandleException
Type Abstract
Use Respond to any exception that is generated

GetRecord
Type Abstract Function  
Use Get record data,
There record position has to be updated within the procedure VIA the GETMODE param. the resulting value must be updated aswell, for example if the file goes off the EOF or BOF.


the BookMark System
You might be asking yourself as i once did: "WELL I DONT NEED BOOKMARKS FOR THIS SIMPLE DATASET!"


Well guess what YOU DO.It seems that the Bookmark is not really a Bookmark more of a ID for each one of the Temporary Buffer. in standard it keeps about 3 records in memory

Prior - Current - Next.
Each containing there WHERE and WHO:

WHERE is the BookmarkFlag (Prior, Current, Next) for orientation
WHO is the BookmarkData (Record No) for ID and Placement.

So in turn we must make a record for this data, beeing that it is fixed width we can place it infront of the main data, but in the case of this sample i fused them both together.

the BookMark procedures
SetBookmarkData
Type Procedure
Use Set RecordNo to Active Buffer
No thinker ^_^

SetBookmarkFlag
Type Procedure
Use Set BookmarkFlag to Active Buffer
No thinker ^_^ aswell

GetBookmarkData
Type Procedure
Use Get RecordNo from Active Buffer
No thinker ^_^ x 3

GetBookmarkFlag
Type Function
Use Get BookmarkFlag from Active Buffer
No thinker ^_^ exp 4

InternalSetToRecord
Type Procedure
Use Get RecordNo from Active Buffer and set it as current record
No thinker o_O

InternalGotoBookmark
Type Procedure
Use Get RecordNo from DATA and set it as current record
No thinker O_o EASY AS "3.1415..." (Pi)


the Navegation  
Now that we see that the last part isn't that hard we move to the navegation,
if you have used a DataSet before this shuld be easy.

InternalFirst
Type Procedure
Use We set our Current Position to -1 (in some cases) BOF
No thinker ^_^

InternalLast
Type Procedure
Use We set our Current Position to RecordCount (in some cases) EOF
No thinker ^_^



the BUFFERS of Terror
Now we come to the next level of the DataSet "the Buffer System"


AllocRecordBuffer
Type Function
Use Return the new memory allocation for the buffer
result := getMemory(MYRECORDSIZEWITHBOOKMARKINFO);
No thinker ^_^

FreeRecordBuffer
Type Procedure
Use HERE IS THE CODE "FreeMem(Buffer);"
No thinker ^_^ x 1000



Well that wasnt that bad was it?
the Data Processing  

Ahh yes we are getting more work to do!

InternalPost
Type Procedure
Use Post changes if any,
We must check if the State is Edit or Insert, since this will have an effect on our process, if the state is set to Edit this meens that we must write our changes on the current record no questions asked, else we must go to the end and add a new record, then we write.
NOT EVEN A MICRO-Thinker o_O

InternalAddRecord
Type Procedure
Use Add current buffered record to file, same as the last but this time we just add it no questions asked.

NOT EVEN A MICRO-Thinker O_O x 2


the Field System
Yes the work is yet to come!

SetFieldData
Type Procedure
Use Convert and Pass the data from the Active Buffer to the Field Buffer
the param contains the FieldClass and the Field Buffer.
the active buffer is given by the ActiveBuffer function.
Semi-Thinker ^_^ depends on the Table Format

GetFieldData
Type Function
Use Convert and Pass the data from the Field Buffer to the Active Buffer
the param contains the FieldClass and the Field Buffer.
the active buffer is given by the ActiveBuffer function.

Result Value is boolean, it the data was passed OK then it returns TRUE

Semi-Thinker ^_^ depends on the Table Format again


the Usefull yet Not Needed
I still use them do, even if they to make a mess if not used properly


GetRecNo
Type Function
Use Return the current Record No

GetRecordCount
Type Function
Use Return the Record Count

GetRecordSize
Type Function
Use Return the Record Size w/o Bookmark Info

SetRecNo
Type Procedure
Use Set the current Record No



These procedures are used by some controls like TDBGrid and such.
the Holy-Grail
It is time to learn!

All these procedures have been detailed for you to figure out, the code is WAY SIMPLE and WELL COMMENTATED so you shuldnt be lost for long.

This is a sample of a TINY User Database complete with:

User Name 20 Characters
Password 10 Characters
AccessLevel 4 Bytes [Integer]

now in two days we will learn to make a DBF file reader! yes you wont have to use that bulky DBE anymore! and you will learn how different file formats work O_o

Download NOW



I hope this tutorial (instruction manual) has gotten some of you to try and build your skill up,
remember that some if not all of knowledge comes from practice, so... repeat and repeat, make your own DataSet's until you get it working just fine!

-William Anthony
HybridGRAF Interactive Solutions






Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
dowload error...
    denis belsky (Aug 10 2006 2:03PM)

when trying to dowload
Component Download: http://www.taxisairport.com/dhype/downloads/cds1.rar
rise error: 404 Not Found error was encountered
Thanks!
Respond

TDataSet BookMark System
    Alecu Mihai Cantacuzino (Mar 17 2003 11:52AM)

The TDataSet and the other objetcs who use it need to knows: where they are, where thay may go, and what's happening with the record data.

So a minimal record information structure should be something like:  
  PRecInfo = ^TRecInfo;
  TRecInfo = record
    Bookmark: Integer;
    BookmarkFlag: TBookmarkFlag;
    UpdateStatus: TUpdateStatus;
  end;
where :
     - Bookmark an integer type field who must indicate the RecordNumber. This field should also be the result of several functions like GetRecNo, GetBookmarkData or GetBookmark.
     - BookmarkFlag a TBookmarkFlag type indicates the state of the record navigations. This tells when the record list have been over or underrunned. This also tells when the flagged record is a new one or not. My researches have shown that this flag is fully used by Insert or Append methods and should be use by the custom implementation of the InternalPost method.
     - UpdateStaus reports the last type of modification operated on the record. This field is reported by the UpdateSatus method and is useful in further implementations of the OnUpdateRecord event.

Those structures might be complicated and the AllocBuffer and FreeBuffer method must manage their allocations.

Borland Example:

TDBEDataSet Record information Structure (dbtables.pas)

  PRecInfo = ^TRecInfo;
  TRecInfo = packed record
    RecordNumber: Longint;
    UpdateStatus: TUpdateStatus;
    BookmarkFlag: TBookmarkFlag;
  end;

My Example:

  PRecInfo = ^TRecInfo;
  TRecInfo = record
    Bookmark,
    RelatedBookmark: Integer;  //Saved original Record bookmark pointing to a special purpose list
    BookmarkFlag: TBookmarkFlag;
    RowTimeStamp: TTimeStamp; //"Borning date"
    UpdateStatus: TUpdateStatus;
    CalcRecords:TList;  // A list where i store data for fkLookup and fkCalulated type fields. I use a list because my record list is shared to several TDataSets.
  end;

Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
D. Wischnewski
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)