首页  编辑  

内存临时表

Tags: /超级猛料/Database.数据库相关/安装、杂项和其他/   Date Created:

建立一个虚拟表(内存表)!!!!

警告: 使用内存表可能导致数据丢失!作者不承担使用下面的代码而造成的任何损失的任何责任!

{

This is an InMemoryTable example. Free for anyone to use, modify and do

whatever else you wish.

Just like all things free it comes with no guarantees. I cannot be responsible

for any damage this code may cause. Let me repeat this:

WARNING! THIS CODE IS PROVIDED AS IS WITH NO GUARANTEES OF ANY KIND!

USE THIS AT YOUR OWN RISK - YOU ARE THE ONLY PERSON RESPONSIBLE FOR

ANY DAMAGE THIS CODE MAY CAUSE - YOU HAVE BEEN WARNED!

THANKS to Steve Garland <72700.2407@compuserve.com> for his help. He

created his own variation of an in-memory table component and I used it

to get started.

InMemory tables are a feature of the Borland Database Engine (BDE).

InMemory tables are created in RAM and deleted when you close them. They

are much faster and are very useful when you need fast operations on small

tables. This example uses the DbiCreateInMemoryTable DBE function call.

This object should work just like a regular table, except InMemory tables

do not support certain features (like referntial integrity, secondary

indexes and BLOBs) and currently this code doesn't do anything to

prevent you from trying to use them. You will probably get some error if

you try to create a memo field.

If you have comments - please contact me at INTERNET:grisha@mira.com

Happy hacking!

Gregory Trubetskoy

http://www.mira.com/home/grisha

}

unit Inmem;

interface

uses DBTables, WinTypes, WinProcs, DBITypes, DBIProcs, DB, SysUtils;

type TInMemoryTable = class(TTable)

 private

   hCursor: hDBICur;

   procedure EncodeFieldDesc(var FieldDesc: FLDDesc;

     const Name: string; DataType: TFieldType; Size: Word);

   function CreateHandle: HDBICur; override;

 public

   procedure CreateTable;

 end;

implementation

{ luckely this function is virtual - so I could override it. In the original

 VCL code for TTable this function actually opens the table - but since

 we already have the handle to the table - we just return it }

function TInMemoryTable.CreateHandle;

begin

 Result := hCursor;

end;

{ This function is cut-and-pasted from the VCL source code. I had to do this

 because it is declared private in the TTable component so I had no access

 to it from here. }

procedure TInMemoryTable.EncodeFieldDesc(var FieldDesc: FLDDesc;

 const Name: string; DataType: TFieldType; Size: Word);

const

 TypeMap: array[TFieldType] of Byte = (

   fldUNKNOWN, fldZSTRING, fldINT16, fldINT32, fldUINT16, fldBOOL,

   fldFLOAT, fldFLOAT, fldBCD, fldDATE, fldTIME, fldTIMESTAMP, fldBYTES,

   fldVARBYTES, fldBLOB, fldBLOB, fldBLOB);

begin

 with FieldDesc do

 begin

   AnsiToNative(Locale, Name, szName, SizeOf(szName) - 1);

   iFldType := TypeMap[DataType];

   case DataType of

     ftString, ftBytes, ftVarBytes, ftBlob, ftMemo, ftGraphic:

       iUnits1 := Size;

     ftBCD:

       begin

         iUnits1 := 32;

         iUnits2 := Size;

       end;

   end;

   case DataType of

     ftCurrency:

       iSubType := fldstMONEY;

     ftBlob:

       iSubType := fldstBINARY;

     ftMemo:

       iSubType := fldstMEMO;

     ftGraphic:

       iSubType := fldstGRAPHIC;

   end;

 end;

end;

{ This is where all the fun happens. I copied this function from the VCL source

 and then changed it to use DbiCreateInMemoryTable instead of DbiCreateTable.

 Since InMemory tables do not support Indexes - I took all of the index-related

 things out }

procedure TInMemoryTable.CreateTable;

var

 I: Integer;

 pFieldDesc: pFLDDesc;

 szTblName: DBITBLNAME;

 iFields: Word;

 Dogs: pfldDesc;

begin

 CheckInactive;

 if FieldDefs.Count = 0 then

   for I := 0 to FieldCount - 1 do

     with Fields[I] do

       if not Calculated then

         FieldDefs.Add(FieldName, DataType, Size, Required);

 pFieldDesc := nil;

 SetDBFlag(dbfTable, True);

 try

   AnsiToNative(Locale, TableName, szTblName, SizeOf(szTblName) - 1);

   iFields := FieldDefs.Count;

   pFieldDesc := AllocMem(iFields * SizeOf(FLDDesc));

   for I := 0 to FieldDefs.Count - 1 do

     with FieldDefs[I] do

     begin

       EncodeFieldDesc(PFieldDescList(pFieldDesc)^[I], Name,

         DataType, Size);

     end;

     { the driver type is nil = logical fields }

     Check(DbiTranslateRecordStructure(nil, iFields, pFieldDesc,

       nil, nil, pFieldDesc));

     { here we go - this is where hCursor gets its value }

   Check(DbiCreateInMemTable(DBHandle, szTblName, iFields, pFieldDesc, hCursor));

 finally

   if pFieldDesc <> nil then FreeMem(pFieldDesc, iFields * SizeOf(FLDDesc));

   SetDBFlag(dbfTable, False);

 end;

end;

end.