sqldb.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. { $Id$
  2. Copyright (c) 2004 by Joost van der Sluis
  3. SQL database & dataset
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit sqldb;
  11. {$mode objfpc}
  12. {$H+}
  13. {$M+} // ### remove this!!!
  14. interface
  15. uses SysUtils, Classes, DB;
  16. type
  17. TSQLConnection = class;
  18. TSQLTransaction = class;
  19. TSQLQuery = class;
  20. TStatementType = (stNone, stSelect, stInsert, stUpdate, stDelete,
  21. stDDL, stGetSegment, stPutSegment, stExecProcedure,
  22. stStartTrans, stCommit, stRollback, stSelectForUpd);
  23. TSQLHandle = Class(TObject)
  24. protected
  25. StatementType : TStatementType;
  26. end;
  27. const
  28. StatementTokens : Array[TStatementType] of string = ('(none)', 'select',
  29. 'insert', 'update', 'delete',
  30. 'create', 'get', 'put', 'execute',
  31. 'start','commit','rollback', '?'
  32. );
  33. { TSQLConnection }
  34. type
  35. TSQLConnection = class (TDatabase)
  36. private
  37. FPassword : string;
  38. FTransaction : TSQLTransaction;
  39. FUserName : string;
  40. FHostName : string;
  41. FCharSet : string;
  42. FRole : String;
  43. procedure SetTransaction(Value : TSQLTransaction);
  44. protected
  45. procedure DoInternalConnect; override;
  46. procedure DoInternalDisconnect; override;
  47. function GetAsSQLText(Field : TField) : string; virtual;
  48. function GetHandle : pointer; virtual; abstract;
  49. Function AllocateCursorHandle : TSQLHandle; virtual; abstract;
  50. Function AllocateTransactionHandle : TSQLHandle; virtual; abstract;
  51. procedure FreeStatement(cursor : TSQLHandle); virtual; abstract;
  52. procedure PrepareStatement(cursor: TSQLHandle;ATransaction : TSQLTransaction;buf : string); virtual; abstract;
  53. procedure FreeFldBuffers(cursor : TSQLHandle); virtual; abstract;
  54. procedure Execute(cursor: TSQLHandle;atransaction:tSQLtransaction); virtual; abstract;
  55. procedure AddFieldDefs(cursor: TSQLHandle; FieldDefs : TfieldDefs); virtual; abstract;
  56. function Fetch(cursor : TSQLHandle) : boolean; virtual; abstract;
  57. function LoadField(cursor : TSQLHandle;FieldDef : TfieldDef;buffer : pointer) : boolean; virtual; abstract;
  58. function GetTransactionHandle(trans : TSQLHandle): pointer; virtual; abstract;
  59. function Commit(trans : TSQLHandle) : boolean; virtual; abstract;
  60. function RollBack(trans : TSQLHandle) : boolean; virtual; abstract;
  61. function StartdbTransaction(trans : TSQLHandle) : boolean; virtual; abstract;
  62. procedure CommitRetaining(trans : TSQLHandle); virtual; abstract;
  63. procedure RollBackRetaining(trans : TSQLHandle); virtual; abstract;
  64. public
  65. destructor Destroy; override;
  66. property Handle: Pointer read GetHandle;
  67. published
  68. property Password : string read FPassword write FPassword;
  69. property Transaction : TSQLTransaction read FTransaction write SetTransaction;
  70. property UserName : string read FUserName write FUserName;
  71. property CharSet : string read FCharSet write FCharSet;
  72. property HostName : string Read FHostName Write FHostName;
  73. property Connected;
  74. Property Role : String read FRole write FRole;
  75. property DatabaseName;
  76. property KeepConnection;
  77. property LoginPrompt;
  78. property Params;
  79. property OnLogin;
  80. end;
  81. { TSQLTransaction }
  82. TCommitRollbackAction = (caNone, caCommit, caCommitRetaining, caRollback,
  83. caRollbackRetaining);
  84. TSQLTransaction = class (TDBTransaction)
  85. private
  86. FTrans : TSQLHandle;
  87. FAction : TCommitRollbackAction;
  88. protected
  89. function GetHandle : Pointer; virtual;
  90. public
  91. procedure Commit; virtual;
  92. procedure CommitRetaining; virtual;
  93. procedure Rollback; virtual;
  94. procedure RollbackRetaining; virtual;
  95. procedure StartTransaction; override;
  96. constructor Create(AOwner : TComponent); override;
  97. destructor Destroy; override;
  98. property Handle: Pointer read GetHandle;
  99. procedure EndTransaction; override;
  100. published
  101. property Action : TCommitRollbackAction read FAction write FAction;
  102. property Database;
  103. end;
  104. { TSQLQuery }
  105. TSQLQuery = class (Tbufdataset)
  106. private
  107. FCursor : TSQLHandle;
  108. FUpdateable : boolean;
  109. FTableName : string;
  110. FSQL : TStrings;
  111. FIsEOF : boolean;
  112. FLoadingFieldDefs : boolean;
  113. procedure FreeStatement;
  114. procedure PrepareStatement;
  115. procedure FreeFldBuffers;
  116. procedure InitUpdates(SQL : string);
  117. procedure Execute;
  118. protected
  119. // abstract & virual methods of TBufDataset
  120. function Fetch : boolean; override;
  121. function LoadField(FieldDef : TFieldDef;buffer : pointer) : boolean; override;
  122. // abstract & virual methods of TDataset
  123. procedure SetDatabase(Value : TDatabase); override;
  124. procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
  125. procedure InternalClose; override;
  126. procedure InternalDelete; override;
  127. procedure InternalHandleException; override;
  128. procedure InternalInitFieldDefs; override;
  129. procedure InternalOpen; override;
  130. function GetCanModify: Boolean; override;
  131. Function GetSQLStatementType(SQL : String) : TStatementType; virtual;
  132. function ApplyRecUpdate : boolean; override;
  133. public
  134. procedure ExecSQL; virtual;
  135. constructor Create(AOwner : TComponent); override;
  136. destructor Destroy; override;
  137. published
  138. // redeclared data set properties
  139. property Active;
  140. // property Filter;
  141. // property Filtered;
  142. // property FilterOptions;
  143. property BeforeOpen;
  144. property AfterOpen;
  145. property BeforeClose;
  146. property AfterClose;
  147. property BeforeInsert;
  148. property AfterInsert;
  149. property BeforeEdit;
  150. property AfterEdit;
  151. property BeforePost;
  152. property AfterPost;
  153. property BeforeCancel;
  154. property AfterCancel;
  155. property BeforeDelete;
  156. property AfterDelete;
  157. property BeforeScroll;
  158. property AfterScroll;
  159. property OnCalcFields;
  160. property OnDeleteError;
  161. property OnEditError;
  162. property OnFilterRecord;
  163. property OnNewRecord;
  164. property OnPostError;
  165. property AutoCalcFields;
  166. property Database;
  167. property Transaction;
  168. property SQL : TStrings read FSQL write FSQL;
  169. end;
  170. implementation
  171. uses dbconst;
  172. { TSQLConnection }
  173. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  174. begin
  175. if FTransaction = nil then
  176. begin
  177. FTransaction := Value;
  178. if Assigned(FTransaction) then
  179. FTransaction.Database := Self;
  180. exit;
  181. end;
  182. if (Value <> FTransaction) and (Value <> nil) then
  183. if (not FTransaction.Active) then
  184. begin
  185. FTransaction := Value;
  186. FTransaction.Database := Self;
  187. end
  188. else
  189. DatabaseError(SErrAssTransaction);
  190. end;
  191. procedure TSQLConnection.DoInternalConnect;
  192. begin
  193. // Where is this for?!?!
  194. // if Connected then
  195. // Close;
  196. end;
  197. procedure TSQLConnection.DoInternalDisconnect;
  198. begin
  199. end;
  200. destructor TSQLConnection.Destroy;
  201. begin
  202. inherited Destroy;
  203. end;
  204. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  205. begin
  206. if not assigned(field) then Result := 'Null'
  207. else case field.DataType of
  208. ftString : Result := '''' + field.asstring + ''''
  209. else
  210. Result := field.asstring;
  211. end; {case}
  212. end;
  213. { TSQLTransaction }
  214. procedure TSQLTransaction.EndTransaction;
  215. begin
  216. rollback;
  217. end;
  218. function TSQLTransaction.GetHandle: pointer;
  219. begin
  220. Result := (Database as tsqlconnection).GetTransactionHandle(FTrans);
  221. end;
  222. procedure TSQLTransaction.Commit;
  223. begin
  224. if active then
  225. begin
  226. closedatasets;
  227. if (Database as tsqlconnection).commit(FTrans) then
  228. begin
  229. closeTrans;
  230. FreeAndNil(FTrans);
  231. end;
  232. end;
  233. end;
  234. procedure TSQLTransaction.CommitRetaining;
  235. begin
  236. if active then
  237. (Database as tsqlconnection).commitRetaining(FTrans);
  238. end;
  239. procedure TSQLTransaction.Rollback;
  240. begin
  241. if active then
  242. begin
  243. closedatasets;
  244. if (Database as tsqlconnection).RollBack(FTrans) then
  245. begin
  246. CloseTrans;
  247. FreeAndNil(FTrans);
  248. end;
  249. end;
  250. end;
  251. procedure TSQLTransaction.RollbackRetaining;
  252. begin
  253. if active then
  254. (Database as tsqlconnection).RollBackRetaining(FTrans);
  255. end;
  256. procedure TSQLTransaction.StartTransaction;
  257. var db : TSQLConnection;
  258. begin
  259. if Active then
  260. DatabaseError(SErrTransAlreadyActive);
  261. db := (Database as tsqlconnection);
  262. if Db = nil then
  263. DatabaseError(SErrDatabasenAssigned);
  264. if not Db.Connected then
  265. Db.Open;
  266. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  267. if Db.StartdbTransaction(FTrans) then OpenTrans;
  268. end;
  269. constructor TSQLTransaction.Create(AOwner : TComponent);
  270. begin
  271. inherited Create(AOwner);
  272. end;
  273. destructor TSQLTransaction.Destroy;
  274. begin
  275. Rollback;
  276. inherited Destroy;
  277. end;
  278. { TSQLQuery }
  279. procedure TSQLQuery.SetDatabase(Value : TDatabase);
  280. var db : tsqlconnection;
  281. begin
  282. if (Database <> Value) then
  283. begin
  284. db := value as tsqlconnection;
  285. inherited setdatabase(value);
  286. if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
  287. transaction := Db.Transaction;
  288. end;
  289. end;
  290. procedure TSQLQuery.FreeStatement;
  291. begin
  292. if assigned(FCursor) then
  293. begin
  294. (Database as tsqlconnection).FreeStatement(FCursor);
  295. // FreeAndNil(FCursor);
  296. end;
  297. end;
  298. procedure TSQLQuery.PrepareStatement;
  299. var
  300. Buf : string;
  301. x : integer;
  302. db : tsqlconnection;
  303. sqltr : tsqltransaction;
  304. begin
  305. db := (Database as tsqlconnection);
  306. if Db = nil then
  307. DatabaseError(SErrDatabasenAssigned);
  308. if not Db.Connected then
  309. db.Open;
  310. if Transaction = nil then
  311. DatabaseError(SErrTransactionnSet);
  312. sqltr := (transaction as tsqltransaction);
  313. if not sqltr.Active then sqltr.StartTransaction;
  314. if assigned(fcursor) then FreeAndNil(fcursor);
  315. FCursor := Db.AllocateCursorHandle;
  316. Buf := '';
  317. for x := 0 to FSQL.Count - 1 do
  318. Buf := Buf + FSQL[x] + ' ';
  319. if Buf='' then
  320. begin
  321. DatabaseError(SErrNoStatement);
  322. exit;
  323. end;
  324. FCursor.StatementType := GetSQLStatementType(buf);
  325. if FCursor.StatementType = stSelect then
  326. InitUpdates(Buf);
  327. Db.PrepareStatement(Fcursor,sqltr,buf);
  328. end;
  329. procedure TSQLQuery.FreeFldBuffers;
  330. begin
  331. if assigned(FCursor) then (Database as tsqlconnection).FreeFldBuffers(FCursor);
  332. end;
  333. function TSQLQuery.Fetch : boolean;
  334. begin
  335. if not (Fcursor.StatementType in [stSelect]) then
  336. Exit;
  337. if not FIsEof then FIsEOF := not (Database as tsqlconnection).Fetch(Fcursor);
  338. Result := not FIsEOF;
  339. end;
  340. procedure TSQLQuery.Execute;
  341. begin
  342. (Database as tsqlconnection).execute(Fcursor,Transaction as tsqltransaction);
  343. end;
  344. function TSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer) : boolean;
  345. begin
  346. result := (Database as tSQLConnection).LoadField(FCursor,FieldDef,buffer)
  347. end;
  348. procedure TSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  349. begin
  350. // not implemented - sql dataset
  351. end;
  352. procedure TSQLQuery.InternalClose;
  353. begin
  354. FreeFldBuffers;
  355. FreeStatement;
  356. if DefaultFields then
  357. DestroyFields;
  358. FIsEOF := False;
  359. // FRecordSize := 0;
  360. inherited internalclose;
  361. end;
  362. procedure TSQLQuery.InternalDelete;
  363. begin
  364. // not implemented - sql dataset
  365. end;
  366. procedure TSQLQuery.InternalHandleException;
  367. begin
  368. end;
  369. procedure TSQLQuery.InternalInitFieldDefs;
  370. begin
  371. if FLoadingFieldDefs then
  372. Exit;
  373. FLoadingFieldDefs := True;
  374. try
  375. FieldDefs.Clear;
  376. (Database as tsqlconnection).AddFieldDefs(fcursor,FieldDefs);
  377. finally
  378. FLoadingFieldDefs := False;
  379. end;
  380. end;
  381. procedure TSQLQuery.InitUpdates(SQL : string);
  382. Var
  383. L : Integer;
  384. P,PP : PChar;
  385. PS: PChar;
  386. S : string;
  387. function GetStatement(var StartP : PChar) : PChar;
  388. var p : pchar;
  389. Cmt, Stm : boolean;
  390. begin
  391. p := StartP;
  392. Cmt := false;
  393. Stm := False;
  394. While ((P-PP)<L) do
  395. begin
  396. if Cmt then
  397. begin
  398. end
  399. else if (p^ in [',',' ','(',')',#13,#10,#9]) then
  400. begin
  401. if stm then break;
  402. end
  403. else if not stm then
  404. begin
  405. StartP := p;
  406. stm := true;
  407. end;
  408. inc(p);
  409. end;
  410. Result := P;
  411. end;
  412. begin
  413. FUpdateable := False;
  414. L:=Length(SQL);
  415. PP:=Pchar(SQL);
  416. P := pp;
  417. PS := pp;
  418. // select-keyword
  419. P := GetStatement(PS);
  420. Setlength(S,P-PS);
  421. Move(PS^,S[1],(P-PS));
  422. S:=Lowercase(S);
  423. if (S) <> 'select' then exit;
  424. // select-part
  425. While ((P-PP)<L) and (S <> 'from') do
  426. begin
  427. repeat
  428. PS := P;
  429. P := GetStatement(PS);
  430. until P^ <> ',';
  431. Setlength(S,P-PS);
  432. Move(PS^,S[1],(P-PS));
  433. S:=Lowercase(S);
  434. end;
  435. // from-part
  436. PS := P;
  437. P := GetStatement(PS);
  438. Setlength(FTableName,P-PS);
  439. Move(PS^,FTableName[1],(P-PS));
  440. While ((P-PP)<L) do
  441. begin
  442. PS := P;
  443. P := GetStatement(PS);
  444. if P^ = ',' then exit; // select-statements from more then one table are not updateable
  445. Setlength(S,P-PS);
  446. Move(PS^,S[1],(P-PS));
  447. S:=Lowercase(S);
  448. if (s = 'where') or (s='order') then break;
  449. end;
  450. FUpdateable := True;
  451. end;
  452. procedure TSQLQuery.InternalOpen;
  453. begin
  454. try
  455. PrepareStatement;
  456. if Fcursor.StatementType in [stSelect] then
  457. begin
  458. Execute;
  459. InternalInitFieldDefs;
  460. if DefaultFields then
  461. CreateFields;
  462. end
  463. else
  464. DatabaseError(SErrNoSelectStatement,Self);
  465. except
  466. on E:Exception do
  467. raise;
  468. end;
  469. inherited InternalOpen;
  470. end;
  471. // public part
  472. procedure TSQLQuery.ExecSQL;
  473. begin
  474. try
  475. PrepareStatement;
  476. Execute;
  477. finally
  478. FreeStatement;
  479. end;
  480. end;
  481. constructor TSQLQuery.Create(AOwner : TComponent);
  482. begin
  483. inherited Create(AOwner);
  484. FSQL := TStringList.Create;
  485. end;
  486. destructor TSQLQuery.Destroy;
  487. begin
  488. if Active then Close;
  489. // if assigned(FCursor) then FCursor.destroy;
  490. FreeAndNil(FSQL);
  491. inherited Destroy;
  492. end;
  493. Function TSQLQuery.GetSQLStatementType(SQL : String) : TStatementType;
  494. Var
  495. L : Integer;
  496. cmt : boolean;
  497. P,PE,PP : PChar;
  498. S : string;
  499. T : TStatementType;
  500. begin
  501. Result:=stNone;
  502. L:=Length(SQL);
  503. If (L=0) then
  504. Exit;
  505. P:=Pchar(SQL);
  506. PP:=P;
  507. Cmt:=False;
  508. While ((P-PP)<L) do
  509. begin
  510. if not (P^ in [' ',#13,#10,#9]) then
  511. begin
  512. if not Cmt then
  513. begin
  514. // Check for comment.
  515. Cmt:=(P^='/') and (((P-PP)<=L) and (P[1]='*'));
  516. if not (cmt) then
  517. Break;
  518. end
  519. else
  520. begin
  521. // Check for end of comment.
  522. Cmt:=Not( (P^='*') and (((P-PP)<=L) and (P[1]='/')) );
  523. If not cmt then
  524. Inc(p);
  525. end;
  526. end;
  527. inc(P);
  528. end;
  529. PE:=P+1;
  530. While ((PE-PP)<L) and (PE^ in ['0'..'9','a'..'z','A'..'Z','_']) do
  531. Inc(PE);
  532. Setlength(S,PE-P);
  533. Move(P^,S[1],(PE-P));
  534. S:=Lowercase(s);
  535. For t:=stselect to strollback do
  536. if (S=StatementTokens[t]) then
  537. Exit(t);
  538. end;
  539. function TSQLQuery.ApplyRecUpdate : boolean;
  540. var r,x,f : integer;
  541. fieldsstr,
  542. v : string;
  543. modify_query : tsqlquery;
  544. sql_tables : string;
  545. sql_set : string;
  546. sql_where : string;
  547. s : string;
  548. begin
  549. Result := False;
  550. sql_tables := FTableName;
  551. s := fields[0].oldvalue;
  552. sql_where := '('+fields[0].displayName+'='+s+')';
  553. sql_set := '';
  554. for x := 0 to Fields.Count -1 do
  555. if ord(ActiveBuffer[(Fields[x].Fieldno-1) div 8]) and (1 shl ((Fields[x].Fieldno-1) mod 8)) > 0 then // check for null
  556. sql_set := sql_set + fields[x].DisplayName + '=' + (Database as TSQLConnection).GetAsSQLText(nil) + ','
  557. else
  558. sql_set := sql_set + fields[x].DisplayName + '=' + (Database as TSQLConnection).GetAsSQLText(fields[x]) + ',';
  559. setlength(sql_set,length(sql_set)-1);
  560. with tsqlquery.Create(nil) do
  561. begin
  562. DataBase := self.Database;
  563. transaction := self.transaction;
  564. sql.clear;
  565. s := 'update ' + sql_tables + ' set ' + sql_set + ' where ' + sql_where;
  566. sql.add(s);
  567. ExecSQL;
  568. Result := true;
  569. Free;
  570. end;
  571. end;
  572. Function TSQLQuery.GetCanModify: Boolean;
  573. begin
  574. if FCursor.StatementType = stSelect then
  575. Result:= Active and FUpdateable
  576. else
  577. Result := False;
  578. end;
  579. end.
  580. {
  581. $Log$
  582. Revision 1.10 2004-12-29 14:31:27 michael
  583. + Patch from Joost van der Sluis:
  584. - implemented support for modifying queries, with a simple parser
  585. - implemented ApplyRecUpdate
  586. Revision 1.9 2004/12/13 19:22:16 michael
  587. * Ptahc from Joost van der Sluis
  588. - moved IsCursorOpen from TSQLQuery to tbufdataset
  589. - moved SetFieldData from TSQLQuery to TBufDataset
  590. - very first start for support of cached updates
  591. Revision 1.8 2004/12/04 22:43:38 michael
  592. * Patch from Joost van der Sluis
  593. - replaced checkactive in commit and rollback for 'if active'
  594. - fixed a warning
  595. - adapted for the changes in TBuffDataset
  596. Revision 1.7 2004/11/05 08:32:02 michael
  597. TBufDataset.inc:
  598. - replaced Freemem by Reallocmem, Free by FreeAndNil
  599. Database.inc:
  600. - Moved Active property from TSQLTransaction to TDBTransaction
  601. - Gives an error if the database of an active transaction is changed
  602. Dataset.inc
  603. - Don't distribute events if FDisableControlsCount > 0
  604. - Replaced FActive by FState<>dsInactive
  605. - Set EOF after append
  606. db.pp:
  607. - Removed duplicate definition of TAlignment
  608. - Moved Active property from TSQLTransaction to TDBTransaction
  609. - Replaced FActive by FState<>dsInactive
  610. - Gives an error if the database of an active transaction is changed
  611. sqldb:
  612. - Moved Active property from TSQLTransaction to TDBTransaction
  613. - replaced Freemem by Reallocmem, Free by FreeAndNil
  614. IBConnection:
  615. - Moved FSQLDAAllocated to the cursor
  616. PQConnection:
  617. - Don't try to free the statement if a fatal error occured
  618. Revision 1.6 2004/10/27 07:23:13 michael
  619. + Patch from Joost Van der Sluis to fix transactions
  620. Revision 1.5 2004/10/10 14:45:52 michael
  621. + Use of dbconst for resource strings
  622. Revision 1.4 2004/10/10 14:24:22 michael
  623. * Large patch from Joost Van der Sluis.
  624. * Float fix in interbase
  625. + Commit and commitretaining for pqconnection
  626. + Preparestatement and prepareselect joined.
  627. + Freestatement and FreeSelect joined
  628. + TSQLQuery.GetSQLStatementType implemented
  629. + TBufDataset.AllocBuffer now no longer does a realloc
  630. + Fetch=True means succesfully got data. False means end of data.
  631. + Default implementation of GetFieldData implemented/
  632. Revision 1.3 2004/10/02 14:52:25 michael
  633. + Added mysql connection
  634. Revision 1.2 2004/09/26 16:56:32 michael
  635. + Further fixes from Joost van der sluis for Postgresql
  636. Revision 1.1 2004/08/31 09:49:47 michael
  637. + initial implementation of TSQLQuery
  638. }