<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=41001&amp;view=findpost&amp;p=266013</guid>
        <pubDate>Thu, 18 Dec 2003 14:57:25 +0000</pubDate>
        <title>Эмуляция таблицы БД в памяти</title>
        <link>https://forum.sources.ru/index.php?showtopic=41001&amp;view=findpost&amp;p=266013</link>
        <description><![CDATA[Vit:  <b>Решение 1. Стандартная таблица TTable (BDE). </b><br><br><!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b></b> </td></tr><tr><td id='CODE'><!--ec1-->{ &nbsp;<br>&nbsp; This is an InMemoryTable example. Free for anyone to use, modify and do &nbsp;<br>&nbsp; whatever else you wish. &nbsp;<br><br>&nbsp; Just like all things free it comes with no guarantees. &nbsp;<br>&nbsp; I cannot be responsible for any damage this code may cause. &nbsp;<br>&nbsp; Let me repeat this&#58; &nbsp;<br><br>&nbsp; &nbsp;WARNING&#33; THIS CODE IS PROVIDED AS IS WITH NO GUARANTEES OF ANY KIND&#33; &nbsp;<br>&nbsp; &nbsp;USE THIS AT YOUR OWN RISK - YOU ARE THE ONLY PERSON RESPONSIBLE FOR &nbsp;<br>&nbsp; &nbsp;ANY DAMAGE THIS CODE MAY CAUSE - YOU HAVE BEEN WARNED&#33; &nbsp;<br><br>&nbsp; THANKS to Steve Garland &#60;72700.2407@compuserve.com&#62; for his help. &nbsp;<br>&nbsp; He created his own variation of an in-memory table component and &nbsp;<br>&nbsp; I used it to get started. &nbsp;<br><br>&nbsp; InMemory tables are a feature of the Borland Database Engine &#40;BDE&#41;. &nbsp;<br>&nbsp; InMemory tables are created in RAM and deleted when you close them. &nbsp;<br>&nbsp; They are much faster and are very useful when you need fast operations on &nbsp;<br>&nbsp; small tables. This example uses the DbiCreateInMemoryTable DBE function call. &nbsp;<br><br>&nbsp; This object should work just like a regular table, except InMemory &nbsp;<br>&nbsp; tables do not support certain features &#40;like referntial integrity, &nbsp;<br>&nbsp; secondary indexes and BLOBs&#41; and currently this code doesn&#39;t do anything to &nbsp;<br>&nbsp; prevent you from trying to use them. You will probably get some error if &nbsp;<br>&nbsp; you try to create a memo field. &nbsp;<br>} &nbsp;<br><br>unit Inmem; &nbsp;<br><br>interface &nbsp;<br><br>uses DBTables, WinTypes, WinProcs, DBITypes, DBIProcs, DB, SysUtils; &nbsp;<br><br>type &nbsp;<br>&nbsp; TInMemoryTable = class&#40;TTable&#41; &nbsp;<br>&nbsp; private &nbsp;<br>&nbsp; &nbsp; hCursor&#58; hDBICur; &nbsp;<br>&nbsp; &nbsp; procedure EncodeFieldDesc&#40;var FieldDesc&#58; FLDDesc; &nbsp;<br>&nbsp; &nbsp; &nbsp; const Name&#58; string; DataType&#58; TFieldType; Size&#58; Word&#41;; &nbsp;<br>&nbsp; &nbsp; function CreateHandle&#58; HDBICur; override; &nbsp;<br>&nbsp; public &nbsp;<br>&nbsp; &nbsp; procedure CreateTable; &nbsp;<br>&nbsp; end; &nbsp;<br><br>implementation &nbsp;<br><br>{ &nbsp;<br>&nbsp; Luckely this function is virtual - so I could override it. In the &nbsp;<br>&nbsp; original VCL code for TTable this function actually opens the table - &nbsp;<br>&nbsp; but since we already have the handle to the table - we just return it &nbsp;<br>} &nbsp;<br><br>function TInMemoryTable.CreateHandle; &nbsp;<br>begin &nbsp;<br>&nbsp; Result &#58;= hCursor; &nbsp;<br>end; &nbsp;<br><br>{ &nbsp;<br>&nbsp; This function is cut-and-pasted from the VCL source code. I had to do &nbsp;<br>&nbsp; this because it is declared private in the TTable component so I had no &nbsp;<br>&nbsp; access to it from here. &nbsp;<br>} &nbsp;<br><br>procedure TInMemoryTable.EncodeFieldDesc&#40;var FieldDesc&#58; FLDDesc; &nbsp;<br>&nbsp; const Name&#58; string; DataType&#58; TFieldType; Size&#58; Word&#41;; &nbsp;<br>const &nbsp;<br>&nbsp; TypeMap&#58; array&#91;TFieldType&#93; of Byte = &#40;fldUNKNOWN, fldZSTRING, fldINT16, &nbsp;<br>&nbsp; &nbsp; fldINT32, fldUINT16, fldBOOL, &nbsp;<br>&nbsp; &nbsp; fldFLOAT, fldFLOAT, fldBCD, fldDATE, fldTIME, fldTIMESTAMP, fldBYTES, &nbsp;<br>&nbsp; &nbsp; fldVARBYTES, fldBLOB, fldBLOB, fldBLOB&#41;; &nbsp;<br>begin &nbsp;<br>&nbsp; with FieldDesc do &nbsp;<br>&nbsp; begin &nbsp;<br>&nbsp; &nbsp; AnsiToNative&#40;Locale, Name, szName, SizeOf&#40;szName&#41; - 1&#41;; &nbsp;<br>&nbsp; &nbsp; iFldType &#58;= TypeMap&#91;DataType&#93;; &nbsp;<br>&nbsp; &nbsp; case DataType of &nbsp;<br>&nbsp; &nbsp; &nbsp; ftString, ftBytes, ftVarBytes, ftBlob, ftMemo, ftGraphic&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; iUnits1 &#58;= Size; &nbsp;<br>&nbsp; &nbsp; &nbsp; ftBCD&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; begin &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iUnits1 &#58;= 32; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iUnits2 &#58;= Size; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; end; &nbsp;<br>&nbsp; &nbsp; end; &nbsp;<br>&nbsp; &nbsp; case DataType of &nbsp;<br>&nbsp; &nbsp; &nbsp; ftCurrency&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; iSubType &#58;= fldstMONEY; &nbsp;<br>&nbsp; &nbsp; &nbsp; ftBlob&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; iSubType &#58;= fldstBINARY; &nbsp;<br>&nbsp; &nbsp; &nbsp; ftMemo&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; iSubType &#58;= fldstMEMO; &nbsp;<br>&nbsp; &nbsp; &nbsp; ftGraphic&#58; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; iSubType &#58;= fldstGRAPHIC; &nbsp;<br>&nbsp; &nbsp; end; &nbsp;<br>&nbsp; end; &nbsp;<br>end; &nbsp;<br><br>{ &nbsp;<br>&nbsp; This is where all the fun happens. I copied this function from the VCL &nbsp;<br>&nbsp; source and then changed it to use DbiCreateInMemoryTable instead of &nbsp;<br>&nbsp; DbiCreateTable. &nbsp;<br><br>&nbsp; Since InMemory tables do not support Indexes - I took all of the &nbsp;<br>&nbsp; index-related things out &nbsp;<br>} &nbsp;<br><br>procedure TInMemoryTable.CreateTable; &nbsp;<br>var &nbsp;<br>&nbsp; I&#58; Integer; &nbsp;<br>&nbsp; pFieldDesc&#58; pFLDDesc; &nbsp;<br>&nbsp; szTblName&#58; DBITBLNAME; &nbsp;<br>&nbsp; iFields&#58; Word; &nbsp;<br>&nbsp; Dogs&#58; pfldDesc; &nbsp;<br>begin &nbsp;<br>&nbsp; CheckInactive; &nbsp;<br>&nbsp; if FieldDefs.Count = 0 then &nbsp;<br>&nbsp; &nbsp; for I &#58;= 0 to FieldCount - 1 do &nbsp;<br>&nbsp; &nbsp; &nbsp; with Fields&#91;I&#93; do &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; if not Calculated then &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FieldDefs.Add&#40;FieldName, DataType, Size, Required&#41;; &nbsp;<br>&nbsp; pFieldDesc &#58;= nil; &nbsp;<br>&nbsp; SetDBFlag&#40;dbfTable, True&#41;; &nbsp;<br>&nbsp; try &nbsp;<br>&nbsp; &nbsp; AnsiToNative&#40;Locale, TableName, szTblName, SizeOf&#40;szTblName&#41; - 1&#41;; &nbsp;<br>&nbsp; &nbsp; iFields &#58;= FieldDefs.Count; &nbsp;<br>&nbsp; &nbsp; pFieldDesc &#58;= AllocMem&#40;iFields * SizeOf&#40;FLDDesc&#41;&#41;; &nbsp;<br>&nbsp; &nbsp; for I &#58;= 0 to FieldDefs.Count - 1 do &nbsp;<br>&nbsp; &nbsp; &nbsp; with FieldDefs&#91;I&#93; do &nbsp;<br>&nbsp; &nbsp; &nbsp; begin &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; EncodeFieldDesc&#40;PFieldDescList&#40;pFieldDesc&#41;^&#91;I&#93;, Name, &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DataType, Size&#41;; &nbsp;<br>&nbsp; &nbsp; &nbsp; end; &nbsp;<br>&nbsp; &nbsp; { the driver type is nil = logical fields } &nbsp;<br>&nbsp; &nbsp; Check&#40;DbiTranslateRecordStructure&#40;nil, iFields, pFieldDesc, &nbsp;<br>&nbsp; &nbsp; &nbsp; nil, nil, pFieldDesc&#41;&#41;; &nbsp;<br>&nbsp; &nbsp; { here we go - this is where hCursor gets its value } &nbsp;<br>&nbsp; &nbsp; Check&#40;DbiCreateInMemTable&#40;DBHandle, szTblName, iFields, pFieldDesc, hCursor&#41;&#41;; &nbsp;<br>&nbsp; finally &nbsp;<br>&nbsp; &nbsp; if pFieldDesc &#60;&#62; nil then FreeMem&#40;pFieldDesc, iFields * SizeOf&#40;FLDDesc&#41;&#41;; &nbsp;<br>&nbsp; &nbsp; SetDBFlag&#40;dbfTable, False&#41;; &nbsp;<br>&nbsp; end; &nbsp;<br>end; &nbsp;<br><br>end. &nbsp;<br><br>Взято с сайта http&#58;//www.swissdelphicenter.ch/en/tipsindex.php <!--c2--></td></tr></table><div class='postcolor'><!--ec2--><br><br><br><b>Решение 2. Нестандартная таблица в памяти. Не требует BDE и других DB компонентов, библиотек и т.п. Впрочем все основные методы и свойства реализованы - с гридом и другими DB комонентами коннектится, поиск и фильтры работают, по-моему есть даже методы перекачки реальной таблицы в память с автоматическим воссозданием всех структур и типов полей</b><br><br>Компонент TMemoryData из библиотек RxLib или JVCL.<br> <br><br>Кстати, во многих серьёзных серверах баз данных есть такая фишка: не обновляемые таблицы (reference-table), т.е. справочники, можно разместить в памяти на сервере, т.е. заставить сервер баз данных держать эти таблицы всё время  в памяти и доступ к ним будет очень быстрый. ]]></description>
        <author>Vit</author>
        <category>Базы данных, репортинг, печать</category>
      </item>
	
      </channel>
      </rss>
	