sqldb.pp 39 KB

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