sqldb.pp 40 KB

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