sqlitedataset.pas 32 KB

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