sqldb.pp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828
  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 GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
  54. protected
  55. FConnOptions : TConnOptions;
  56. procedure SetTransaction(Value : TSQLTransaction);virtual;
  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. { TSQLConnector }
  277. TSQLConnector = Class(TSQLConnection)
  278. private
  279. FProxy : TSQLConnection;
  280. FConnectorType: String;
  281. procedure SetConnectorType(const AValue: String);
  282. protected
  283. procedure SetTransaction(Value : TSQLTransaction);override;
  284. procedure DoInternalConnect; override;
  285. procedure DoInternalDisconnect; override;
  286. Procedure CheckProxy;
  287. Procedure CreateProxy; virtual;
  288. Procedure FreeProxy; virtual;
  289. function StrToStatementType(s : string) : TStatementType; override;
  290. function GetAsSQLText(Field : TField) : string; overload; override;
  291. function GetAsSQLText(Param : TParam) : string; overload; override;
  292. function GetHandle : pointer; override;
  293. Function AllocateCursorHandle : TSQLCursor; override;
  294. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
  295. Function AllocateTransactionHandle : TSQLHandle; override;
  296. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
  297. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
  298. function Fetch(cursor : TSQLCursor) : boolean; override;
  299. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
  300. procedure UnPrepareStatement(cursor : TSQLCursor); override;
  301. procedure FreeFldBuffers(cursor : TSQLCursor); override;
  302. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  303. function GetTransactionHandle(trans : TSQLHandle): pointer; override;
  304. function Commit(trans : TSQLHandle) : boolean; override;
  305. function RollBack(trans : TSQLHandle) : boolean; override;
  306. function StartdbTransaction(trans : TSQLHandle; aParams : string) : boolean; override;
  307. procedure CommitRetaining(trans : TSQLHandle); override;
  308. procedure RollBackRetaining(trans : TSQLHandle); override;
  309. procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); override;
  310. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; override;
  311. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); override;
  312. Property Proxy : TSQLConnection Read FProxy;
  313. Published
  314. Property ConnectorType : String Read FConnectorType Write SetConnectorType;
  315. end;
  316. TSQLConnectionClass = Class of TSQLConnection;
  317. { TConnectionDef }
  318. TConnectionDef = Class(TPersistent)
  319. Class Function TypeName : String; virtual;
  320. Class Function ConnectionClass : TSQLConnectionClass; virtual;
  321. Class Function Description : String; virtual;
  322. Procedure ApplyParams(Params : TStrings; AConnection : TSQLConnection); virtual;
  323. end;
  324. TConnectionDefClass = class of TConnectionDef;
  325. Procedure RegisterConnection(Def : TConnectionDefClass);
  326. Procedure UnRegisterConnection(Def : TConnectionDefClass);
  327. Procedure UnRegisterConnection(ConnectionName : String);
  328. Procedure GetConnectionList(List : TSTrings);
  329. implementation
  330. uses dbconst, strutils;
  331. { TSQLConnection }
  332. function TSQLConnection.StrToStatementType(s : string) : TStatementType;
  333. var T : TStatementType;
  334. begin
  335. S:=Lowercase(s);
  336. For t:=stselect to strollback do
  337. if (S=StatementTokens[t]) then
  338. Exit(t);
  339. end;
  340. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  341. begin
  342. if FTransaction<>value then
  343. begin
  344. if Assigned(FTransaction) and FTransaction.Active then
  345. DatabaseError(SErrAssTransaction);
  346. if Assigned(Value) then
  347. Value.Database := Self;
  348. FTransaction := Value;
  349. end;
  350. end;
  351. procedure TSQLConnection.UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string);
  352. begin
  353. // Empty abstract
  354. end;
  355. procedure TSQLConnection.DoInternalConnect;
  356. begin
  357. if (DatabaseName = '') then
  358. DatabaseError(SErrNoDatabaseName,self);
  359. end;
  360. procedure TSQLConnection.DoInternalDisconnect;
  361. begin
  362. end;
  363. destructor TSQLConnection.Destroy;
  364. begin
  365. inherited Destroy;
  366. end;
  367. procedure TSQLConnection.StartTransaction;
  368. begin
  369. if not assigned(Transaction) then
  370. DatabaseError(SErrConnTransactionnSet)
  371. else
  372. Transaction.StartTransaction;
  373. end;
  374. procedure TSQLConnection.EndTransaction;
  375. begin
  376. if not assigned(Transaction) then
  377. DatabaseError(SErrConnTransactionnSet)
  378. else
  379. Transaction.EndTransaction;
  380. end;
  381. Procedure TSQLConnection.ExecuteDirect(SQL: String);
  382. begin
  383. ExecuteDirect(SQL,FTransaction);
  384. end;
  385. Procedure TSQLConnection.ExecuteDirect(SQL: String; ATransaction : TSQLTransaction);
  386. var Cursor : TSQLCursor;
  387. begin
  388. if not assigned(ATransaction) then
  389. DatabaseError(SErrTransactionnSet);
  390. if not Connected then Open;
  391. if not ATransaction.Active then ATransaction.StartTransaction;
  392. try
  393. Cursor := AllocateCursorHandle;
  394. SQL := TrimRight(SQL);
  395. if SQL = '' then
  396. DatabaseError(SErrNoStatement);
  397. Cursor.FStatementType := stNone;
  398. PrepareStatement(cursor,ATransaction,SQL,Nil);
  399. execute(cursor,ATransaction, Nil);
  400. UnPrepareStatement(Cursor);
  401. finally;
  402. DeAllocateCursorHandle(Cursor);
  403. end;
  404. end;
  405. procedure TSQLConnection.GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
  406. var qry : TSQLQuery;
  407. begin
  408. if not assigned(Transaction) then
  409. DatabaseError(SErrConnTransactionnSet);
  410. qry := tsqlquery.Create(nil);
  411. qry.transaction := Transaction;
  412. qry.database := Self;
  413. with qry do
  414. begin
  415. ParseSQL := False;
  416. SetSchemaInfo(SchemaType,SchemaObjectName,'');
  417. open;
  418. List.Clear;
  419. while not eof do
  420. begin
  421. List.Append(fieldbyname(ReturnField).asstring);
  422. Next;
  423. end;
  424. end;
  425. qry.free;
  426. end;
  427. procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
  428. begin
  429. if not systemtables then GetDBInfo(stTables,'','table_name',List)
  430. else GetDBInfo(stSysTables,'','table_name',List);
  431. end;
  432. procedure TSQLConnection.GetProcedureNames(List: TStrings);
  433. begin
  434. GetDBInfo(stProcedures,'','proc_name',List);
  435. end;
  436. procedure TSQLConnection.GetFieldNames(const TableName: string; List: TStrings);
  437. begin
  438. GetDBInfo(stColumns,TableName,'column_name',List);
  439. end;
  440. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  441. begin
  442. if (not assigned(field)) or field.IsNull then Result := 'Null'
  443. else case field.DataType of
  444. ftString : Result := '''' + field.asstring + '''';
  445. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Field.AsDateTime) + '''';
  446. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Field.AsDateTime) + ''''
  447. else
  448. Result := field.asstring;
  449. end; {case}
  450. end;
  451. function TSQLConnection.GetAsSQLText(Param: TParam) : string;
  452. begin
  453. if (not assigned(param)) or param.IsNull then Result := 'Null'
  454. else case param.DataType of
  455. ftString : Result := '''' + param.asstring + '''';
  456. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Param.AsDateTime) + '''';
  457. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Param.AsDateTime) + ''''
  458. else
  459. Result := Param.asstring;
  460. end; {case}
  461. end;
  462. function TSQLConnection.GetHandle: pointer;
  463. begin
  464. Result := nil;
  465. end;
  466. procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
  467. begin
  468. // empty
  469. end;
  470. function TSQLConnection.GetSchemaInfoSQL( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string;
  471. begin
  472. DatabaseError(SMetadataUnavailable);
  473. end;
  474. procedure TSQLConnection.CreateDB;
  475. begin
  476. DatabaseError(SNotSupported);
  477. end;
  478. procedure TSQLConnection.DropDB;
  479. begin
  480. DatabaseError(SNotSupported);
  481. end;
  482. { TSQLTransaction }
  483. procedure TSQLTransaction.EndTransaction;
  484. begin
  485. rollback;
  486. end;
  487. function TSQLTransaction.GetHandle: pointer;
  488. begin
  489. Result := (Database as tsqlconnection).GetTransactionHandle(FTrans);
  490. end;
  491. procedure TSQLTransaction.Commit;
  492. begin
  493. if active then
  494. begin
  495. closedatasets;
  496. if (Database as tsqlconnection).commit(FTrans) then
  497. begin
  498. closeTrans;
  499. FreeAndNil(FTrans);
  500. end;
  501. end;
  502. end;
  503. procedure TSQLTransaction.CommitRetaining;
  504. begin
  505. if active then
  506. (Database as tsqlconnection).commitRetaining(FTrans);
  507. end;
  508. procedure TSQLTransaction.Rollback;
  509. begin
  510. if active then
  511. begin
  512. closedatasets;
  513. if (Database as tsqlconnection).RollBack(FTrans) then
  514. begin
  515. CloseTrans;
  516. FreeAndNil(FTrans);
  517. end;
  518. end;
  519. end;
  520. procedure TSQLTransaction.RollbackRetaining;
  521. begin
  522. if active then
  523. (Database as tsqlconnection).RollBackRetaining(FTrans);
  524. end;
  525. procedure TSQLTransaction.StartTransaction;
  526. var db : TSQLConnection;
  527. begin
  528. if Active then
  529. DatabaseError(SErrTransAlreadyActive);
  530. db := (Database as tsqlconnection);
  531. if Db = nil then
  532. DatabaseError(SErrDatabasenAssigned);
  533. if not Db.Connected then
  534. Db.Open;
  535. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  536. if Db.StartdbTransaction(FTrans,FParams.CommaText) then OpenTrans;
  537. end;
  538. constructor TSQLTransaction.Create(AOwner : TComponent);
  539. begin
  540. inherited Create(AOwner);
  541. FParams := TStringList.Create;
  542. end;
  543. destructor TSQLTransaction.Destroy;
  544. begin
  545. Rollback;
  546. FreeAndNil(FParams);
  547. inherited Destroy;
  548. end;
  549. Procedure TSQLTransaction.SetDatabase(Value : TDatabase);
  550. begin
  551. If Value<>Database then
  552. begin
  553. CheckInactive;
  554. If Assigned(Database) then
  555. with Database as TSqlConnection do
  556. if Transaction = self then Transaction := nil;
  557. inherited SetDatabase(Value);
  558. end;
  559. end;
  560. { TSQLQuery }
  561. procedure TSQLQuery.OnChangeSQL(Sender : TObject);
  562. var ConnOptions : TConnOptions;
  563. begin
  564. UnPrepare;
  565. if (FSQL <> nil) then
  566. begin
  567. if assigned(DataBase) then
  568. ConnOptions := (DataBase as TSQLConnection).ConnOptions
  569. else
  570. ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
  571. Fparams.ParseSQL(FSQL.Text,True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase);
  572. If Assigned(FMasterLink) then
  573. FMasterLink.RefreshParamNames;
  574. end;
  575. end;
  576. procedure TSQLQuery.OnChangeModifySQL(Sender : TObject);
  577. begin
  578. CheckInactive;
  579. end;
  580. Procedure TSQLQuery.SetTransaction(Value : TDBTransaction);
  581. begin
  582. UnPrepare;
  583. inherited;
  584. end;
  585. procedure TSQLQuery.SetDatabase(Value : TDatabase);
  586. var db : tsqlconnection;
  587. begin
  588. if (Database <> Value) then
  589. begin
  590. UnPrepare;
  591. if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
  592. db := value as tsqlconnection;
  593. inherited setdatabase(value);
  594. if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
  595. transaction := Db.Transaction;
  596. OnChangeSQL(Self);
  597. end;
  598. end;
  599. Function TSQLQuery.IsPrepared : Boolean;
  600. begin
  601. Result := Assigned(FCursor) and FCursor.FPrepared;
  602. end;
  603. Function TSQLQuery.AddFilter(SQLstr : string) : string;
  604. begin
  605. if FWhereStartPos = 0 then
  606. SQLstr := SQLstr + ' where (' + Filter + ')'
  607. else if FWhereStopPos > 0 then
  608. system.insert(' and ('+Filter+') ',SQLstr,FWhereStopPos+1)
  609. else
  610. system.insert(' where ('+Filter+') ',SQLstr,FWhereStartPos);
  611. Result := SQLstr;
  612. end;
  613. procedure TSQLQuery.ApplyFilter;
  614. var S : String;
  615. begin
  616. FreeFldBuffers;
  617. (Database as tsqlconnection).UnPrepareStatement(FCursor);
  618. FIsEOF := False;
  619. inherited internalclose;
  620. s := FSQLBuf;
  621. if ServerFiltered then s := AddFilter(s);
  622. (Database as tsqlconnection).PrepareStatement(Fcursor,(transaction as tsqltransaction),S,FParams);
  623. Execute;
  624. inherited InternalOpen;
  625. First;
  626. end;
  627. Procedure TSQLQuery.SetActive (Value : Boolean);
  628. begin
  629. inherited SetActive(Value);
  630. // The query is UnPrepared, so that if a transaction closes all datasets
  631. // they also get unprepared
  632. if not Value and IsPrepared then UnPrepare;
  633. end;
  634. procedure TSQLQuery.SetServerFiltered(Value: Boolean);
  635. begin
  636. if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
  637. if (ServerFiltered <> Value) then
  638. begin
  639. FServerFiltered := Value;
  640. if active then ApplyFilter;
  641. end;
  642. end;
  643. procedure TSQLQuery.SetServerFilterText(const Value: string);
  644. begin
  645. if Value <> ServerFilter then
  646. begin
  647. FServerFilterText := Value;
  648. if active then ApplyFilter;
  649. end;
  650. end;
  651. procedure TSQLQuery.Prepare;
  652. var
  653. db : tsqlconnection;
  654. sqltr : tsqltransaction;
  655. begin
  656. if not IsPrepared then
  657. begin
  658. db := (Database as tsqlconnection);
  659. sqltr := (transaction as tsqltransaction);
  660. if not assigned(Db) then
  661. DatabaseError(SErrDatabasenAssigned);
  662. if not assigned(sqltr) then
  663. DatabaseError(SErrTransactionnSet);
  664. if not Db.Connected then db.Open;
  665. if not sqltr.Active then sqltr.StartTransaction;
  666. // if assigned(fcursor) then FreeAndNil(fcursor);
  667. if not assigned(fcursor) then
  668. FCursor := Db.AllocateCursorHandle;
  669. FSQLBuf := TrimRight(FSQL.Text);
  670. if FSQLBuf = '' then
  671. DatabaseError(SErrNoStatement);
  672. SQLParser(FSQLBuf);
  673. if ServerFiltered then
  674. Db.PrepareStatement(Fcursor,sqltr,AddFilter(FSQLBuf),FParams)
  675. else
  676. Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
  677. if (FCursor.FStatementType = stSelect) then
  678. begin
  679. FCursor.FInitFieldDef := True;
  680. if not ReadOnly then InitUpdates(FSQLBuf);
  681. end;
  682. end;
  683. end;
  684. procedure TSQLQuery.UnPrepare;
  685. begin
  686. CheckInactive;
  687. if IsPrepared then with Database as TSQLConnection do
  688. UnPrepareStatement(FCursor);
  689. end;
  690. procedure TSQLQuery.FreeFldBuffers;
  691. begin
  692. if assigned(FCursor) then (Database as tsqlconnection).FreeFldBuffers(FCursor);
  693. end;
  694. function TSQLQuery.Fetch : boolean;
  695. begin
  696. if not (Fcursor.FStatementType in [stSelect]) then
  697. Exit;
  698. if not FIsEof then FIsEOF := not (Database as tsqlconnection).Fetch(Fcursor);
  699. Result := not FIsEOF;
  700. end;
  701. procedure TSQLQuery.Execute;
  702. begin
  703. If (FParams.Count>0) and Assigned(FMasterLink) then
  704. FMasterLink.CopyParamsFromMaster(False);
  705. (Database as tsqlconnection).execute(Fcursor,Transaction as tsqltransaction, FParams);
  706. end;
  707. function TSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  708. begin
  709. result := (Database as tSQLConnection).LoadField(FCursor,FieldDef,buffer, Createblob)
  710. end;
  711. procedure TSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  712. begin
  713. // not implemented - sql dataset
  714. end;
  715. procedure TSQLQuery.InternalClose;
  716. begin
  717. if StatementType = stSelect then FreeFldBuffers;
  718. // Database and FCursor could be nil, for example if the database is not assigned, and .open is called
  719. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then (database as TSQLconnection).UnPrepareStatement(FCursor);
  720. if DefaultFields then
  721. DestroyFields;
  722. FIsEOF := False;
  723. if assigned(FUpdateQry) then FreeAndNil(FUpdateQry);
  724. if assigned(FInsertQry) then FreeAndNil(FInsertQry);
  725. if assigned(FDeleteQry) then FreeAndNil(FDeleteQry);
  726. // FRecordSize := 0;
  727. inherited internalclose;
  728. end;
  729. procedure TSQLQuery.InternalInitFieldDefs;
  730. begin
  731. if FLoadingFieldDefs then
  732. Exit;
  733. FLoadingFieldDefs := True;
  734. try
  735. FieldDefs.Clear;
  736. (Database as tsqlconnection).AddFieldDefs(fcursor,FieldDefs);
  737. finally
  738. FLoadingFieldDefs := False;
  739. FCursor.FInitFieldDef := false;
  740. end;
  741. end;
  742. procedure TSQLQuery.SQLParser(var ASQL : string);
  743. type TParsePart = (ppStart,ppSelect,ppWhere,ppFrom,ppOrder,ppComment,ppGroup,ppBogus);
  744. Var
  745. PSQL,CurrentP,
  746. PhraseP, PStatementPart : pchar;
  747. S : string;
  748. ParsePart : TParsePart;
  749. StrLength : Integer;
  750. EndOfComment : Boolean;
  751. BracketCount : Integer;
  752. ConnOptions : TConnOptions;
  753. begin
  754. PSQL:=Pchar(ASQL);
  755. ParsePart := ppStart;
  756. CurrentP := PSQL-1;
  757. PhraseP := PSQL;
  758. FWhereStartPos := 0;
  759. FWhereStopPos := 0;
  760. ConnOptions := (DataBase as TSQLConnection).ConnOptions;
  761. repeat
  762. begin
  763. inc(CurrentP);
  764. EndOfComment := SkipComments(CurrentP,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
  765. if EndOfcomment then dec(currentp);
  766. if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;
  767. // skip everything between bracket, since it could be a sub-select, and
  768. // further nothing between brackets could be interesting for the parser.
  769. if currentp^='(' then
  770. begin
  771. inc(currentp);
  772. BracketCount := 0;
  773. while (currentp^ <> #0) and ((currentp^ <> ')') or (BracketCount > 0 )) do
  774. begin
  775. if currentp^ = '(' then inc(bracketcount)
  776. else if currentp^ = ')' then dec(bracketcount);
  777. inc(currentp);
  778. end;
  779. EndOfComment := True;
  780. end;
  781. if EndOfComment or (CurrentP^ in [' ',#13,#10,#9,#0,';']) then
  782. begin
  783. if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
  784. begin
  785. strLength := CurrentP-PhraseP;
  786. Setlength(S,strLength);
  787. if strLength > 0 then Move(PhraseP^,S[1],(strLength));
  788. s := uppercase(s);
  789. case ParsePart of
  790. ppStart : begin
  791. FCursor.FStatementType := (Database as tsqlconnection).StrToStatementType(s);
  792. if FCursor.FStatementType = stSelect then ParsePart := ppSelect
  793. else break;
  794. if not FParseSQL then break;
  795. PStatementPart := CurrentP;
  796. end;
  797. ppSelect : begin
  798. if s = 'FROM' then
  799. begin
  800. ParsePart := ppFrom;
  801. PhraseP := CurrentP;
  802. PStatementPart := CurrentP;
  803. end;
  804. end;
  805. ppFrom : begin
  806. if (s = 'WHERE') or (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  807. begin
  808. if (s = 'WHERE') then
  809. begin
  810. ParsePart := ppWhere;
  811. StrLength := PhraseP-PStatementPart;
  812. end
  813. else if (s = 'GROUP') then
  814. begin
  815. ParsePart := ppGroup;
  816. StrLength := PhraseP-PStatementPart;
  817. end
  818. else if (s = 'ORDER') then
  819. begin
  820. ParsePart := ppOrder;
  821. StrLength := PhraseP-PStatementPart
  822. end
  823. else
  824. begin
  825. ParsePart := ppBogus;
  826. StrLength := CurrentP-PStatementPart;
  827. end;
  828. Setlength(FFromPart,StrLength);
  829. Move(PStatementPart^,FFromPart[1],(StrLength));
  830. FFrompart := trim(FFrompart);
  831. FWhereStartPos := PStatementPart-PSQL+StrLength+1;
  832. PStatementPart := CurrentP;
  833. end;
  834. end;
  835. ppWhere : begin
  836. if (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  837. begin
  838. ParsePart := ppBogus;
  839. FWhereStartPos := PStatementPart-PSQL;
  840. if (s = 'ORDER') or (s = 'GROUP') then
  841. FWhereStopPos := PhraseP-PSQL+1
  842. else
  843. FWhereStopPos := CurrentP-PSQL+1;
  844. end;
  845. end;
  846. end; {case}
  847. end;
  848. PhraseP := CurrentP+1;
  849. end
  850. end;
  851. until CurrentP^=#0;
  852. if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
  853. begin
  854. system.insert('(',ASQL,FWhereStartPos+1);
  855. inc(FWhereStopPos);
  856. system.insert(')',ASQL,FWhereStopPos);
  857. end
  858. end;
  859. procedure TSQLQuery.InitUpdates(ASQL : string);
  860. begin
  861. if pos(',',FFromPart) > 0 then
  862. FUpdateable := False // select-statements from more then one table are not updateable
  863. else
  864. begin
  865. FUpdateable := True;
  866. FTableName := FFromPart;
  867. end;
  868. end;
  869. procedure TSQLQuery.InternalOpen;
  870. procedure InitialiseModifyQuery(var qry : TSQLQuery; aSQL: TSTringList);
  871. begin
  872. qry := TSQLQuery.Create(nil);
  873. with qry do
  874. begin
  875. ParseSQL := False;
  876. DataBase := Self.DataBase;
  877. Transaction := Self.Transaction;
  878. SQL.Assign(aSQL);
  879. end;
  880. end;
  881. var tel, fieldc : integer;
  882. f : TField;
  883. s : string;
  884. IndexFields : TStrings;
  885. begin
  886. try
  887. Prepare;
  888. if FCursor.FStatementType in [stSelect] then
  889. begin
  890. Execute;
  891. // InternalInitFieldDef is only called after a prepare. i.e. not twice if
  892. // a dataset is opened - closed - opened.
  893. if FCursor.FInitFieldDef then InternalInitFieldDefs;
  894. if DefaultFields then
  895. begin
  896. CreateFields;
  897. if FUpdateable then
  898. begin
  899. if FusePrimaryKeyAsKey then
  900. begin
  901. UpdateIndexDefs;
  902. for tel := 0 to indexdefs.count-1 do {with indexdefs[tel] do}
  903. begin
  904. if ixPrimary in indexdefs[tel].options then
  905. begin
  906. // Todo: If there is more then one field in the key, that must be parsed
  907. IndexFields := TStringList.Create;
  908. ExtractStrings([';'],[' '],pchar(indexdefs[tel].fields),IndexFields);
  909. for fieldc := 0 to IndexFields.Count-1 do
  910. begin
  911. F := Findfield(IndexFields[fieldc]);
  912. if F <> nil then
  913. F.ProviderFlags := F.ProviderFlags + [pfInKey];
  914. end;
  915. IndexFields.Free;
  916. end;
  917. end;
  918. end;
  919. end;
  920. end
  921. else
  922. BindFields(True);
  923. if FUpdateable then
  924. begin
  925. InitialiseModifyQuery(FDeleteQry,FDeleteSQL);
  926. InitialiseModifyQuery(FUpdateQry,FUpdateSQL);
  927. InitialiseModifyQuery(FInsertQry,FInsertSQL);
  928. end;
  929. end
  930. else
  931. DatabaseError(SErrNoSelectStatement,Self);
  932. except
  933. on E:Exception do
  934. raise;
  935. end;
  936. inherited InternalOpen;
  937. end;
  938. // public part
  939. procedure TSQLQuery.ExecSQL;
  940. begin
  941. try
  942. Prepare;
  943. Execute;
  944. finally
  945. // FCursor has to be assigned, or else the prepare went wrong before PrepareStatment was
  946. // called, so UnPrepareStatement shoudn't be called either
  947. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then (database as TSQLConnection).UnPrepareStatement(Fcursor);
  948. end;
  949. end;
  950. constructor TSQLQuery.Create(AOwner : TComponent);
  951. begin
  952. inherited Create(AOwner);
  953. FParams := TParams.create(self);
  954. FSQL := TStringList.Create;
  955. FSQL.OnChange := @OnChangeSQL;
  956. FUpdateSQL := TStringList.Create;
  957. FUpdateSQL.OnChange := @OnChangeModifySQL;
  958. FInsertSQL := TStringList.Create;
  959. FInsertSQL.OnChange := @OnChangeModifySQL;
  960. FDeleteSQL := TStringList.Create;
  961. FDeleteSQL.OnChange := @OnChangeModifySQL;
  962. FIndexDefs := TIndexDefs.Create(Self);
  963. FReadOnly := false;
  964. FParseSQL := True;
  965. FServerFiltered := False;
  966. FServerFilterText := '';
  967. // Delphi has upWhereAll as default, but since strings and oldvalue's don't work yet
  968. // (variants) set it to upWhereKeyOnly
  969. FUpdateMode := upWhereKeyOnly;
  970. FUsePrimaryKeyAsKey := True;
  971. end;
  972. destructor TSQLQuery.Destroy;
  973. begin
  974. if Active then Close;
  975. UnPrepare;
  976. if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
  977. FreeAndNil(FMasterLink);
  978. FreeAndNil(FParams);
  979. FreeAndNil(FSQL);
  980. FreeAndNil(FInsertSQL);
  981. FreeAndNil(FDeleteSQL);
  982. FreeAndNil(FUpdateSQL);
  983. FreeAndNil(FIndexDefs);
  984. inherited Destroy;
  985. end;
  986. procedure TSQLQuery.SetReadOnly(AValue : Boolean);
  987. begin
  988. CheckInactive;
  989. if not AValue then
  990. begin
  991. if FParseSQL then FReadOnly := False
  992. else DatabaseErrorFmt(SNoParseSQL,['Updating ']);
  993. end
  994. else FReadOnly := True;
  995. end;
  996. procedure TSQLQuery.SetParseSQL(AValue : Boolean);
  997. begin
  998. CheckInactive;
  999. if not AValue then
  1000. begin
  1001. FReadOnly := True;
  1002. FServerFiltered := False;
  1003. FParseSQL := False;
  1004. end
  1005. else
  1006. FParseSQL := True;
  1007. end;
  1008. procedure TSQLQuery.SetUsePrimaryKeyAsKey(AValue : Boolean);
  1009. begin
  1010. if not Active then FusePrimaryKeyAsKey := AValue
  1011. else
  1012. begin
  1013. // Just temporary, this should be possible in the future
  1014. DatabaseError(SActiveDataset);
  1015. end;
  1016. end;
  1017. Procedure TSQLQuery.UpdateIndexDefs;
  1018. begin
  1019. if assigned(DataBase) then
  1020. (DataBase as TSQLConnection).UpdateIndexDefs(FIndexDefs,FTableName);
  1021. end;
  1022. Procedure TSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
  1023. procedure UpdateWherePart(var sql_where : string;x : integer);
  1024. begin
  1025. if (pfInKey in Fields[x].ProviderFlags) or
  1026. ((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
  1027. ((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
  1028. sql_where := sql_where + '(' + fields[x].FieldName + '= :OLD_' + fields[x].FieldName + ') and ';
  1029. end;
  1030. function ModifyRecQuery : string;
  1031. var x : integer;
  1032. sql_set : string;
  1033. sql_where : string;
  1034. begin
  1035. sql_set := '';
  1036. sql_where := '';
  1037. for x := 0 to Fields.Count -1 do
  1038. begin
  1039. UpdateWherePart(sql_where,x);
  1040. if (pfInUpdate in Fields[x].ProviderFlags) then
  1041. sql_set := sql_set + fields[x].FieldName + '=:' + fields[x].FieldName + ',';
  1042. end;
  1043. if length(sql_set) = 0 then DatabaseError(sNoUpdateFields,self);
  1044. setlength(sql_set,length(sql_set)-1);
  1045. if length(sql_where) = 0 then DatabaseError(sNoWhereFields,self);
  1046. setlength(sql_where,length(sql_where)-5);
  1047. result := 'update ' + FTableName + ' set ' + sql_set + ' where ' + sql_where;
  1048. end;
  1049. function InsertRecQuery : string;
  1050. var x : integer;
  1051. sql_fields : string;
  1052. sql_values : string;
  1053. begin
  1054. sql_fields := '';
  1055. sql_values := '';
  1056. for x := 0 to Fields.Count -1 do
  1057. begin
  1058. if (not fields[x].IsNull) and (pfInUpdate in Fields[x].ProviderFlags) then
  1059. begin
  1060. sql_fields := sql_fields + fields[x].FieldName + ',';
  1061. sql_values := sql_values + ':' + fields[x].FieldName + ',';
  1062. end;
  1063. end;
  1064. if length(sql_fields) = 0 then DatabaseError(sNoUpdateFields,self);
  1065. setlength(sql_fields,length(sql_fields)-1);
  1066. setlength(sql_values,length(sql_values)-1);
  1067. result := 'insert into ' + FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
  1068. end;
  1069. function DeleteRecQuery : string;
  1070. var x : integer;
  1071. sql_where : string;
  1072. begin
  1073. sql_where := '';
  1074. for x := 0 to Fields.Count -1 do
  1075. UpdateWherePart(sql_where,x);
  1076. if length(sql_where) = 0 then DatabaseError(sNoWhereFields,self);
  1077. setlength(sql_where,length(sql_where)-5);
  1078. result := 'delete from ' + FTableName + ' where ' + sql_where;
  1079. end;
  1080. var qry : tsqlquery;
  1081. x : integer;
  1082. Fld : TField;
  1083. begin
  1084. case UpdateKind of
  1085. ukModify : begin
  1086. qry := FUpdateQry;
  1087. if trim(qry.sql.Text) = '' then qry.SQL.Add(ModifyRecQuery);
  1088. end;
  1089. ukInsert : begin
  1090. qry := FInsertQry;
  1091. if trim(qry.sql.Text) = '' then qry.SQL.Add(InsertRecQuery);
  1092. end;
  1093. ukDelete : begin
  1094. qry := FDeleteQry;
  1095. if trim(qry.sql.Text) = '' then qry.SQL.Add(DeleteRecQuery);
  1096. end;
  1097. end;
  1098. with qry do
  1099. begin
  1100. for x := 0 to Params.Count-1 do with params[x] do if leftstr(name,4)='OLD_' then
  1101. begin
  1102. Fld := self.FieldByName(copy(name,5,length(name)-4));
  1103. AssignFieldValue(Fld,Fld.OldValue);
  1104. end
  1105. else
  1106. begin
  1107. Fld := self.FieldByName(name);
  1108. AssignFieldValue(Fld,Fld.Value);
  1109. end;
  1110. execsql;
  1111. end;
  1112. end;
  1113. Function TSQLQuery.GetCanModify: Boolean;
  1114. begin
  1115. // the test for assigned(FCursor) is needed for the case that the dataset isn't opened
  1116. if assigned(FCursor) and (FCursor.FStatementType = stSelect) then
  1117. Result:= FUpdateable and (not FReadOnly)
  1118. else
  1119. Result := False;
  1120. end;
  1121. function TSQLQuery.GetIndexDefs : TIndexDefs;
  1122. begin
  1123. Result := FIndexDefs;
  1124. end;
  1125. procedure TSQLQuery.SetIndexDefs(AValue : TIndexDefs);
  1126. begin
  1127. FIndexDefs := AValue;
  1128. end;
  1129. procedure TSQLQuery.SetUpdateMode(AValue : TUpdateMode);
  1130. begin
  1131. FUpdateMode := AValue;
  1132. end;
  1133. procedure TSQLQuery.SetSchemaInfo( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string);
  1134. begin
  1135. ReadOnly := True;
  1136. SQL.Clear;
  1137. SQL.Add((DataBase as tsqlconnection).GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern));
  1138. end;
  1139. procedure TSQLQuery.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1140. ABlobBuf: PBufBlobField);
  1141. begin
  1142. (DataBase as tsqlconnection).LoadBlobIntoBuffer(FieldDef, ABlobBuf, FCursor,(Transaction as tsqltransaction));
  1143. end;
  1144. function TSQLQuery.GetStatementType : TStatementType;
  1145. begin
  1146. if assigned(FCursor) then Result := FCursor.FStatementType
  1147. else Result := stNone;
  1148. end;
  1149. Procedure TSQLQuery.SetDataSource(AVAlue : TDatasource);
  1150. Var
  1151. DS : TDatasource;
  1152. begin
  1153. DS:=DataSource;
  1154. If (AValue<>DS) then
  1155. begin
  1156. If Assigned(DS) then
  1157. DS.RemoveFreeNotification(Self);
  1158. If Assigned(AValue) then
  1159. begin
  1160. AValue.FreeNotification(Self);
  1161. FMasterLink:=TMasterParamsDataLink.Create(Self);
  1162. FMasterLink.Datasource:=AValue;
  1163. end
  1164. else
  1165. FreeAndNil(FMasterLink);
  1166. end;
  1167. end;
  1168. Function TSQLQuery.GetDataSource : TDatasource;
  1169. begin
  1170. If Assigned(FMasterLink) then
  1171. Result:=FMasterLink.DataSource
  1172. else
  1173. Result:=Nil;
  1174. end;
  1175. procedure TSQLQuery.Notification(AComponent: TComponent; Operation: TOperation);
  1176. begin
  1177. Inherited;
  1178. If (Operation=opRemove) and (AComponent=DataSource) then
  1179. DataSource:=Nil;
  1180. end;
  1181. { TSQLScript }
  1182. procedure TSQLScript.SetScript(const AValue: TStrings);
  1183. begin
  1184. FScript.assign(AValue);
  1185. end;
  1186. procedure TSQLScript.SetDatabase(Value: TDatabase);
  1187. begin
  1188. FDatabase := Value;
  1189. end;
  1190. procedure TSQLScript.SetTransaction(Value: TDBTransaction);
  1191. begin
  1192. FTransaction := Value;
  1193. end;
  1194. procedure TSQLScript.CheckDatabase;
  1195. begin
  1196. If (FDatabase=Nil) then
  1197. DatabaseError(SErrNoDatabaseAvailable,Self)
  1198. end;
  1199. constructor TSQLScript.Create(AOwner: TComponent);
  1200. begin
  1201. inherited Create(AOwner);
  1202. FScript := TStringList.Create;
  1203. FQuery := TSQLQuery.Create(nil);
  1204. end;
  1205. destructor TSQLScript.Destroy;
  1206. begin
  1207. FScript.Free;
  1208. FQuery.Free;
  1209. inherited Destroy;
  1210. end;
  1211. procedure TSQLScript.ExecuteScript;
  1212. var BufStr : String;
  1213. pBufStatStart,
  1214. pBufPos : PChar;
  1215. Statement : String;
  1216. begin
  1217. FQuery.DataBase := FDatabase;
  1218. FQuery.Transaction := FTransaction;
  1219. BufStr := FScript.Text;
  1220. pBufPos := @BufStr[1];
  1221. repeat
  1222. pBufStatStart := pBufPos;
  1223. repeat
  1224. inc(pBufPos);
  1225. until (pBufPos^ = ';') or (pBufPos^ = #0);
  1226. SetLength(statement,pbufpos-pBufStatStart);
  1227. move(pBufStatStart^,Statement[1],pbufpos-pBufStatStart);
  1228. if trim(statement) <> '' then
  1229. begin
  1230. fquery.SQL.Text := Statement;
  1231. fquery.ExecSQL;
  1232. inc(pBufPos);
  1233. end;
  1234. until pBufPos^ = #0;
  1235. end;
  1236. { Connection definitions }
  1237. Var
  1238. ConnDefs : TStringList;
  1239. Procedure CheckDefs;
  1240. begin
  1241. If (ConnDefs=Nil) then
  1242. begin
  1243. ConnDefs:=TStringList.Create;
  1244. ConnDefs.Sorted:=True;
  1245. ConnDefs.Duplicates:=dupError;
  1246. end;
  1247. end;
  1248. Procedure DoneDefs;
  1249. Var
  1250. I : Integer;
  1251. begin
  1252. If Assigned(ConnDefs) then
  1253. begin
  1254. For I:=ConnDefs.Count-1 downto 0 do
  1255. begin
  1256. ConnDefs.Objects[i].Free;
  1257. ConnDefs.Delete(I);
  1258. end;
  1259. FreeAndNil(ConnDefs);
  1260. end;
  1261. end;
  1262. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  1263. Var
  1264. I : Integer;
  1265. begin
  1266. CheckDefs;
  1267. I:=ConnDefs.IndexOf(ConnectorName);
  1268. If (I<>-1) then
  1269. Result:=TConnectionDef(ConnDefs.Objects[i])
  1270. else
  1271. Result:=Nil;
  1272. end;
  1273. procedure RegisterConnection(Def: TConnectionDefClass);
  1274. Var
  1275. I : Integer;
  1276. begin
  1277. CheckDefs;
  1278. I:=ConnDefs.IndexOf(Def.TypeName);
  1279. If (I=-1) then
  1280. ConnDefs.AddObject(Def.TypeName,Def.Create)
  1281. else
  1282. begin
  1283. ConnDefs.Objects[I].Free;
  1284. ConnDefs.Objects[I]:=Def.Create;
  1285. end;
  1286. end;
  1287. procedure UnRegisterConnection(Def: TConnectionDefClass);
  1288. begin
  1289. UnRegisterConnection(Def.TypeName);
  1290. end;
  1291. procedure UnRegisterConnection(ConnectionName: String);
  1292. Var
  1293. I : Integer;
  1294. begin
  1295. if (ConnDefs<>Nil) then
  1296. begin
  1297. I:=ConnDefs.IndexOf(ConnectionName);
  1298. If (I<>-1) then
  1299. begin
  1300. ConnDefs.Objects[I].Free;
  1301. ConnDefs.Delete(I);
  1302. end;
  1303. end;
  1304. end;
  1305. procedure GetConnectionList(List: TSTrings);
  1306. begin
  1307. CheckDefs;
  1308. List.Text:=ConnDefs.Text;
  1309. end;
  1310. { TSQLConnector }
  1311. procedure TSQLConnector.SetConnectorType(const AValue: String);
  1312. begin
  1313. if FConnectorType<>AValue then
  1314. begin
  1315. CheckDisconnected;
  1316. If Assigned(FProxy) then
  1317. FreeProxy;
  1318. FConnectorType:=AValue;
  1319. end;
  1320. end;
  1321. procedure TSQLConnector.SetTransaction(Value: TSQLTransaction);
  1322. begin
  1323. inherited SetTransaction(Value);
  1324. If Assigned(FProxy) and (FProxy.Transaction<>Value) then
  1325. FProxy.Transaction:=Value;
  1326. end;
  1327. procedure TSQLConnector.DoInternalConnect;
  1328. Var
  1329. D : TConnectionDef;
  1330. begin
  1331. inherited DoInternalConnect;
  1332. CreateProxy;
  1333. FProxy.DatabaseName:=Self.DatabaseName;
  1334. FProxy.HostName:=Self.HostName;
  1335. FProxy.UserName:=Self.UserName;
  1336. FProxy.Password:=Self.Password;
  1337. FProxy.Transaction:=Self.Transaction;
  1338. D:=GetConnectionDef(ConnectorType);
  1339. D.ApplyParams(Params,FProxy);
  1340. FProxy.Connected:=True;
  1341. end;
  1342. procedure TSQLConnector.DoInternalDisconnect;
  1343. begin
  1344. FProxy.Connected:=False;
  1345. inherited DoInternalDisconnect;
  1346. end;
  1347. procedure TSQLConnector.CheckProxy;
  1348. begin
  1349. If (FProxy=Nil) then
  1350. CreateProxy;
  1351. end;
  1352. procedure TSQLConnector.CreateProxy;
  1353. Var
  1354. D : TConnectionDef;
  1355. begin
  1356. D:=GetConnectionDef(ConnectorType);
  1357. If (D=Nil) then
  1358. DatabaseErrorFmt(SErrUnknownConnectorType,[ConnectorType],Self);
  1359. FProxy:=D.ConnectionClass.Create(Self);
  1360. end;
  1361. procedure TSQLConnector.FreeProxy;
  1362. begin
  1363. FProxy.Connected:=False;
  1364. FreeAndNil(FProxy);
  1365. end;
  1366. function TSQLConnector.StrToStatementType(s: string): TStatementType;
  1367. begin
  1368. CheckProxy;
  1369. Result:=FProxy.StrToStatementType(s);
  1370. end;
  1371. function TSQLConnector.GetAsSQLText(Field: TField): string;
  1372. begin
  1373. CheckProxy;
  1374. Result:=FProxy.GetAsSQLText(Field);
  1375. end;
  1376. function TSQLConnector.GetAsSQLText(Param: TParam): string;
  1377. begin
  1378. CheckProxy;
  1379. Result:=FProxy.GetAsSQLText(Param);
  1380. end;
  1381. function TSQLConnector.GetHandle: pointer;
  1382. begin
  1383. CheckProxy;
  1384. Result:=FProxy.GetHandle;
  1385. end;
  1386. function TSQLConnector.AllocateCursorHandle: TSQLCursor;
  1387. begin
  1388. CheckProxy;
  1389. Result:=FProxy.AllocateCursorHandle;
  1390. end;
  1391. procedure TSQLConnector.DeAllocateCursorHandle(var cursor: TSQLCursor);
  1392. begin
  1393. CheckProxy;
  1394. FProxy.DeAllocateCursorHandle(cursor);
  1395. end;
  1396. function TSQLConnector.AllocateTransactionHandle: TSQLHandle;
  1397. begin
  1398. CheckProxy;
  1399. Result:=FProxy.AllocateTransactionHandle;
  1400. end;
  1401. procedure TSQLConnector.PrepareStatement(cursor: TSQLCursor;
  1402. ATransaction: TSQLTransaction; buf: string; AParams: TParams);
  1403. begin
  1404. CheckProxy;
  1405. FProxy.PrepareStatement(cursor, ATransaction, buf, AParams);
  1406. end;
  1407. procedure TSQLConnector.Execute(cursor: TSQLCursor;
  1408. atransaction: tSQLtransaction; AParams: TParams);
  1409. begin
  1410. CheckProxy;
  1411. FProxy.Execute(cursor, atransaction, AParams);
  1412. end;
  1413. function TSQLConnector.Fetch(cursor: TSQLCursor): boolean;
  1414. begin
  1415. CheckProxy;
  1416. Result:=FProxy.Fetch(cursor);
  1417. end;
  1418. procedure TSQLConnector.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TfieldDefs
  1419. );
  1420. begin
  1421. CheckProxy;
  1422. FProxy.AddFieldDefs(cursor, FieldDefs);
  1423. end;
  1424. procedure TSQLConnector.UnPrepareStatement(cursor: TSQLCursor);
  1425. begin
  1426. CheckProxy;
  1427. FProxy.UnPrepareStatement(cursor);
  1428. end;
  1429. procedure TSQLConnector.FreeFldBuffers(cursor: TSQLCursor);
  1430. begin
  1431. CheckProxy;
  1432. FProxy.FreeFldBuffers(cursor);
  1433. end;
  1434. function TSQLConnector.LoadField(cursor: TSQLCursor; FieldDef: TfieldDef;
  1435. buffer: pointer; out CreateBlob: boolean): boolean;
  1436. begin
  1437. CheckProxy;
  1438. Result:=FProxy.LoadField(cursor, FieldDef, buffer, CreateBlob);
  1439. end;
  1440. function TSQLConnector.GetTransactionHandle(trans: TSQLHandle): pointer;
  1441. begin
  1442. CheckProxy;
  1443. Result:=FProxy.GetTransactionHandle(trans);
  1444. end;
  1445. function TSQLConnector.Commit(trans: TSQLHandle): boolean;
  1446. begin
  1447. CheckProxy;
  1448. Result:=FProxy.Commit(trans);
  1449. end;
  1450. function TSQLConnector.RollBack(trans: TSQLHandle): boolean;
  1451. begin
  1452. CheckProxy;
  1453. Result:=FProxy.RollBack(trans);
  1454. end;
  1455. function TSQLConnector.StartdbTransaction(trans: TSQLHandle; aParams: string
  1456. ): boolean;
  1457. begin
  1458. CheckProxy;
  1459. Result:=FProxy.StartdbTransaction(trans, aParams);
  1460. end;
  1461. procedure TSQLConnector.CommitRetaining(trans: TSQLHandle);
  1462. begin
  1463. CheckProxy;
  1464. FProxy.CommitRetaining(trans);
  1465. end;
  1466. procedure TSQLConnector.RollBackRetaining(trans: TSQLHandle);
  1467. begin
  1468. CheckProxy;
  1469. FProxy.RollBackRetaining(trans);
  1470. end;
  1471. procedure TSQLConnector.UpdateIndexDefs(var IndexDefs: TIndexDefs;
  1472. TableName: string);
  1473. begin
  1474. CheckProxy;
  1475. FProxy.UpdateIndexDefs(IndexDefs, TableName);
  1476. end;
  1477. function TSQLConnector.GetSchemaInfoSQL(SchemaType: TSchemaType;
  1478. SchemaObjectName, SchemaPattern: string): string;
  1479. begin
  1480. CheckProxy;
  1481. Result:=FProxy.GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern
  1482. );
  1483. end;
  1484. procedure TSQLConnector.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1485. ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction: TSQLTransaction);
  1486. begin
  1487. CheckProxy;
  1488. FProxy.LoadBlobIntoBuffer(FieldDef, ABlobBuf, cursor, ATransaction);
  1489. end;
  1490. { TConnectionDef }
  1491. class function TConnectionDef.TypeName: String;
  1492. begin
  1493. Result:='';
  1494. end;
  1495. class function TConnectionDef.ConnectionClass: TSQLConnectionClass;
  1496. begin
  1497. Result:=Nil;
  1498. end;
  1499. class function TConnectionDef.Description: String;
  1500. begin
  1501. Result:='';
  1502. end;
  1503. procedure TConnectionDef.ApplyParams(Params: TStrings;
  1504. AConnection: TSQLConnection);
  1505. begin
  1506. AConnection.Params.Assign(Params);
  1507. end;
  1508. Initialization
  1509. Finalization
  1510. DoneDefs;
  1511. end.