sqldb.pp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. {
  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, bufdataset;
  16. type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages);
  17. TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat);
  18. TConnOptions= set of TConnOption;
  19. type
  20. TSQLConnection = class;
  21. TSQLTransaction = class;
  22. TSQLQuery = class;
  23. TSQLScript = class;
  24. TStatementType = (stNone, stSelect, stInsert, stUpdate, stDelete,
  25. stDDL, stGetSegment, stPutSegment, stExecProcedure,
  26. stStartTrans, stCommit, stRollback, stSelectForUpd);
  27. TSQLHandle = Class(TObject)
  28. end;
  29. { TSQLCursor }
  30. TSQLCursor = Class(TSQLHandle)
  31. public
  32. FPrepared : Boolean;
  33. FInitFieldDef : Boolean;
  34. FStatementType : TStatementType;
  35. FBlobStrings : TStringList; // list of strings in which the blob-fields are stored
  36. public
  37. constructor Create; virtual;
  38. destructor Destroy; override;
  39. end;
  40. const
  41. StatementTokens : Array[TStatementType] of string = ('(none)', 'select',
  42. 'insert', 'update', 'delete',
  43. 'create', 'get', 'put', 'execute',
  44. 'start','commit','rollback', '?'
  45. );
  46. { TSQLConnection }
  47. type
  48. { TSQLConnection }
  49. TSQLConnection = class (TDatabase)
  50. private
  51. FPassword : string;
  52. FTransaction : TSQLTransaction;
  53. FUserName : string;
  54. FHostName : string;
  55. FCharSet : string;
  56. FRole : String;
  57. procedure SetTransaction(Value : TSQLTransaction);
  58. procedure GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
  59. protected
  60. FConnOptions : TConnOptions;
  61. function StrToStatementType(s : string) : TStatementType; virtual;
  62. procedure DoInternalConnect; override;
  63. procedure DoInternalDisconnect; override;
  64. function GetAsSQLText(Field : TField) : string; overload; virtual;
  65. function GetAsSQLText(Param : TParam) : string; overload; virtual;
  66. function GetHandle : pointer; virtual; virtual;
  67. Function AllocateCursorHandle : TSQLCursor; virtual; abstract;
  68. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); virtual; abstract;
  69. Function AllocateTransactionHandle : TSQLHandle; virtual; abstract;
  70. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); virtual; abstract;
  71. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
  72. function Fetch(cursor : TSQLCursor) : boolean; virtual; abstract;
  73. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); virtual; abstract;
  74. procedure UnPrepareStatement(cursor : TSQLCursor); virtual; abstract;
  75. procedure FreeFldBuffers(cursor : TSQLCursor); virtual;
  76. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; virtual; abstract;
  77. function GetTransactionHandle(trans : TSQLHandle): pointer; virtual; abstract;
  78. function Commit(trans : TSQLHandle) : boolean; virtual; abstract;
  79. function RollBack(trans : TSQLHandle) : boolean; virtual; abstract;
  80. function StartdbTransaction(trans : TSQLHandle; aParams : string) : boolean; virtual; abstract;
  81. procedure CommitRetaining(trans : TSQLHandle); virtual; abstract;
  82. procedure RollBackRetaining(trans : TSQLHandle); virtual; abstract;
  83. procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); virtual;
  84. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; virtual;
  85. procedure LoadBlobIntoStream(Field: TField;AStream: TStream;cursor: TSQLCursor;ATransaction : TSQLTransaction); virtual;
  86. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); virtual; abstract;
  87. public
  88. property Handle: Pointer read GetHandle;
  89. destructor Destroy; override;
  90. procedure StartTransaction; override;
  91. procedure EndTransaction; override;
  92. property ConnOptions: TConnOptions read FConnOptions;
  93. procedure ExecuteDirect(SQL : String); overload; virtual;
  94. procedure ExecuteDirect(SQL : String; ATransaction : TSQLTransaction); overload; virtual;
  95. procedure GetTableNames(List : TStrings; SystemTables : Boolean = false); virtual;
  96. procedure GetProcedureNames(List : TStrings); virtual;
  97. procedure GetFieldNames(const TableName : string; List : TStrings); virtual;
  98. procedure CreateDB; virtual;
  99. procedure DropDB; virtual;
  100. published
  101. property Password : string read FPassword write FPassword;
  102. property Transaction : TSQLTransaction read FTransaction write SetTransaction;
  103. property UserName : string read FUserName write FUserName;
  104. property CharSet : string read FCharSet write FCharSet;
  105. property HostName : string Read FHostName Write FHostName;
  106. property Connected;
  107. Property Role : String read FRole write FRole;
  108. property DatabaseName;
  109. property KeepConnection;
  110. property LoginPrompt;
  111. property Params;
  112. property OnLogin;
  113. end;
  114. { TSQLTransaction }
  115. TCommitRollbackAction = (caNone, caCommit, caCommitRetaining, caRollback,
  116. caRollbackRetaining);
  117. TSQLTransaction = class (TDBTransaction)
  118. private
  119. FTrans : TSQLHandle;
  120. FAction : TCommitRollbackAction;
  121. FParams : TStringList;
  122. protected
  123. function GetHandle : Pointer; virtual;
  124. Procedure SetDatabase (Value : TDatabase); override;
  125. public
  126. procedure Commit; virtual;
  127. procedure CommitRetaining; virtual;
  128. procedure Rollback; virtual;
  129. procedure RollbackRetaining; virtual;
  130. procedure StartTransaction; override;
  131. constructor Create(AOwner : TComponent); override;
  132. destructor Destroy; override;
  133. property Handle: Pointer read GetHandle;
  134. procedure EndTransaction; override;
  135. published
  136. property Action : TCommitRollbackAction read FAction write FAction;
  137. property Database;
  138. property Params : TStringList read FParams write FParams;
  139. end;
  140. { TSQLQuery }
  141. TSQLQuery = class (Tbufdataset)
  142. private
  143. FCursor : TSQLCursor;
  144. FUpdateable : boolean;
  145. FTableName : string;
  146. FSQL : TStringList;
  147. FUpdateSQL,
  148. FInsertSQL,
  149. FDeleteSQL : TStringList;
  150. FIsEOF : boolean;
  151. FLoadingFieldDefs : boolean;
  152. FIndexDefs : TIndexDefs;
  153. FReadOnly : boolean;
  154. FUpdateMode : TUpdateMode;
  155. FParams : TParams;
  156. FusePrimaryKeyAsKey : Boolean;
  157. FSQLBuf : String;
  158. FFromPart : String;
  159. FWhereStartPos : integer;
  160. FWhereStopPos : integer;
  161. FParseSQL : boolean;
  162. FMasterLink : TMasterParamsDatalink;
  163. // FSchemaInfo : TSchemaInfo;
  164. FServerFilterText : string;
  165. FServerFiltered : Boolean;
  166. FUpdateQry,
  167. FDeleteQry,
  168. FInsertQry : TSQLQuery;
  169. procedure FreeFldBuffers;
  170. procedure InitUpdates(ASQL : string);
  171. function GetIndexDefs : TIndexDefs;
  172. function GetStatementType : TStatementType;
  173. procedure SetIndexDefs(AValue : TIndexDefs);
  174. procedure SetReadOnly(AValue : Boolean);
  175. procedure SetParseSQL(AValue : Boolean);
  176. procedure SetUsePrimaryKeyAsKey(AValue : Boolean);
  177. procedure SetUpdateMode(AValue : TUpdateMode);
  178. procedure OnChangeSQL(Sender : TObject);
  179. procedure OnChangeModifySQL(Sender : TObject);
  180. procedure Execute;
  181. Procedure SQLParser(var ASQL : string);
  182. procedure ApplyFilter;
  183. Function AddFilter(SQLstr : string) : string;
  184. protected
  185. // abstract & virtual methods of TBufDataset
  186. function Fetch : boolean; override;
  187. function LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  188. // abstract & virtual methods of TDataset
  189. procedure UpdateIndexDefs; override;
  190. procedure SetDatabase(Value : TDatabase); override;
  191. Procedure SetTransaction(Value : TDBTransaction); override;
  192. procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
  193. procedure InternalClose; override;
  194. procedure InternalInitFieldDefs; override;
  195. procedure InternalOpen; override;
  196. function GetCanModify: Boolean; override;
  197. procedure ApplyRecUpdate(UpdateKind : TUpdateKind); override;
  198. Function IsPrepared : Boolean; virtual;
  199. Procedure SetActive (Value : Boolean); override;
  200. procedure SetServerFiltered(Value: Boolean); virtual;
  201. procedure SetServerFilterText(const Value: string); virtual;
  202. Function GetDataSource : TDatasource; override;
  203. Procedure SetDataSource(AValue : TDatasource);
  204. procedure LoadBlobIntoStream(Field: TField;AStream: TStream); override;
  205. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField); override;
  206. public
  207. procedure Prepare; virtual;
  208. procedure UnPrepare; virtual;
  209. procedure ExecSQL; virtual;
  210. constructor Create(AOwner : TComponent); override;
  211. destructor Destroy; override;
  212. procedure SetSchemaInfo( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string); virtual;
  213. property Prepared : boolean read IsPrepared;
  214. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  215. published
  216. // redeclared data set properties
  217. property Active;
  218. property Filter;
  219. property Filtered;
  220. property ServerFilter: string read FServerFilterText write SetServerFilterText;
  221. property ServerFiltered: Boolean read FServerFiltered write SetServerFiltered default False;
  222. // property FilterOptions;
  223. property BeforeOpen;
  224. property AfterOpen;
  225. property BeforeClose;
  226. property AfterClose;
  227. property BeforeInsert;
  228. property AfterInsert;
  229. property BeforeEdit;
  230. property AfterEdit;
  231. property BeforePost;
  232. property AfterPost;
  233. property BeforeCancel;
  234. property AfterCancel;
  235. property BeforeDelete;
  236. property AfterDelete;
  237. property BeforeScroll;
  238. property AfterScroll;
  239. property OnCalcFields;
  240. property OnDeleteError;
  241. property OnEditError;
  242. property OnFilterRecord;
  243. property OnNewRecord;
  244. property OnPostError;
  245. property AutoCalcFields;
  246. property Database;
  247. property Transaction;
  248. property ReadOnly : Boolean read FReadOnly write SetReadOnly;
  249. property SQL : TStringlist read FSQL write FSQL;
  250. property UpdateSQL : TStringlist read FUpdateSQL write FUpdateSQL;
  251. property InsertSQL : TStringlist read FInsertSQL write FInsertSQL;
  252. property DeleteSQL : TStringlist read FDeleteSQL write FDeleteSQL;
  253. property IndexDefs : TIndexDefs read GetIndexDefs;
  254. property Params : TParams read FParams write FParams;
  255. property UpdateMode : TUpdateMode read FUpdateMode write SetUpdateMode;
  256. property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey;
  257. property StatementType : TStatementType read GetStatementType;
  258. property ParseSQL : Boolean read FParseSQL write SetParseSQL;
  259. Property DataSource : TDatasource Read GetDataSource Write SetDatasource;
  260. // property SchemaInfo : TSchemaInfo read FSchemaInfo default stNoSchema;
  261. end;
  262. { TSQLScript }
  263. TSQLScript = class (Tcomponent)
  264. private
  265. FScript : TStrings;
  266. FQuery : TSQLQuery;
  267. FDatabase : TDatabase;
  268. FTransaction : TDBTransaction;
  269. protected
  270. procedure SetScript(const AValue: TStrings);
  271. Procedure SetDatabase (Value : TDatabase); virtual;
  272. Procedure SetTransaction(Value : TDBTransaction); virtual;
  273. Procedure CheckDatabase;
  274. public
  275. constructor Create(AOwner : TComponent); override;
  276. destructor Destroy; override;
  277. procedure ExecuteScript;
  278. Property Script : TStrings Read FScript Write SetScript;
  279. Property DataBase : TDatabase Read FDatabase Write SetDatabase;
  280. Property Transaction : TDBTransaction Read FTransaction Write SetTransaction;
  281. end;
  282. implementation
  283. uses dbconst, strutils;
  284. { TSQLConnection }
  285. function TSQLConnection.StrToStatementType(s : string) : TStatementType;
  286. var T : TStatementType;
  287. begin
  288. S:=Lowercase(s);
  289. For t:=stselect to strollback do
  290. if (S=StatementTokens[t]) then
  291. Exit(t);
  292. end;
  293. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  294. begin
  295. if FTransaction<>value then
  296. begin
  297. if Assigned(FTransaction) and FTransaction.Active then
  298. DatabaseError(SErrAssTransaction);
  299. if Assigned(Value) then
  300. Value.Database := Self;
  301. FTransaction := Value;
  302. end;
  303. end;
  304. procedure TSQLConnection.UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string);
  305. begin
  306. // Empty abstract
  307. end;
  308. procedure TSQLConnection.DoInternalConnect;
  309. begin
  310. if (DatabaseName = '') then
  311. DatabaseError(SErrNoDatabaseName,self);
  312. end;
  313. procedure TSQLConnection.DoInternalDisconnect;
  314. begin
  315. end;
  316. destructor TSQLConnection.Destroy;
  317. begin
  318. inherited Destroy;
  319. end;
  320. procedure TSQLConnection.StartTransaction;
  321. begin
  322. if not assigned(Transaction) then
  323. DatabaseError(SErrConnTransactionnSet)
  324. else
  325. Transaction.StartTransaction;
  326. end;
  327. procedure TSQLConnection.EndTransaction;
  328. begin
  329. if not assigned(Transaction) then
  330. DatabaseError(SErrConnTransactionnSet)
  331. else
  332. Transaction.EndTransaction;
  333. end;
  334. Procedure TSQLConnection.ExecuteDirect(SQL: String);
  335. begin
  336. ExecuteDirect(SQL,FTransaction);
  337. end;
  338. Procedure TSQLConnection.ExecuteDirect(SQL: String; ATransaction : TSQLTransaction);
  339. var Cursor : TSQLCursor;
  340. begin
  341. if not assigned(ATransaction) then
  342. DatabaseError(SErrTransactionnSet);
  343. if not Connected then Open;
  344. if not ATransaction.Active then ATransaction.StartTransaction;
  345. try
  346. Cursor := AllocateCursorHandle;
  347. SQL := TrimRight(SQL);
  348. if SQL = '' then
  349. DatabaseError(SErrNoStatement);
  350. Cursor.FStatementType := stNone;
  351. PrepareStatement(cursor,ATransaction,SQL,Nil);
  352. execute(cursor,ATransaction, Nil);
  353. UnPrepareStatement(Cursor);
  354. finally;
  355. DeAllocateCursorHandle(Cursor);
  356. end;
  357. end;
  358. procedure TSQLConnection.GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
  359. var qry : TSQLQuery;
  360. begin
  361. if not assigned(Transaction) then
  362. DatabaseError(SErrConnTransactionnSet);
  363. qry := tsqlquery.Create(nil);
  364. qry.transaction := Transaction;
  365. qry.database := Self;
  366. with qry do
  367. begin
  368. ParseSQL := False;
  369. SetSchemaInfo(SchemaType,SchemaObjectName,'');
  370. open;
  371. List.Clear;
  372. while not eof do
  373. begin
  374. List.Append(fieldbyname(ReturnField).asstring);
  375. Next;
  376. end;
  377. end;
  378. qry.free;
  379. end;
  380. procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
  381. begin
  382. if not systemtables then GetDBInfo(stTables,'','table_name',List)
  383. else GetDBInfo(stSysTables,'','table_name',List);
  384. end;
  385. procedure TSQLConnection.GetProcedureNames(List: TStrings);
  386. begin
  387. GetDBInfo(stProcedures,'','proc_name',List);
  388. end;
  389. procedure TSQLConnection.GetFieldNames(const TableName: string; List: TStrings);
  390. begin
  391. GetDBInfo(stColumns,TableName,'column_name',List);
  392. end;
  393. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  394. begin
  395. if (not assigned(field)) or field.IsNull then Result := 'Null'
  396. else case field.DataType of
  397. ftString : Result := '''' + field.asstring + '''';
  398. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Field.AsDateTime) + '''';
  399. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Field.AsDateTime) + ''''
  400. else
  401. Result := field.asstring;
  402. end; {case}
  403. end;
  404. function TSQLConnection.GetAsSQLText(Param: TParam) : string;
  405. begin
  406. if (not assigned(param)) or param.IsNull then Result := 'Null'
  407. else case param.DataType of
  408. ftString : Result := '''' + param.asstring + '''';
  409. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Param.AsDateTime) + '''';
  410. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Param.AsDateTime) + ''''
  411. else
  412. Result := Param.asstring;
  413. end; {case}
  414. end;
  415. function TSQLConnection.GetHandle: pointer;
  416. begin
  417. Result := nil;
  418. end;
  419. procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
  420. begin
  421. cursor.FBlobStrings.Clear;
  422. end;
  423. function TSQLConnection.GetSchemaInfoSQL( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string;
  424. begin
  425. DatabaseError(SMetadataUnavailable);
  426. end;
  427. procedure TSQLConnection.LoadBlobIntoStream(Field: TField;AStream: TStream; cursor: TSQLCursor;ATransaction : TSQLTransaction);
  428. var blobId : pinteger;
  429. BlobBuf : TBufBlobField;
  430. s : string;
  431. begin
  432. { if not field.getData(@BlobBuf) then
  433. exit;
  434. blobId := @BlobBuf.BufBlobId;
  435. s := cursor.FBlobStrings.Strings[blobid^];
  436. AStream.WriteBuffer(s[1],length(s));
  437. AStream.seek(0,soFromBeginning);}
  438. end;
  439. procedure TSQLConnection.CreateDB;
  440. begin
  441. DatabaseError(SNotSupported);
  442. end;
  443. procedure TSQLConnection.DropDB;
  444. begin
  445. DatabaseError(SNotSupported);
  446. end;
  447. { TSQLTransaction }
  448. procedure TSQLTransaction.EndTransaction;
  449. begin
  450. rollback;
  451. end;
  452. function TSQLTransaction.GetHandle: pointer;
  453. begin
  454. Result := (Database as tsqlconnection).GetTransactionHandle(FTrans);
  455. end;
  456. procedure TSQLTransaction.Commit;
  457. begin
  458. if active then
  459. begin
  460. closedatasets;
  461. if (Database as tsqlconnection).commit(FTrans) then
  462. begin
  463. closeTrans;
  464. FreeAndNil(FTrans);
  465. end;
  466. end;
  467. end;
  468. procedure TSQLTransaction.CommitRetaining;
  469. begin
  470. if active then
  471. (Database as tsqlconnection).commitRetaining(FTrans);
  472. end;
  473. procedure TSQLTransaction.Rollback;
  474. begin
  475. if active then
  476. begin
  477. closedatasets;
  478. if (Database as tsqlconnection).RollBack(FTrans) then
  479. begin
  480. CloseTrans;
  481. FreeAndNil(FTrans);
  482. end;
  483. end;
  484. end;
  485. procedure TSQLTransaction.RollbackRetaining;
  486. begin
  487. if active then
  488. (Database as tsqlconnection).RollBackRetaining(FTrans);
  489. end;
  490. procedure TSQLTransaction.StartTransaction;
  491. var db : TSQLConnection;
  492. begin
  493. if Active then
  494. DatabaseError(SErrTransAlreadyActive);
  495. db := (Database as tsqlconnection);
  496. if Db = nil then
  497. DatabaseError(SErrDatabasenAssigned);
  498. if not Db.Connected then
  499. Db.Open;
  500. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  501. if Db.StartdbTransaction(FTrans,FParams.CommaText) then OpenTrans;
  502. end;
  503. constructor TSQLTransaction.Create(AOwner : TComponent);
  504. begin
  505. inherited Create(AOwner);
  506. FParams := TStringList.Create;
  507. end;
  508. destructor TSQLTransaction.Destroy;
  509. begin
  510. Rollback;
  511. FreeAndNil(FParams);
  512. inherited Destroy;
  513. end;
  514. Procedure TSQLTransaction.SetDatabase(Value : TDatabase);
  515. begin
  516. If Value<>Database then
  517. begin
  518. CheckInactive;
  519. If Assigned(Database) then
  520. with Database as TSqlConnection do
  521. if Transaction = self then Transaction := nil;
  522. inherited SetDatabase(Value);
  523. end;
  524. end;
  525. { TSQLQuery }
  526. procedure TSQLQuery.OnChangeSQL(Sender : TObject);
  527. var ConnOptions : TConnOptions;
  528. begin
  529. UnPrepare;
  530. if (FSQL <> nil) then
  531. begin
  532. if assigned(DataBase) then
  533. ConnOptions := (DataBase as TSQLConnection).ConnOptions
  534. else
  535. ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
  536. Fparams.ParseSQL(FSQL.Text,True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase);
  537. If Assigned(FMasterLink) then
  538. FMasterLink.RefreshParamNames;
  539. end;
  540. end;
  541. procedure TSQLQuery.OnChangeModifySQL(Sender : TObject);
  542. begin
  543. CheckInactive;
  544. end;
  545. Procedure TSQLQuery.SetTransaction(Value : TDBTransaction);
  546. begin
  547. UnPrepare;
  548. inherited;
  549. end;
  550. procedure TSQLQuery.SetDatabase(Value : TDatabase);
  551. var db : tsqlconnection;
  552. begin
  553. if (Database <> Value) then
  554. begin
  555. UnPrepare;
  556. if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
  557. db := value as tsqlconnection;
  558. inherited setdatabase(value);
  559. if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
  560. transaction := Db.Transaction;
  561. OnChangeSQL(Self);
  562. end;
  563. end;
  564. Function TSQLQuery.IsPrepared : Boolean;
  565. begin
  566. Result := Assigned(FCursor) and FCursor.FPrepared;
  567. end;
  568. Function TSQLQuery.AddFilter(SQLstr : string) : string;
  569. begin
  570. if FWhereStartPos = 0 then
  571. SQLstr := SQLstr + ' where (' + Filter + ')'
  572. else if FWhereStopPos > 0 then
  573. system.insert(' and ('+Filter+') ',SQLstr,FWhereStopPos+1)
  574. else
  575. system.insert(' where ('+Filter+') ',SQLstr,FWhereStartPos);
  576. Result := SQLstr;
  577. end;
  578. procedure TSQLQuery.ApplyFilter;
  579. var S : String;
  580. begin
  581. FreeFldBuffers;
  582. (Database as tsqlconnection).UnPrepareStatement(FCursor);
  583. FIsEOF := False;
  584. inherited internalclose;
  585. s := FSQLBuf;
  586. if ServerFiltered then s := AddFilter(s);
  587. (Database as tsqlconnection).PrepareStatement(Fcursor,(transaction as tsqltransaction),S,FParams);
  588. Execute;
  589. inherited InternalOpen;
  590. First;
  591. end;
  592. Procedure TSQLQuery.SetActive (Value : Boolean);
  593. begin
  594. inherited SetActive(Value);
  595. // The query is UnPrepared, so that if a transaction closes all datasets
  596. // they also get unprepared
  597. if not Value and IsPrepared then UnPrepare;
  598. end;
  599. procedure TSQLQuery.SetServerFiltered(Value: Boolean);
  600. begin
  601. if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
  602. if (ServerFiltered <> Value) then
  603. begin
  604. FServerFiltered := Value;
  605. if active then ApplyFilter;
  606. end;
  607. end;
  608. procedure TSQLQuery.SetServerFilterText(const Value: string);
  609. begin
  610. if Value <> ServerFilter then
  611. begin
  612. FServerFilterText := Value;
  613. if active then ApplyFilter;
  614. end;
  615. end;
  616. procedure TSQLQuery.Prepare;
  617. var
  618. db : tsqlconnection;
  619. sqltr : tsqltransaction;
  620. begin
  621. if not IsPrepared then
  622. begin
  623. db := (Database as tsqlconnection);
  624. sqltr := (transaction as tsqltransaction);
  625. if not assigned(Db) then
  626. DatabaseError(SErrDatabasenAssigned);
  627. if not assigned(sqltr) then
  628. DatabaseError(SErrTransactionnSet);
  629. if not Db.Connected then db.Open;
  630. if not sqltr.Active then sqltr.StartTransaction;
  631. // if assigned(fcursor) then FreeAndNil(fcursor);
  632. if not assigned(fcursor) then
  633. FCursor := Db.AllocateCursorHandle;
  634. FSQLBuf := TrimRight(FSQL.Text);
  635. if FSQLBuf = '' then
  636. DatabaseError(SErrNoStatement);
  637. SQLParser(FSQLBuf);
  638. if ServerFiltered then
  639. Db.PrepareStatement(Fcursor,sqltr,AddFilter(FSQLBuf),FParams)
  640. else
  641. Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
  642. if (FCursor.FStatementType = stSelect) then
  643. begin
  644. FCursor.FInitFieldDef := True;
  645. if not ReadOnly then InitUpdates(FSQLBuf);
  646. end;
  647. end;
  648. end;
  649. procedure TSQLQuery.UnPrepare;
  650. begin
  651. CheckInactive;
  652. if IsPrepared then with Database as TSQLConnection do
  653. UnPrepareStatement(FCursor);
  654. end;
  655. procedure TSQLQuery.FreeFldBuffers;
  656. begin
  657. if assigned(FCursor) then (Database as tsqlconnection).FreeFldBuffers(FCursor);
  658. end;
  659. function TSQLQuery.Fetch : boolean;
  660. begin
  661. if not (Fcursor.FStatementType in [stSelect]) then
  662. Exit;
  663. if not FIsEof then FIsEOF := not (Database as tsqlconnection).Fetch(Fcursor);
  664. Result := not FIsEOF;
  665. end;
  666. procedure TSQLQuery.Execute;
  667. begin
  668. If (FParams.Count>0) and Assigned(FMasterLink) then
  669. FMasterLink.CopyParamsFromMaster(False);
  670. (Database as tsqlconnection).execute(Fcursor,Transaction as tsqltransaction, FParams);
  671. end;
  672. function TSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  673. begin
  674. result := (Database as tSQLConnection).LoadField(FCursor,FieldDef,buffer, Createblob)
  675. end;
  676. procedure TSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  677. begin
  678. // not implemented - sql dataset
  679. end;
  680. procedure TSQLQuery.InternalClose;
  681. begin
  682. if StatementType = stSelect then FreeFldBuffers;
  683. // Database and FCursor could be nil, for example if the database is not assigned, and .open is called
  684. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then (database as TSQLconnection).UnPrepareStatement(FCursor);
  685. if DefaultFields then
  686. DestroyFields;
  687. FIsEOF := False;
  688. if assigned(FUpdateQry) then FreeAndNil(FUpdateQry);
  689. if assigned(FInsertQry) then FreeAndNil(FInsertQry);
  690. if assigned(FDeleteQry) then FreeAndNil(FDeleteQry);
  691. // FRecordSize := 0;
  692. inherited internalclose;
  693. end;
  694. procedure TSQLQuery.InternalInitFieldDefs;
  695. begin
  696. if FLoadingFieldDefs then
  697. Exit;
  698. FLoadingFieldDefs := True;
  699. try
  700. FieldDefs.Clear;
  701. (Database as tsqlconnection).AddFieldDefs(fcursor,FieldDefs);
  702. finally
  703. FLoadingFieldDefs := False;
  704. FCursor.FInitFieldDef := false;
  705. end;
  706. end;
  707. procedure TSQLQuery.SQLParser(var ASQL : string);
  708. type TParsePart = (ppStart,ppSelect,ppWhere,ppFrom,ppOrder,ppComment,ppGroup,ppBogus);
  709. Var
  710. PSQL,CurrentP,
  711. PhraseP, PStatementPart : pchar;
  712. S : string;
  713. ParsePart : TParsePart;
  714. StrLength : Integer;
  715. EndOfComment : Boolean;
  716. BracketCount : Integer;
  717. ConnOptions : TConnOptions;
  718. begin
  719. PSQL:=Pchar(ASQL);
  720. ParsePart := ppStart;
  721. CurrentP := PSQL-1;
  722. PhraseP := PSQL;
  723. FWhereStartPos := 0;
  724. FWhereStopPos := 0;
  725. ConnOptions := (DataBase as TSQLConnection).ConnOptions;
  726. repeat
  727. begin
  728. inc(CurrentP);
  729. EndOfComment := SkipComments(CurrentP,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
  730. if EndOfcomment then dec(currentp);
  731. if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;
  732. // skip everything between bracket, since it could be a sub-select, and
  733. // further nothing between brackets could be interesting for the parser.
  734. if currentp^='(' then
  735. begin
  736. inc(currentp);
  737. BracketCount := 0;
  738. while (currentp^ <> #0) and ((currentp^ <> ')') or (BracketCount > 0 )) do
  739. begin
  740. if currentp^ = '(' then inc(bracketcount)
  741. else if currentp^ = ')' then dec(bracketcount);
  742. inc(currentp);
  743. end;
  744. EndOfComment := True;
  745. end;
  746. if EndOfComment or (CurrentP^ in [' ',#13,#10,#9,#0,';']) then
  747. begin
  748. if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
  749. begin
  750. strLength := CurrentP-PhraseP;
  751. Setlength(S,strLength);
  752. if strLength > 0 then Move(PhraseP^,S[1],(strLength));
  753. s := uppercase(s);
  754. case ParsePart of
  755. ppStart : begin
  756. FCursor.FStatementType := (Database as tsqlconnection).StrToStatementType(s);
  757. if FCursor.FStatementType = stSelect then ParsePart := ppSelect
  758. else break;
  759. if not FParseSQL then break;
  760. PStatementPart := CurrentP;
  761. end;
  762. ppSelect : begin
  763. if s = 'FROM' then
  764. begin
  765. ParsePart := ppFrom;
  766. PhraseP := CurrentP;
  767. PStatementPart := CurrentP;
  768. end;
  769. end;
  770. ppFrom : begin
  771. if (s = 'WHERE') or (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  772. begin
  773. if (s = 'WHERE') then
  774. begin
  775. ParsePart := ppWhere;
  776. StrLength := PhraseP-PStatementPart;
  777. end
  778. else if (s = 'GROUP') then
  779. begin
  780. ParsePart := ppGroup;
  781. StrLength := PhraseP-PStatementPart;
  782. end
  783. else if (s = 'ORDER') then
  784. begin
  785. ParsePart := ppOrder;
  786. StrLength := PhraseP-PStatementPart
  787. end
  788. else
  789. begin
  790. ParsePart := ppBogus;
  791. StrLength := CurrentP-PStatementPart;
  792. end;
  793. Setlength(FFromPart,StrLength);
  794. Move(PStatementPart^,FFromPart[1],(StrLength));
  795. FFrompart := trim(FFrompart);
  796. FWhereStartPos := PStatementPart-PSQL+StrLength+1;
  797. PStatementPart := CurrentP;
  798. end;
  799. end;
  800. ppWhere : begin
  801. if (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  802. begin
  803. ParsePart := ppBogus;
  804. FWhereStartPos := PStatementPart-PSQL;
  805. if (s = 'ORDER') or (s = 'GROUP') then
  806. FWhereStopPos := PhraseP-PSQL+1
  807. else
  808. FWhereStopPos := CurrentP-PSQL+1;
  809. end;
  810. end;
  811. end; {case}
  812. end;
  813. PhraseP := CurrentP+1;
  814. end
  815. end;
  816. until CurrentP^=#0;
  817. if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
  818. begin
  819. system.insert('(',ASQL,FWhereStartPos+1);
  820. inc(FWhereStopPos);
  821. system.insert(')',ASQL,FWhereStopPos);
  822. end
  823. end;
  824. procedure TSQLQuery.InitUpdates(ASQL : string);
  825. begin
  826. if pos(',',FFromPart) > 0 then
  827. FUpdateable := False // select-statements from more then one table are not updateable
  828. else
  829. begin
  830. FUpdateable := True;
  831. FTableName := FFromPart;
  832. end;
  833. end;
  834. procedure TSQLQuery.InternalOpen;
  835. procedure InitialiseModifyQuery(var qry : TSQLQuery; aSQL: TSTringList);
  836. begin
  837. qry := TSQLQuery.Create(nil);
  838. with qry do
  839. begin
  840. ParseSQL := False;
  841. DataBase := Self.DataBase;
  842. Transaction := Self.Transaction;
  843. SQL.Assign(aSQL);
  844. end;
  845. end;
  846. var tel : integer;
  847. f : TField;
  848. s : string;
  849. begin
  850. try
  851. Prepare;
  852. if FCursor.FStatementType in [stSelect] then
  853. begin
  854. Execute;
  855. // InternalInitFieldDef is only called after a prepare. i.e. not twice if
  856. // a dataset is opened - closed - opened.
  857. if FCursor.FInitFieldDef then InternalInitFieldDefs;
  858. if DefaultFields then
  859. begin
  860. CreateFields;
  861. if FUpdateable then
  862. begin
  863. if FusePrimaryKeyAsKey then
  864. begin
  865. UpdateIndexDefs;
  866. for tel := 0 to indexdefs.count-1 do {with indexdefs[tel] do}
  867. begin
  868. if ixPrimary in indexdefs[tel].options then
  869. begin
  870. // Todo: If there is more then one field in the key, that must be parsed
  871. s := indexdefs[tel].fields;
  872. F := Findfield(s);
  873. if F <> nil then
  874. F.ProviderFlags := F.ProviderFlags + [pfInKey];
  875. end;
  876. end;
  877. end;
  878. end;
  879. end
  880. else
  881. BindFields(True);
  882. if FUpdateable then
  883. begin
  884. InitialiseModifyQuery(FDeleteQry,FDeleteSQL);
  885. InitialiseModifyQuery(FUpdateQry,FUpdateSQL);
  886. InitialiseModifyQuery(FInsertQry,FInsertSQL);
  887. end;
  888. end
  889. else
  890. DatabaseError(SErrNoSelectStatement,Self);
  891. except
  892. on E:Exception do
  893. raise;
  894. end;
  895. inherited InternalOpen;
  896. end;
  897. // public part
  898. procedure TSQLQuery.ExecSQL;
  899. begin
  900. try
  901. Prepare;
  902. Execute;
  903. finally
  904. // FCursor has to be assigned, or else the prepare went wrong before PrepareStatment was
  905. // called, so UnPrepareStatement shoudn't be called either
  906. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then (database as TSQLConnection).UnPrepareStatement(Fcursor);
  907. end;
  908. end;
  909. constructor TSQLQuery.Create(AOwner : TComponent);
  910. begin
  911. inherited Create(AOwner);
  912. FParams := TParams.create(self);
  913. FSQL := TStringList.Create;
  914. FSQL.OnChange := @OnChangeSQL;
  915. FUpdateSQL := TStringList.Create;
  916. FUpdateSQL.OnChange := @OnChangeModifySQL;
  917. FInsertSQL := TStringList.Create;
  918. FInsertSQL.OnChange := @OnChangeModifySQL;
  919. FDeleteSQL := TStringList.Create;
  920. FDeleteSQL.OnChange := @OnChangeModifySQL;
  921. FIndexDefs := TIndexDefs.Create(Self);
  922. FReadOnly := false;
  923. FParseSQL := True;
  924. FServerFiltered := False;
  925. FServerFilterText := '';
  926. // Delphi has upWhereAll as default, but since strings and oldvalue's don't work yet
  927. // (variants) set it to upWhereKeyOnly
  928. FUpdateMode := upWhereKeyOnly;
  929. FUsePrimaryKeyAsKey := True;
  930. end;
  931. destructor TSQLQuery.Destroy;
  932. begin
  933. if Active then Close;
  934. UnPrepare;
  935. if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
  936. FreeAndNil(FMasterLink);
  937. FreeAndNil(FParams);
  938. FreeAndNil(FSQL);
  939. FreeAndNil(FInsertSQL);
  940. FreeAndNil(FDeleteSQL);
  941. FreeAndNil(FUpdateSQL);
  942. FreeAndNil(FIndexDefs);
  943. inherited Destroy;
  944. end;
  945. procedure TSQLQuery.SetReadOnly(AValue : Boolean);
  946. begin
  947. CheckInactive;
  948. if not AValue then
  949. begin
  950. if FParseSQL then FReadOnly := False
  951. else DatabaseErrorFmt(SNoParseSQL,['Updating ']);
  952. end
  953. else FReadOnly := True;
  954. end;
  955. procedure TSQLQuery.SetParseSQL(AValue : Boolean);
  956. begin
  957. CheckInactive;
  958. if not AValue then
  959. begin
  960. FReadOnly := True;
  961. FServerFiltered := False;
  962. FParseSQL := False;
  963. end
  964. else
  965. FParseSQL := True;
  966. end;
  967. procedure TSQLQuery.SetUsePrimaryKeyAsKey(AValue : Boolean);
  968. begin
  969. if not Active then FusePrimaryKeyAsKey := AValue
  970. else
  971. begin
  972. // Just temporary, this should be possible in the future
  973. DatabaseError(SActiveDataset);
  974. end;
  975. end;
  976. Procedure TSQLQuery.UpdateIndexDefs;
  977. begin
  978. if assigned(DataBase) then
  979. (DataBase as TSQLConnection).UpdateIndexDefs(FIndexDefs,FTableName);
  980. end;
  981. Procedure TSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
  982. procedure UpdateWherePart(var sql_where : string;x : integer);
  983. begin
  984. if (pfInKey in Fields[x].ProviderFlags) or
  985. ((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
  986. ((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
  987. sql_where := sql_where + '(' + fields[x].FieldName + '= :OLD_' + fields[x].FieldName + ') and ';
  988. end;
  989. function ModifyRecQuery : string;
  990. var x : integer;
  991. sql_set : string;
  992. sql_where : string;
  993. begin
  994. sql_set := '';
  995. sql_where := '';
  996. for x := 0 to Fields.Count -1 do
  997. begin
  998. UpdateWherePart(sql_where,x);
  999. if (pfInUpdate in Fields[x].ProviderFlags) then
  1000. sql_set := sql_set + fields[x].FieldName + '=:' + fields[x].FieldName + ',';
  1001. end;
  1002. if length(sql_set) = 0 then DatabaseError(sNoUpdateFields,self);
  1003. setlength(sql_set,length(sql_set)-1);
  1004. if length(sql_where) = 0 then DatabaseError(sNoWhereFields,self);
  1005. setlength(sql_where,length(sql_where)-5);
  1006. result := 'update ' + FTableName + ' set ' + sql_set + ' where ' + sql_where;
  1007. end;
  1008. function InsertRecQuery : string;
  1009. var x : integer;
  1010. sql_fields : string;
  1011. sql_values : string;
  1012. begin
  1013. sql_fields := '';
  1014. sql_values := '';
  1015. for x := 0 to Fields.Count -1 do
  1016. begin
  1017. if (not fields[x].IsNull) and (pfInUpdate in Fields[x].ProviderFlags) then
  1018. begin
  1019. sql_fields := sql_fields + fields[x].FieldName + ',';
  1020. sql_values := sql_values + ':' + fields[x].FieldName + ',';
  1021. end;
  1022. end;
  1023. if length(sql_fields) = 0 then DatabaseError(sNoUpdateFields,self);
  1024. setlength(sql_fields,length(sql_fields)-1);
  1025. setlength(sql_values,length(sql_values)-1);
  1026. result := 'insert into ' + FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
  1027. end;
  1028. function DeleteRecQuery : string;
  1029. var x : integer;
  1030. sql_where : string;
  1031. begin
  1032. sql_where := '';
  1033. for x := 0 to Fields.Count -1 do
  1034. UpdateWherePart(sql_where,x);
  1035. if length(sql_where) = 0 then DatabaseError(sNoWhereFields,self);
  1036. setlength(sql_where,length(sql_where)-5);
  1037. result := 'delete from ' + FTableName + ' where ' + sql_where;
  1038. end;
  1039. var qry : tsqlquery;
  1040. x : integer;
  1041. Fld : TField;
  1042. begin
  1043. case UpdateKind of
  1044. ukModify : begin
  1045. qry := FUpdateQry;
  1046. if trim(qry.sql.Text) = '' then qry.SQL.Add(ModifyRecQuery);
  1047. end;
  1048. ukInsert : begin
  1049. qry := FInsertQry;
  1050. if trim(qry.sql.Text) = '' then qry.SQL.Add(InsertRecQuery);
  1051. end;
  1052. ukDelete : begin
  1053. qry := FDeleteQry;
  1054. if trim(qry.sql.Text) = '' then qry.SQL.Add(DeleteRecQuery);
  1055. end;
  1056. end;
  1057. with qry do
  1058. begin
  1059. for x := 0 to Params.Count-1 do with params[x] do if leftstr(name,4)='OLD_' then
  1060. begin
  1061. Fld := self.FieldByName(copy(name,5,length(name)-4));
  1062. AssignFieldValue(Fld,Fld.OldValue);
  1063. end
  1064. else
  1065. begin
  1066. Fld := self.FieldByName(name);
  1067. AssignFieldValue(Fld,Fld.Value);
  1068. end;
  1069. execsql;
  1070. end;
  1071. end;
  1072. Function TSQLQuery.GetCanModify: Boolean;
  1073. begin
  1074. // the test for assigned(FCursor) is needed for the case that the dataset isn't opened
  1075. if assigned(FCursor) and (FCursor.FStatementType = stSelect) then
  1076. Result:= FUpdateable and (not FReadOnly)
  1077. else
  1078. Result := False;
  1079. end;
  1080. function TSQLQuery.GetIndexDefs : TIndexDefs;
  1081. begin
  1082. Result := FIndexDefs;
  1083. end;
  1084. procedure TSQLQuery.SetIndexDefs(AValue : TIndexDefs);
  1085. begin
  1086. FIndexDefs := AValue;
  1087. end;
  1088. procedure TSQLQuery.SetUpdateMode(AValue : TUpdateMode);
  1089. begin
  1090. FUpdateMode := AValue;
  1091. end;
  1092. procedure TSQLQuery.SetSchemaInfo( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string);
  1093. begin
  1094. ReadOnly := True;
  1095. SQL.Clear;
  1096. SQL.Add((DataBase as tsqlconnection).GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern));
  1097. end;
  1098. procedure TSQLQuery.LoadBlobIntoStream(Field: TField;AStream: TStream);
  1099. begin
  1100. (DataBase as tsqlconnection).LoadBlobIntoStream(Field, AStream, FCursor,(Transaction as tsqltransaction));
  1101. end;
  1102. procedure TSQLQuery.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1103. ABlobBuf: PBufBlobField);
  1104. begin
  1105. (DataBase as tsqlconnection).LoadBlobIntoBuffer(FieldDef, ABlobBuf, FCursor,(Transaction as tsqltransaction));
  1106. end;
  1107. function TSQLQuery.GetStatementType : TStatementType;
  1108. begin
  1109. if assigned(FCursor) then Result := FCursor.FStatementType
  1110. else Result := stNone;
  1111. end;
  1112. Procedure TSQLQuery.SetDataSource(AVAlue : TDatasource);
  1113. Var
  1114. DS : TDatasource;
  1115. begin
  1116. DS:=DataSource;
  1117. If (AValue<>DS) then
  1118. begin
  1119. If Assigned(DS) then
  1120. DS.RemoveFreeNotification(Self);
  1121. If Assigned(AValue) then
  1122. begin
  1123. AValue.FreeNotification(Self);
  1124. FMasterLink:=TMasterParamsDataLink.Create(Self);
  1125. FMasterLink.Datasource:=AValue;
  1126. end
  1127. else
  1128. FreeAndNil(FMasterLink);
  1129. end;
  1130. end;
  1131. Function TSQLQuery.GetDataSource : TDatasource;
  1132. begin
  1133. If Assigned(FMasterLink) then
  1134. Result:=FMasterLink.DataSource
  1135. else
  1136. Result:=Nil;
  1137. end;
  1138. procedure TSQLQuery.Notification(AComponent: TComponent; Operation: TOperation);
  1139. begin
  1140. Inherited;
  1141. If (Operation=opRemove) and (AComponent=DataSource) then
  1142. DataSource:=Nil;
  1143. end;
  1144. { TSQLScript }
  1145. procedure TSQLScript.SetScript(const AValue: TStrings);
  1146. begin
  1147. FScript.assign(AValue);
  1148. end;
  1149. procedure TSQLScript.SetDatabase(Value: TDatabase);
  1150. begin
  1151. FDatabase := Value;
  1152. end;
  1153. procedure TSQLScript.SetTransaction(Value: TDBTransaction);
  1154. begin
  1155. FTransaction := Value;
  1156. end;
  1157. procedure TSQLScript.CheckDatabase;
  1158. begin
  1159. If (FDatabase=Nil) then
  1160. DatabaseError(SErrNoDatabaseAvailable,Self)
  1161. end;
  1162. constructor TSQLScript.Create(AOwner: TComponent);
  1163. begin
  1164. inherited Create(AOwner);
  1165. FScript := TStringList.Create;
  1166. FQuery := TSQLQuery.Create(nil);
  1167. end;
  1168. destructor TSQLScript.Destroy;
  1169. begin
  1170. FScript.Free;
  1171. FQuery.Free;
  1172. inherited Destroy;
  1173. end;
  1174. procedure TSQLScript.ExecuteScript;
  1175. var BufStr : String;
  1176. pBufStatStart,
  1177. pBufPos : PChar;
  1178. Statement : String;
  1179. begin
  1180. FQuery.DataBase := FDatabase;
  1181. FQuery.Transaction := FTransaction;
  1182. BufStr := FScript.Text;
  1183. pBufPos := @BufStr[1];
  1184. repeat
  1185. pBufStatStart := pBufPos;
  1186. repeat
  1187. inc(pBufPos);
  1188. until (pBufPos^ = ';') or (pBufPos^ = #0);
  1189. SetLength(statement,pbufpos-pBufStatStart);
  1190. move(pBufStatStart^,Statement[1],pbufpos-pBufStatStart);
  1191. if trim(statement) <> '' then
  1192. begin
  1193. fquery.SQL.Text := Statement;
  1194. fquery.ExecSQL;
  1195. inc(pBufPos);
  1196. end;
  1197. until pBufPos^ = #0;
  1198. end;
  1199. { TSQLCursor }
  1200. constructor TSQLCursor.Create;
  1201. begin
  1202. FBlobStrings := TStringList.Create;
  1203. inherited;
  1204. end;
  1205. destructor TSQLCursor.Destroy;
  1206. begin
  1207. FBlobStrings.Free;
  1208. inherited Destroy;
  1209. end;
  1210. end.