sqlitedataset.pas 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. {$mode objfpc}
  2. {$h+}
  3. unit SQLiteDataset;
  4. {
  5. Improved class sqLite,copyright(c) 2002-2003 Marcin Krzetowski
  6. [email protected]
  7. http://www.a-i.prv.pl
  8. simple class interface for SQLite. Hacked in by Ben Hochstrasser ([email protected])
  9. Thanks to Roger Reghin ([email protected]) for his idea to ValueList.
  10. }
  11. interface
  12. uses
  13. Classes,db,sysutils,Contnrs;
  14. type
  15. PRecInfo = ^TRecInfo;
  16. TRecInfo = record
  17. Index: Integer;
  18. Bookmark: Longint;
  19. BookmarkFlag: TBookmarkFlag;
  20. end;
  21. type
  22. pBinBookMark = ^tBinBookMark;
  23. tBinBookmark = record
  24. RecPtr : Int64;
  25. end;
  26. type
  27. TSQLiteExecCallback = function(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer of object; cdecl;
  28. TSQLiteBusyCallback = function(Sender: TObject; ObjectName: PChar; BusyCount: integer): integer of object; cdecl;
  29. TOnData = Procedure(Sender: TObject; Columns: Integer; ColumnNames, ColumnValues: String) of object;
  30. TOnBusy = Procedure(Sender: TObject; ObjectName: String; BusyCount: integer; var Cancel: Boolean) of object;
  31. TOnQueryComplete = Procedure(Sender: TObject) of object;
  32. Type
  33. tSqliteField = class(tObject)
  34. protected
  35. FOwner : tObject;
  36. data : string;
  37. fFieldKind: tFieldKind;
  38. fFieldType: tFieldType;
  39. { tIntegerType : Integer;
  40. tLongIntegerType : int64;
  41. tDateTimeType : tDateTime;}
  42. // procedure SetName(const Value: string);
  43. procedure SetFieldKind(const Value: tFieldKind);
  44. procedure SetFieldType(const Value: tFieldType);
  45. public
  46. constructor create(aOwner : tObject);
  47. destructor destroy; override;
  48. procedure SetData(pt : pChar; NativeFormat : boolean);
  49. function GetData(Buffer: Pointer; NativeFormat : Boolean) : boolean;
  50. function GetData(Buffer: Pointer{=True}) : boolean;
  51. // property FieldName : string read fName write SetName;
  52. property FieldKind : tFieldKind read fFieldKind write SetFieldKind;
  53. property FieldType : tFieldType read fFieldType write SetFieldType;
  54. end;
  55. tSqliteRows = class (tObject)
  56. private
  57. function getItem(index: integer): tSqliteField;
  58. procedure SetItem(index: integer; const Value: tSqliteField);
  59. function checkIndex(index : integer) : boolean;
  60. public
  61. BookmarkFlag : tBookmarkFlag;
  62. Bookmark : LongInt;
  63. DataPointer : Pointer;
  64. constructor Create(fieldCount : integer);
  65. destructor destroy; override;
  66. procedure Push(item : tSqliteField);
  67. function Pop : tSqliteField;
  68. property Items[index : integer] : tSqliteField read getItem write SetItem;
  69. procedure Clear;
  70. procedure ClearCalcFields;
  71. function add(pt : Pchar; ptName : pCHar) : boolean;
  72. protected
  73. fbuffercount : integer;
  74. fBuffer : ^tSqliteField;
  75. internalCount : integer;
  76. procedure clearBuffer;
  77. end;
  78. TSQLite = class(TDataSet)
  79. private
  80. maxLengthInit : boolean;
  81. maxiL : pinteger;
  82. maxilcount : integer;
  83. fDoExceptions : boolean;
  84. fDoSQL : boolean;
  85. fIsCancel: boolean;
  86. fSQLite: Pointer;
  87. fMsg: String;
  88. fIsOpen: Boolean;
  89. fBusy: Boolean;
  90. fError: Integer;
  91. fVersion: String;
  92. fEncoding: String;
  93. fTable: tStrings;
  94. fLstName: TStringList;
  95. fLstVal: TStringList;
  96. // fbuffer : tObjectList;
  97. fOnData: TOnData;
  98. fOnBusy: TOnBusy;
  99. fOnQueryComplete: TOnQueryComplete;
  100. fBusyTimeout: integer;
  101. fPMsg: PChar;
  102. fChangeCount: integer;
  103. fSQL: tStringlist;
  104. fonwer : tComponent;
  105. fDataBaseName : string;
  106. fDataBase: string;
  107. fTableName: string;
  108. factive : boolean;
  109. procedure SetBusyTimeout(Timeout: integer);
  110. procedure SetDataBase(DBFileName: String);
  111. procedure setTableName(const Value: string);
  112. function getIsCancel: boolean;
  113. procedure clearBuffer;
  114. protected
  115. fCalcFieldsOfs,fRecordSize : integer;
  116. fBookMarkOfs,fRecordBufferSize : integer;
  117. fCurrentRecord : int64;
  118. fRecordCount : int64;
  119. fCursorOpen : boolean;
  120. fFieldOffset : tList;
  121. // procedure internalInsert; override;
  122. function getActive: boolean;
  123. // procedure setActive(Value: boolean); override;
  124. function getRecNo : integer; override;
  125. function getBookmarkFlag(Buffer : pChar) : tBookMarkFlag; override;
  126. procedure InitBufferPointers;
  127. procedure GetBookmarkData(Buffer : pChar; Data : Pointer); override;
  128. procedure SetBookMarkData(Buffer : pChar; Data : Pointer); override;
  129. procedure InternalGotoBookmark(ABookMark : Pointer) ; override;
  130. function FieldDefsStored : boolean;
  131. procedure ClearCalcFields(Buffer : pChar); override;
  132. procedure OpenCursor(InfoQuery : Boolean); override;
  133. function getRecordCount : integer; override;
  134. procedure SetRecNo (value : integer); override;
  135. function getRecord(Buffer : pChar; GetMode : tGetMode; DoCheck : Boolean): tGetResult; override;
  136. procedure InternalInitFieldDefs; override;
  137. procedure InternalOpen; override;
  138. procedure InternalClose; override;
  139. procedure InternalAddRecord(Buffer : Pointer; DoAppend : boolean); override;
  140. procedure InternalDelete; override;
  141. procedure InternalFirst; override;
  142. procedure InternalInitRecord(Buffer : pChar); override;
  143. procedure InternalLast;override;
  144. procedure InternalPost;override;
  145. procedure InternalSetToRecord (Buffer : pChar); override;
  146. function isCursorOpen : Boolean; override;
  147. procedure SetBookmarkFlag(Buffer : pChar; value : tBookmarkFlag); override;
  148. procedure SetFieldData(Field : tField; Buffer : Pointer); override;
  149. function allocRecordBuffer : pChar; override;
  150. procedure FreeRecordBuffer(var Buffer : pChar); override;
  151. function getRecordSize : Word; override;
  152. function getCanModify : boolean; override;
  153. public
  154. fbuffer : tObjectList; //po zakonczeniu debuggowania usunac
  155. constructor create(Aowner : tComponent); override;
  156. destructor Destroy; override;
  157. function getFieldData(Field : tField; Buffer : Pointer) : boolean; override;
  158. function Query(ASql: String{table= nil}) : Boolean;
  159. Function Query(ASQL: String; Table: TStrings): boolean;
  160. function ExecSQL : boolean;
  161. function ErrorMessage(ErrNo: Integer): string;
  162. function IsComplete(ASql: String): boolean;
  163. function LastInsertRow: integer;
  164. procedure Cancel; override;
  165. function DatabaseDetails(Table: TStrings): boolean;
  166. function CreateTable : boolean;
  167. procedure countMaxiLength(pt: pChar;index : int64);
  168. procedure InitMaxLength(length : integer);
  169. published
  170. property LastErrorMessage: string read fMsg;
  171. property LastError: Integer read fError;
  172. property Version: String read fVersion;
  173. property Encoding: String read fEncoding;
  174. property OnData: TOnData read fOnData write fOnData;
  175. property OnBusy: TOnBusy read fOnBusy write fOnBusy;
  176. property OnQueryComplete: TOnQueryComplete read fOnQueryComplete write fOnQueryComplete;
  177. property BusyTimeout: Integer read fBusyTimeout write SetBusyTimeout;
  178. property ChangeCount: Integer read fChangeCount;
  179. property SQL : tStringlist read fSQL write fSQL;
  180. // property Fields : tstringlist read fFields;
  181. property DataBase : string read fDataBase write SetDataBase;
  182. property TableName : string read fTableName write setTableName;
  183. property Active : boolean read getActive write setActive;
  184. property isCancel : boolean read getIsCancel;
  185. property DoExceptions : boolean read fDoExceptions write fDoExceptions stored true default true;
  186. end;
  187. function Pas2SQLStr(const PasString: string): string;
  188. function SQL2PasStr(const SQLString: string): string;
  189. function QuoteStr(const s: string; QuoteChar: Char): string;
  190. function UnQuoteStr(const s: string; QuoteChar: Char): string;
  191. function QuoteStr(const s: string{; QuoteChar: Char = #39}): string;
  192. function UnQuoteStr(const s: string{; QuoteChar: Char = #39}): string;
  193. procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);
  194. procedure Register;
  195. implementation
  196. {$ifndef dynload}
  197. uses sqlite;
  198. {$else}
  199. uses dynlibs;
  200. function GetProcAddress(S : String) : Pointer;
  201. begin
  202. end;
  203. {$endif}
  204. const
  205. SQLITE_OK = 0; // Successful result
  206. SQLITE_ERROR = 1; // SQL error or missing database
  207. SQLITE_INTERNAL = 2; // An internal logic error in SQLite
  208. SQLITE_PERM = 3; // Access permission denied
  209. SQLITE_ABORT = 4; // Callback routine requested an abort
  210. SQLITE_BUSY = 5; // The database file is locked
  211. SQLITE_LOCKED = 6; // A table in the database is locked
  212. SQLITE_NOMEM = 7; // A malloc() failed
  213. SQLITE_READONLY = 8; // Attempt to write a readonly database
  214. SQLITE_INTERRUPT = 9; // Operation terminated by sqlite_interrupt()
  215. SQLITE_IOERR = 10; // Some kind of disk I/O error occurred
  216. SQLITE_CORRUPT = 11; // The database disk image is malformed
  217. SQLITE_NOTFOUND = 12; // (Internal Only) Table or record not found
  218. SQLITE_FULL = 13; // Insertion failed because database is full
  219. SQLITE_CANTOPEN = 14; // Unable to open the database file
  220. SQLITE_PROTOCOL = 15; // Database lock protocol error
  221. SQLITE_EMPTY = 16; // (Internal Only) Database table is empty
  222. SQLITE_SCHEMA = 17; // The database schema changed
  223. SQLITE_TOOBIG = 18; // Too much data for one row of a table
  224. SQLITE_CONSTRAINT = 19; // Abort due to contraint violation
  225. SQLITE_MISMATCH = 20; // Data type mismatch
  226. SQLITEDLL: PChar = 'sqlite.dll';
  227. DblQuote: Char = '"';
  228. SngQuote: Char = #39;
  229. Crlf: String = #13#10;
  230. Tab: Char = #9;
  231. _DO_EXCEPTIONS = 1; //Handle or not exceptions in dataset
  232. {$ifdef dynload}
  233. var
  234. SQLite_Open: function(dbname: PChar; mode: Integer; var ErrMsg: PChar): Pointer; cdecl;
  235. SQLite_Close: procedure(db: Pointer); cdecl;
  236. SQLite_Exec: function(db: Pointer; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl;
  237. SQLite_Version: function(): PChar; cdecl;
  238. SQLite_Encoding: function(): PChar; cdecl;
  239. SQLite_ErrorString: function(ErrNo: Integer): PChar; cdecl;
  240. SQLite_GetTable: function(db: Pointer; SQLStatement: PChar; var ResultPtr: Pointer; var RowCount: Cardinal; var ColCount: Cardinal; var ErrMsg: PChar): integer; cdecl;
  241. SQLite_FreeTable: procedure(Table: PChar); cdecl;
  242. SQLite_FreeMem: procedure(P: PChar); cdecl;
  243. SQLite_Complete: function(P: PChar): boolean; cdecl;
  244. SQLite_LastInsertRow: function(db: Pointer): integer; cdecl;
  245. SQLite_Cancel: procedure(db: Pointer); cdecl;
  246. SQLite_BusyHandler: procedure(db: Pointer; CallbackPtr: Pointer; Sender: TObject); cdecl;
  247. SQLite_BusyTimeout: procedure(db: Pointer; TimeOut: integer); cdecl;
  248. SQLite_Changes: function(db: Pointer): integer; cdecl;
  249. LibsLoaded: Boolean;
  250. DLLHandle: THandle;
  251. {$endif}
  252. Var
  253. MsgNoError: String;
  254. function QuoteStr(const s: string): string;
  255. begin
  256. Result := QuoteStr(S,#39);
  257. end;
  258. function QuoteStr(const s: string; QuoteChar: Char): string;
  259. begin
  260. Result := Concat(QuoteChar, s, QuoteChar);
  261. end;
  262. function UnQuoteStr(const s: string): string;
  263. begin
  264. Result := UnQuoteStr(s,#39);
  265. end;
  266. function UnQuoteStr(const s: string; QuoteChar: Char): string;
  267. begin
  268. Result := s;
  269. if length(Result) > 1 then
  270. begin
  271. if Result[1] = QuoteChar then
  272. Delete(Result, 1, 1);
  273. if Result[Length(Result)] = QuoteChar then
  274. Delete(Result, Length(Result), 1);
  275. end;
  276. end;
  277. function Pas2SQLStr(const PasString: string): string;
  278. var
  279. n: integer;
  280. begin
  281. Result := SQL2PasStr(PasString);
  282. n := Length(Result);
  283. while n > 0 do
  284. begin
  285. if Result[n] = SngQuote then
  286. Insert(SngQuote, Result, n);
  287. dec(n);
  288. end;
  289. Result := QuoteStr(Result);
  290. end;
  291. function SQL2PasStr(const SQLString: string): string;
  292. const
  293. DblSngQuote: String = #39#39;
  294. var
  295. p: integer;
  296. begin
  297. Result := SQLString;
  298. p := pos(DblSngQuote, Result);
  299. while p > 0 do
  300. begin
  301. Delete(Result, p, 1);
  302. p := pos(DblSngQuote, Result);
  303. end;
  304. Result := UnQuoteStr(Result);
  305. end;
  306. procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);
  307. var
  308. n: integer;
  309. lstName, lstValue: TStringList;
  310. begin
  311. if NameValuePairs <> nil then
  312. begin
  313. lstName := TStringList.Create;
  314. lstValue := TStringList.Create;
  315. lstName.CommaText := ColumnNames;
  316. lstValue.CommaText := ColumnValues;
  317. NameValuePairs.Clear;
  318. if lstName.Count = LstValue.Count then
  319. if lstName.Count > 0 then
  320. for n := 0 to lstName.Count - 1 do
  321. NameValuePairs.Append(Concat(lstName.Strings[n], '=', lstValue.Strings[n]));
  322. lstValue.Free;
  323. lstName.Free;
  324. end;
  325. end;
  326. {$ifdef dynload}
  327. function LoadLibs: Boolean;
  328. begin
  329. Result := False;
  330. DLLHandle := LoadLibrary(SQLITEDLL);
  331. if DLLHandle <> 0 then
  332. begin
  333. @SQLite_Open := GetProcAddress(DLLHandle, 'sqlite_open');
  334. if not Assigned(@SQLite_Open) then exit;
  335. @SQLite_Close := GetProcAddress(DLLHandle, 'sqlite_close');
  336. if not Assigned(@SQLite_Close) then exit;
  337. @SQLite_Exec := GetProcAddress(DLLHandle, 'sqlite_exec');
  338. if not Assigned(@SQLite_Exec) then exit;
  339. @SQLite_Version := GetProcAddress(DLLHandle, 'sqlite_libversion');
  340. if not Assigned(@SQLite_Version) then exit;
  341. @SQLite_Encoding := GetProcAddress(DLLHandle, 'sqlite_libencoding');
  342. if not Assigned(@SQLite_Encoding) then exit;
  343. @SQLite_ErrorString := GetProcAddress(DLLHandle, 'sqlite_error_string');
  344. if not Assigned(@SQLite_ErrorString) then exit;
  345. @SQLite_GetTable := GetProcAddress(DLLHandle, 'sqlite_get_table');
  346. if not Assigned(@SQLite_GetTable) then exit;
  347. @SQLite_FreeTable := GetProcAddress(DLLHandle, 'sqlite_free_table');
  348. if not Assigned(@SQLite_FreeTable) then exit;
  349. @SQLite_FreeMem := GetProcAddress(DLLHandle, 'sqlite_freemem');
  350. if not Assigned(@SQLite_FreeMem) then exit;
  351. @SQLite_Complete := GetProcAddress(DLLHandle, 'sqlite_complete');
  352. if not Assigned(@SQLite_Complete) then exit;
  353. @SQLite_LastInsertRow := GetProcAddress(DLLHandle, 'sqlite_last_insert_rowid');
  354. if not Assigned(@SQLite_LastInsertRow) then exit;
  355. @SQLite_Cancel := GetProcAddress(DLLHandle, 'sqlite_interrupt');
  356. if not Assigned(@SQLite_Cancel) then exit;
  357. @SQLite_BusyTimeout := GetProcAddress(DLLHandle, 'sqlite_busy_timeout');
  358. if not Assigned(@SQLite_BusyTimeout) then exit;
  359. @SQLite_BusyHandler := GetProcAddress(DLLHandle, 'sqlite_busy_handler');
  360. if not Assigned(@SQLite_BusyHandler) then exit;
  361. @SQLite_Changes := GetProcAddress(DLLHandle, 'sqlite_changes');
  362. if not Assigned(@SQLite_Changes) then exit;
  363. Result := True;
  364. end;
  365. end;
  366. {$endif}
  367. function SystemErrorMsg(ErrNo: Integer): String;
  368. var
  369. buf: PChar;
  370. size: Integer;
  371. MsgLen: Integer;
  372. begin
  373. { msglen:=0;
  374. size := 256;
  375. GetMem(buf, size);
  376. If ErrNo = - 1 then
  377. ErrNo := GetLastError;
  378. MsgLen := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, ErrNo, 0, buf, size, nil);
  379. if MsgLen = 0 then
  380. Result := 'ERROR'
  381. else
  382. Result := buf;
  383. }
  384. Result := ('SystemErrorMsg Not Implemented');
  385. end;
  386. function SystemErrorMsg: String;
  387. begin
  388. SystemErrorMsg(-1);
  389. end;
  390. function BusyCallback(Sender: Pointer; ObjectName: PChar; BusyCount: integer): integer; cdecl;
  391. var
  392. sObjName: String;
  393. bCancel: Boolean;
  394. begin
  395. Result := -1;
  396. with TSQLite(Sender) do
  397. begin
  398. if Assigned(fOnBusy) then
  399. begin
  400. bCancel := False;
  401. sObjName := ObjectName;
  402. fOnBusy(Tsqlite(Sender), sObjName, BusyCount, bCancel);
  403. if bCancel then
  404. Result := 0;
  405. end;
  406. end;
  407. end;
  408. function ExecCallback(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer; cdecl;
  409. var
  410. PVal, PName: ^PChar;
  411. n: integer;
  412. sVal, sName: String;
  413. begin
  414. Result := 0;
  415. with Sender as TSQLite do
  416. begin
  417. if (Assigned(fOnData) or Assigned(fTable)) then
  418. begin
  419. fLstName.Clear;
  420. fLstVal.Clear;
  421. if Columns > 0 then
  422. begin
  423. PName := ColumnNames;
  424. PVal := ColumnValues;
  425. for n := 0 to Columns - 1 do
  426. begin
  427. fLstName.Append(PName^);
  428. fLstVal.Append(PVal^);
  429. if Assigned(fTable) then
  430. begin
  431. fTable.Append(PVal^);
  432. end;
  433. inc(PName);
  434. inc(PVal);
  435. end;
  436. end;
  437. sVal := fLstVal.CommaText;
  438. sName := fLstName.CommaText;
  439. if Assigned(fOnData) then
  440. fOnData(Sender, Columns, sName, sVal);
  441. end;
  442. // InternalOpen;
  443. end;
  444. end;
  445. function ExecCallback2(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer; cdecl;
  446. var
  447. PVal, PName: ^PChar;
  448. n: integer;
  449. sVal, sName: String;
  450. t : tSqliteRows;
  451. p : pointer;
  452. temp : LongInt;
  453. begin
  454. Result := 0;
  455. with Sender as TSQLite do begin
  456. if (Assigned(fOnData) or assigned(fBuffer)) then begin
  457. fLstName.Clear;
  458. // fLstVal.Clear;
  459. if Columns > 0 then begin
  460. PName := ColumnNames;
  461. PVal := ColumnValues;
  462. fBuffer.Add(tSqliteRows.Create(Columns));
  463. temp:=fBuffer.count-1;
  464. initMaxLength(columns);
  465. for n := 0 to Columns - 1 do begin
  466. fLstName.Append(PName^);
  467. if Assigned(fBuffer) then begin
  468. p:=fBuffer.Items[temp];
  469. t:=tSqliteRows(p);
  470. if t=nil then continue;
  471. t.Add(PVAL^,PNAME^);
  472. end;
  473. countMaxiLength(PVAL^,n);
  474. inc(PName);
  475. inc(PVal);
  476. end;
  477. // at last we add the bookmark info
  478. t.Bookmark:=temp;
  479. end;
  480. if Assigned(fOnData) then begin
  481. sVal := fLstVal.CommaText;
  482. sName := fLstName.CommaText;
  483. fOnData(Sender, Columns, sName, sVal);
  484. end;
  485. end;
  486. // InternalOpen;
  487. end;
  488. end;
  489. procedure TSQLite.SetDataBase(DBFileName: String);
  490. var
  491. afPMsg: PChar;
  492. begin
  493. fError := SQLITE_ERROR;
  494. fIsOpen := False;
  495. fOnData := nil;
  496. fOnBusy := nil;
  497. fOnQueryComplete := nil;
  498. fChangeCount := 0;
  499. {$ifdef dynload}
  500. if LibsLoaded then
  501. begin
  502. {$endif}
  503. fSQLite := SQLite_Open(PChar(DBFileName), 1, @afPMsg);
  504. SQLite_FreeMem(afPMsg);
  505. if fSQLite <> nil then
  506. begin
  507. {$ifndef fpc}
  508. fVersion := strpas(SQLite_Version);
  509. fEncoding := strpas(SQLite_Encoding);
  510. {$endif}
  511. fIsOpen := True;
  512. fError := SQLITE_OK;
  513. end;
  514. {$ifdef dynload}
  515. end;
  516. {$endif}
  517. fMsg := ErrorMessage(fError);
  518. end;
  519. destructor TSQLite.Destroy;
  520. begin
  521. try
  522. if assigned(fSQl) then begin
  523. fsql.free;
  524. fsql:=nil;
  525. end;
  526. if fIsOpen then
  527. SQLite_Close(fSQLite);
  528. fIsOpen := False;
  529. if assigned(fLstName) then begin
  530. fLstName.Free;
  531. fLstName:=nil;
  532. end;
  533. if assigned(fLstVal) then begin
  534. fLstVal.Free;
  535. fLstVal:=nil;
  536. end;
  537. fSQLite := nil;
  538. fOnData := nil;
  539. fOnBusy := nil;
  540. fOnQueryComplete := nil;
  541. fLstName := nil;
  542. fLstVal := nil;
  543. if assigned(fBuffer) then begin
  544. clearBuffer;
  545. fBuffer.Free;
  546. fBuffer:=nil;
  547. end;
  548. except
  549. end;
  550. inherited Destroy;
  551. end;
  552. function TSQLite.Query(ASql: String): boolean;
  553. begin
  554. Result:=Query(ASql,Nil);
  555. end;
  556. function TSQLite.Query(ASql: String; Table: TStrings): boolean;
  557. //var
  558. // fPMsg: PChar;
  559. begin
  560. maxLengthInit:=false;
  561. fError := SQLITE_ERROR;
  562. if fIsOpen then
  563. begin
  564. fPMsg := nil;
  565. fBusy := True;
  566. fTable := Table;
  567. if fTable <> nil then
  568. fTable.Clear;
  569. fError := SQLite_Exec(fSQLite, PChar(ASql), @ExecCallback, Self, @fPMsg);
  570. SQLite_FreeMem(fPMsg);
  571. fChangeCount := SQLite_Changes(fSQLite);
  572. fTable := nil;
  573. fBusy := False;
  574. if Assigned(fOnQueryComplete) then
  575. fOnQueryComplete(Self);
  576. end;
  577. fMsg := ErrorMessage(fError);
  578. Result := not (fError <> SQLITE_OK);//function should return true, if execution of query ends ok..
  579. if result and not active then
  580. factive:=true;
  581. fDoSql:=true;
  582. end;
  583. procedure TSQLite.SetBusyTimeout(Timeout: Integer);
  584. begin
  585. fBusyTimeout := Timeout;
  586. if fIsOpen then
  587. begin
  588. SQLite_Busy_Timeout(fSQLite, fBusyTimeout);
  589. if fBusyTimeout > 0 then
  590. SQLite_Busy_Handler(fSQLite, @BusyCallback, Self)
  591. else
  592. SQLite_Busy_Handler(fSQLite, nil, nil);
  593. end;
  594. end;
  595. function TSQLite.LastInsertRow: integer;
  596. begin
  597. if fIsOpen then
  598. Result := SQLite_Last_Insert_Rowid(fSQLite)
  599. else
  600. Result := -1;
  601. end;
  602. function TSQLite.ErrorMessage(ErrNo: Integer): string;
  603. begin
  604. {$ifdef dynload}
  605. if LibsLoaded then
  606. begin
  607. {$endif}
  608. if ErrNo = 0 then
  609. Result := MsgNoError
  610. else
  611. Result := SQLite_Error_String(ErrNo);
  612. {$ifdef dynload}
  613. end else
  614. Raise exception.Create('Library "sqlite.dll" not found.');
  615. {$endif}
  616. end;
  617. function TSQLite.IsComplete(ASql: String): boolean;
  618. begin
  619. Result := SQLite_Complete(PChar(ASql))=0;
  620. end;
  621. function TSQLite.DatabaseDetails(Table: TStrings): boolean;
  622. begin
  623. Result := Query('SELECT * FROM SQLITE_MASTER;', Table);
  624. end;
  625. function TSQLite.ExecSQL: boolean;
  626. var i : integer;
  627. begin
  628. result:=false;
  629. maxLengthInit:=false;
  630. fError := SQLITE_ERROR;
  631. if fIsOpen then
  632. begin
  633. fPMsg := nil;
  634. fBusy := True;
  635. if fTable <> nil then
  636. fTable.Clear;
  637. for i:=0 to fsql.Count-1 do begin
  638. fError := SQLite_Exec(fSQLite, PChar(fSql[i]), @ExecCallback2, Self, @fPMsg);
  639. SQLite_FreeMem(fPMsg);
  640. end;
  641. fChangeCount := SQLite_Changes(fSQLite);
  642. fTable := nil;
  643. fBusy := False;
  644. if Assigned(fOnQueryComplete) then
  645. fOnQueryComplete(Self);
  646. end;
  647. fMsg := ErrorMessage(fError);
  648. Result :=not (fError <> SQLITE_OK);
  649. if result and not active then
  650. factive:=true;
  651. fDoSQl:=true;
  652. end;
  653. constructor TSQLite.Create(Aowner: tComponent);
  654. begin
  655. inherited create(Aowner);
  656. fLstName := TStringList.Create;
  657. fLstVal := TStringList.Create;
  658. fDoSql:=false;
  659. fsql:=tStringList.Create;
  660. fOnwer:=owner;
  661. fBuffer:=tObjectList.Create(true);
  662. if length(fDataBase)>1 then
  663. setDataBase(fDataBase);
  664. end;
  665. procedure TSQLite.setTableName(const Value: string);
  666. begin
  667. if (not active) and (length(value)>0) then begin
  668. fTableName := Value;
  669. sql.Clear;
  670. sql.add('select rowid,* from '+tableName+';');
  671. end;
  672. end;
  673. function TSQLite.getActive: boolean;
  674. begin
  675. result:=fActive;
  676. end;
  677. {
  678. procedure TSQLite.setActive(Value: boolean);
  679. begin
  680. if value then
  681. begin
  682. //switch for active=true;
  683. if active then
  684. active:=false;
  685. end
  686. else
  687. begin
  688. fDoSQL:=value;
  689. end;
  690. inherited setActive(value);
  691. end;
  692. }
  693. function TSQLite.getRecNo: integer;
  694. begin
  695. result:=self.fCurrentRecord;
  696. end;
  697. procedure TSQLite.Cancel;
  698. begin
  699. inherited;
  700. fIsCancel := False;
  701. if fBusy and fIsOpen then
  702. begin
  703. do_SQLite_interrupt(fSQLite);
  704. fBusy := false;
  705. fIsCancel := True;
  706. end;
  707. end;
  708. function TSQLite.getIsCancel: boolean;
  709. begin
  710. end;
  711. function TSQLite.getBookmarkFlag(Buffer: pChar): tBookMarkFlag;
  712. begin
  713. result:= pRecInfo(Buffer)^.BookmarkFlag;
  714. end;
  715. procedure TSQLite.InitBufferPointers;
  716. begin
  717. fCalcFieldsOfs :=fRecordSize;
  718. //fRecInfoOfs :=fCalcFieldsOfs + CalcFieldsSize;
  719. //fBookMarkOfs := fRecInfoOfs+SizeOf(tRecInfo);
  720. fRecordBufferSize :=fBookmarkOfs + BookmarkSize;
  721. end;
  722. procedure TSQLite.GetBookmarkData(Buffer: pChar; Data: Pointer);
  723. begin
  724. Move(Buffer[fBookMarkOfs],Data^,SizeOf(tBinBookMark));
  725. //implementacja jest watpliwa
  726. end;
  727. procedure TSQLite.SetBookMarkData(Buffer: pChar; Data: Pointer);
  728. begin
  729. Move(Data^,Buffer[fBookMarkOfs],SizeOf(tbinBookMark));
  730. end;
  731. procedure TSQLite.InternalGotoBookmark(ABookMark: Pointer);
  732. begin
  733. with pBinBookMark(ABookMark)^ do begin
  734. fCurrentRecord :=RecPtr;
  735. end;
  736. end;
  737. function TSQLite.FieldDefsStored: boolean;
  738. begin
  739. end;
  740. procedure TSQLite.ClearCalcFields(Buffer: pChar);
  741. var p : pointer;
  742. t : tSQliteRows;
  743. begin
  744. inherited;
  745. p:=buffer;
  746. if p<>nil then begin
  747. try
  748. t:=tSQliteRows(p);
  749. t.clearCalcFields;
  750. except
  751. end;
  752. end;
  753. end;
  754. function TSQLite.getRecordCount: integer;
  755. begin
  756. result :=fRecordCount;
  757. end;
  758. procedure TSQLite.OpenCursor(InfoQuery: Boolean);
  759. begin
  760. inherited;
  761. end;
  762. procedure TSQLite.SetRecNo(value: integer);
  763. begin
  764. inherited;
  765. end;
  766. function TSQLite.CreateTable: boolean;
  767. begin
  768. end;
  769. function TSQLite.getRecord(Buffer: pChar; GetMode: tGetMode;
  770. DoCheck: Boolean): tGetResult;
  771. begin
  772. if fRecordCount<1 then
  773. result:=grEof
  774. else begin
  775. result:=grOk;
  776. Case GetMode of
  777. gmNext :
  778. if fCurrentRecord>= (fRecordCount-1) then
  779. result:=grEof
  780. else
  781. Inc(fCurrentRecord);
  782. gmPrior :
  783. if (fCurrentRecord <=0) then
  784. result:=grBof
  785. else
  786. Dec(fCurrentRecord);
  787. gmCurrent :
  788. if (fCurrentRecord >= fRecordCount) or (fCurrentRecord <0) then
  789. result:=grError;
  790. end;
  791. end;
  792. if result=grOk then begin
  793. self.fRecordBufferSize:=sizeOf(fBuffer[fCurrentRecord]);
  794. self.fRecordSize:=self.fRecordBufferSize;
  795. // Buffer:=fBuffer.List[fcurrentRecord];
  796. //read data from psyh buffer sqlite..;)
  797. GetCalcFields(Buffer);
  798. { with fBuffer.Items[fCurrentRecord] as tSqliteRows do begin
  799. BookmarkFlag := bfCurrent;
  800. end;}
  801. with PRecInfo(Buffer)^ do
  802. begin
  803. Index := fCurrentRecord;
  804. BookmarkFlag := bfCurrent;
  805. Bookmark := Integer (fCurrentRecord);
  806. end;
  807. end;
  808. if result=grError then begin
  809. if DoCheck and DoExceptions then
  810. raise edataBaseError.Create('Invalid Record');
  811. end;
  812. end;
  813. procedure TSQLite.InternalInitFieldDefs;
  814. var i : integer;
  815. begin
  816. FieldDefs.Clear;
  817. for i:=0 to fLstname.Count-1 do begin
  818. FieldDefs.Add(fLstName[i],ftString,MaxiL[i],false);
  819. end;
  820. end;
  821. procedure TSQLite.InternalOpen;
  822. begin
  823. if fBUffer<>nil then begin
  824. clearBuffer;
  825. end;
  826. if (length(tableName)>0) and (fSQL.Count<1) then begin
  827. fsql.add('select rowid,* from '+fTableName);
  828. end;
  829. if not fDoSQL then
  830. fActive:=execSQL;
  831. InternalInitFieldDefs;
  832. {
  833. if ((fLstName.count-1)>0) and (fBuffer<>nil) then
  834. fRecordCount:=(fBuffer.Count-1) div (fLstName.Count-1)
  835. else
  836. fRecordCount:=0;
  837. }
  838. if (fBuffer<>nil) then
  839. fRecordCount:=(fBuffer.Count-1)
  840. else
  841. fRecordCount:=0;
  842. if DefaultFields then
  843. CreateFields;
  844. BindFields(true);
  845. FisOpen:=true;
  846. FRecordSize := sizeof (TRecInfo);
  847. FCurrentRecord := -1;
  848. BookmarkSize := sizeOf (Integer);
  849. end;
  850. procedure TSQLite.InternalClose;
  851. begin
  852. clearBuffer;
  853. end;
  854. function TSQLite.allocRecordBuffer: pChar;
  855. var p : pointer;
  856. begin
  857. //now is time to calculate currentRecordSize...
  858. GetMem(Result,GetRecordSize);
  859. FillChar(Result^,GetRecordSize,0);
  860. end;
  861. procedure TSQLite.FreeRecordBuffer(var Buffer: pChar);
  862. begin
  863. //FreeMem(Buffer,sizeOf(Buffer));
  864. FreeMem(Buffer,GetRecordSize);
  865. end;
  866. function TSQLite.getRecordSize: Word;
  867. begin
  868. Result:=sizeof(TRecInfo);
  869. end;
  870. procedure TSQLite.InternalAddRecord(Buffer: Pointer; DoAppend: boolean);
  871. begin
  872. end;
  873. procedure TSQLite.InternalDelete;
  874. begin
  875. end;
  876. procedure TSQLite.InternalFirst;
  877. begin
  878. self.fCurrentRecord:=0;
  879. end;
  880. procedure TSQLite.InternalInitRecord(Buffer: pChar);
  881. begin
  882. end;
  883. procedure TSQLite.InternalLast;
  884. begin
  885. fCurrentRecord:=fRecordCount;
  886. end;
  887. procedure TSQLite.InternalPost;
  888. begin
  889. end;
  890. procedure TSQLite.InternalSetToRecord(Buffer: pChar);
  891. begin
  892. end;
  893. function TSQLite.isCursorOpen: Boolean;
  894. begin
  895. end;
  896. procedure TSQLite.SetFieldData(Field: tField; Buffer: Pointer);
  897. // var aa : string;
  898. begin
  899. // Does NOthing ??
  900. // aa:=Field.NewValue;
  901. // inherited;
  902. end;
  903. procedure TSQLite.SetBookmarkFlag(Buffer: pChar; value: tBookmarkFlag);
  904. begin
  905. // inherited;
  906. end;
  907. function TSQLite.getFieldData(Field: tField; Buffer: Pointer): boolean;
  908. var i,k : integer;
  909. p : tSqliteField;
  910. r : tSqliteRows;
  911. pt : pointer;
  912. begin
  913. result:=false;
  914. k:=fieldDefs.Count-1;
  915. self.fLstName.Count;
  916. r:=fBuffer[PRecInfo(ActiveBuffer)^.Index] as tSqliteRows;
  917. if r=nil then exit;
  918. for i:=0 to k do begin
  919. if lowercase(fLstName[i])=lowercase(field.FieldName) then begin
  920. p:=r.items[i];
  921. if p = nil then break;
  922. p.GetData(Buffer,true);
  923. result:=true;
  924. break;
  925. end;
  926. end;
  927. end;
  928. { tSqliteRows }
  929. procedure tSqliteRows.Push(item: tSqliteField);
  930. begin
  931. if internalcount<fBuffercount then begin
  932. fBuffer[internalCount]:=item;
  933. inc(internalCount);
  934. end;
  935. end;
  936. constructor tSqliteRows.Create(fieldCount: integer);
  937. begin
  938. inherited create;
  939. if fieldCount<=0 then
  940. fieldCount:=1;
  941. fbuffercount:=fieldcount+1;
  942. getmem(fBuffer,fbuffercount*sizeof(pointer));
  943. end;
  944. destructor tSqliteRows.destroy;
  945. begin
  946. clearBuffer;
  947. inherited;
  948. end;
  949. function tSqliteRows.Pop: tSqliteField;
  950. begin
  951. result:=nil;
  952. if (internalCount>0) and (internalCount<fBuffercount) then begin
  953. result:=fBuffer[internalCount];
  954. Dec(internalCount);
  955. end;
  956. end;
  957. function tSqliteRows.getItem(index: integer): tSqliteField;
  958. begin
  959. result:=nil;
  960. if checkIndex(index) then
  961. result:=fBuffer[Index];
  962. end;
  963. procedure tSqliteRows.SetItem(index: integer; const Value: tSqliteField);
  964. begin
  965. if checkIndex(index) then
  966. fBuffer[index]:=Value;
  967. end;
  968. function tSqliteRows.checkIndex(index : integer): boolean;
  969. begin
  970. result:=false;
  971. if (index>=0) and (index<internalCount) then
  972. result:=true;
  973. end;
  974. procedure tSqliteRows.clearBuffer;
  975. var i : integer;
  976. begin
  977. if internalcount>0 then begin
  978. for i:=0 to internalCount -1 do begin
  979. if fBuffer[i]<>nil then begin
  980. fBuffer[i].Free;
  981. fBuffer[i]:=nil;
  982. try
  983. except
  984. continue;
  985. end;
  986. end;
  987. end;
  988. fbuffercount:=0;
  989. FreeMem(fBuffer);
  990. end;
  991. end;
  992. procedure tSqliteRows.Clear;
  993. begin
  994. clearBuffer;
  995. internalCount:=0;
  996. end;
  997. procedure tSqliteRows.ClearCalcFields;
  998. begin
  999. end;
  1000. function tSqliteRows.Add(pt: pChar;ptName : pChar):boolean;
  1001. var tmp : int64;
  1002. begin
  1003. Push(tSqliteField.Create(nil));
  1004. tmp:=internalCount-1;
  1005. items[tmp].FieldKind:=fkData;
  1006. items[tmp].SetFieldType(ftString);
  1007. items[tmp].SetData(pt,true);
  1008. end;
  1009. procedure tSqlite.countMaxiLength(pt: pChar; index : int64);
  1010. begin
  1011. if length(pt)>maxil[index] then
  1012. maxiL[index]:=length(pt);
  1013. end;
  1014. { tSqliteField }
  1015. constructor tSqliteField.create(aOwner: tObject);
  1016. begin
  1017. inherited create;
  1018. fOwner:=aOwner;
  1019. end;
  1020. destructor tSqliteField.destroy;
  1021. begin
  1022. inherited;
  1023. end;
  1024. function tSqliteField.GetData(Buffer: Pointer) : boolean;
  1025. begin
  1026. Result:=GetData(Buffer,True);
  1027. end ;
  1028. function tSqliteField.GetData(Buffer: Pointer;
  1029. NativeFormat: Boolean): boolean;
  1030. var
  1031. l,tIntegerType : integer;
  1032. tDateTimeType : tDateTime;
  1033. begin
  1034. try
  1035. result:=false;
  1036. if not nativeFormat then begin
  1037. Move(data,Buffer^,sizeOf(data));
  1038. result:=true;
  1039. end else begin
  1040. case self.fieldType of
  1041. ftInteger : begin
  1042. tIntegerType:=StrToInt(data);
  1043. Move(tIntegerType,Buffer^,sizeOf(data));
  1044. end;
  1045. ftDateTime : begin
  1046. tDateTimeType:=StrToDate(data);
  1047. Move(tDateTimeType,Buffer^,sizeOf(data));
  1048. end;
  1049. ftString : begin
  1050. // L:=length(data);
  1051. // Move(data,Buffer^,l);
  1052. StrCopy (Buffer, pchar(data));
  1053. end;
  1054. else
  1055. Move(data,Buffer^,sizeOf(data));
  1056. end;
  1057. result:=true;
  1058. end;
  1059. except
  1060. Buffer:=nil;
  1061. end;
  1062. end;
  1063. procedure tSqliteField.SetData(pt: pChar; NativeFormat: boolean);
  1064. begin
  1065. data:=pt;
  1066. end;
  1067. procedure tSqliteField.SetFieldKind(const Value: tFieldKind);
  1068. begin
  1069. fFieldKind := Value;
  1070. end;
  1071. procedure tSqliteField.SetFieldType(const Value: tFieldType);
  1072. begin
  1073. fFieldType := Value;
  1074. end;
  1075. {
  1076. procedure tSqliteField.SetName(const Value: string);
  1077. begin
  1078. fName := Value;
  1079. end;
  1080. }
  1081. function TSQLite.getCanModify: boolean;
  1082. begin
  1083. result:=false;
  1084. exit;//temporary
  1085. if length(fTableName)>0 then
  1086. result:=true;
  1087. end;
  1088. procedure TSQLite.InitMaxLength(length: integer);
  1089. begin
  1090. if not maxLengthInit and (length>0) then begin
  1091. maxLengthInit:=true;
  1092. maxilcount:=length;
  1093. getmem(maxiL,maxilcount*sizeof(integer));
  1094. end;
  1095. end;
  1096. procedure TSQLite.clearBuffer;
  1097. begin
  1098. if assigned(fBuffer) then begin
  1099. if fBuffer.count>0 then begin
  1100. fBuffer.pack;
  1101. fBuffer.clear;
  1102. end;
  1103. end;
  1104. if assigned(fLstVal) then begin
  1105. fLstVal.Clear;
  1106. end;
  1107. if assigned(fLstName) then begin
  1108. fLstName.Clear;
  1109. end;
  1110. end;
  1111. {
  1112. procedure TSQLite.internalInsert;
  1113. begin
  1114. inherited;
  1115. if not getCanModify then exit;
  1116. end;
  1117. }
  1118. procedure Register;
  1119. begin
  1120. RegisterComponents('MK', [tSqlite]);
  1121. end;
  1122. initialization
  1123. {$ifdef dynload}
  1124. LibsLoaded := LoadLibs;
  1125. {$endif}
  1126. {$ifdef fpc}
  1127. MsgNoError := SystemErrorMsg(0);
  1128. {$else}
  1129. MsgNoError := 'The operation completed successfully';
  1130. {$endif}
  1131. finalization
  1132. {$ifdef dynload}
  1133. if DLLHandle <> 0 then
  1134. FreeLibrary(DLLHandle);
  1135. {$endif}
  1136. end.