sqlitedataset.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  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. If ErrNo = - 1 then
  378. ErrNo := GetLastError;
  379. MsgLen := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, ErrNo, 0, buf, size, nil);
  380. if MsgLen = 0 then
  381. Result := 'ERROR'
  382. else
  383. Result := buf;
  384. }
  385. Result := ('SystemErrorMsg Not Implemented');
  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 -1 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.