sqldb.pp 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075
  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, sqlscript;
  16. type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages);
  17. TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat,sqQuoteFieldnames);
  18. TConnOptions= set of TConnOption;
  19. TRowsCount = LargeInt;
  20. type
  21. TSQLConnection = class;
  22. TSQLTransaction = class;
  23. TCustomSQLQuery = class;
  24. TSQLQuery = class;
  25. TSQLScript = class;
  26. TStatementType = (stNone, stSelect, stInsert, stUpdate, stDelete,
  27. stDDL, stGetSegment, stPutSegment, stExecProcedure,
  28. stStartTrans, stCommit, stRollback, stSelectForUpd);
  29. TSQLHandle = Class(TObject)
  30. end;
  31. { TSQLCursor }
  32. TSQLCursor = Class(TSQLHandle)
  33. public
  34. FPrepared : Boolean;
  35. FInitFieldDef : Boolean;
  36. FStatementType : TStatementType;
  37. FSchemaType : TSchemaType;
  38. end;
  39. const
  40. StatementTokens : Array[TStatementType] of string = ('(none)', 'select',
  41. 'insert', 'update', 'delete',
  42. 'create', 'get', 'put', 'execute',
  43. 'start','commit','rollback', '?'
  44. );
  45. type
  46. { TServerIndexDefs }
  47. TServerIndexDefs = class(TIndexDefs)
  48. Private
  49. public
  50. constructor Create(ADataSet: TDataSet); override;
  51. procedure Update; override;
  52. end;
  53. { TSQLConnection }
  54. type
  55. { TSQLConnection }
  56. TSQLConnection = class (TDatabase)
  57. private
  58. FPassword : string;
  59. FTransaction : TSQLTransaction;
  60. FUserName : string;
  61. FHostName : string;
  62. FCharSet : string;
  63. FRole : String;
  64. FSQLServerFormatSettings : TFormatSettings;
  65. function GetPort: cardinal;
  66. procedure Setport(const AValue: cardinal);
  67. protected
  68. FConnOptions : TConnOptions;
  69. procedure GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
  70. procedure SetTransaction(Value : TSQLTransaction);virtual;
  71. function StrToStatementType(s : string) : TStatementType; virtual;
  72. procedure DoInternalConnect; override;
  73. procedure DoInternalDisconnect; override;
  74. function GetAsSQLText(Field : TField) : string; overload; virtual;
  75. function GetAsSQLText(Param : TParam) : string; overload; virtual;
  76. function GetHandle : pointer; virtual; virtual;
  77. Function AllocateCursorHandle : TSQLCursor; virtual; abstract;
  78. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); virtual; abstract;
  79. Function AllocateTransactionHandle : TSQLHandle; virtual; abstract;
  80. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); virtual; abstract;
  81. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
  82. function Fetch(cursor : TSQLCursor) : boolean; virtual; abstract;
  83. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); virtual; abstract;
  84. procedure UnPrepareStatement(cursor : TSQLCursor); virtual; abstract;
  85. procedure FreeFldBuffers(cursor : TSQLCursor); virtual;
  86. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; virtual; abstract;
  87. function GetTransactionHandle(trans : TSQLHandle): pointer; virtual; abstract;
  88. function Commit(trans : TSQLHandle) : boolean; virtual; abstract;
  89. function RollBack(trans : TSQLHandle) : boolean; virtual; abstract;
  90. function StartdbTransaction(trans : TSQLHandle; aParams : string) : boolean; virtual; abstract;
  91. procedure CommitRetaining(trans : TSQLHandle); virtual; abstract;
  92. procedure RollBackRetaining(trans : TSQLHandle); virtual; abstract;
  93. procedure UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string); virtual;
  94. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; virtual;
  95. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); virtual; abstract;
  96. function RowsAffected(cursor: TSQLCursor): TRowsCount; virtual;
  97. property port: cardinal read GetPort write Setport;
  98. public
  99. property Handle: Pointer read GetHandle;
  100. constructor Create(AOwner: TComponent); override;
  101. destructor Destroy; override;
  102. procedure StartTransaction; override;
  103. procedure EndTransaction; override;
  104. property ConnOptions: TConnOptions read FConnOptions;
  105. procedure ExecuteDirect(SQL : String); overload; virtual;
  106. procedure ExecuteDirect(SQL : String; ATransaction : TSQLTransaction); overload; virtual;
  107. procedure GetTableNames(List : TStrings; SystemTables : Boolean = false); virtual;
  108. procedure GetProcedureNames(List : TStrings); virtual;
  109. procedure GetFieldNames(const TableName : string; List : TStrings); virtual;
  110. procedure CreateDB; virtual;
  111. procedure DropDB; virtual;
  112. published
  113. property Password : string read FPassword write FPassword;
  114. property Transaction : TSQLTransaction read FTransaction write SetTransaction;
  115. property UserName : string read FUserName write FUserName;
  116. property CharSet : string read FCharSet write FCharSet;
  117. property HostName : string Read FHostName Write FHostName;
  118. property Connected;
  119. Property Role : String read FRole write FRole;
  120. property DatabaseName;
  121. property KeepConnection;
  122. property LoginPrompt;
  123. property Params;
  124. property OnLogin;
  125. end;
  126. { TSQLTransaction }
  127. TCommitRollbackAction = (caNone, caCommit, caCommitRetaining, caRollback,
  128. caRollbackRetaining);
  129. TSQLTransaction = class (TDBTransaction)
  130. private
  131. FTrans : TSQLHandle;
  132. FAction : TCommitRollbackAction;
  133. FParams : TStringList;
  134. procedure SetParams(const AValue: TStringList);
  135. protected
  136. function GetHandle : Pointer; virtual;
  137. Procedure SetDatabase (Value : TDatabase); override;
  138. public
  139. procedure Commit; virtual;
  140. procedure CommitRetaining; virtual;
  141. procedure Rollback; virtual;
  142. procedure RollbackRetaining; virtual;
  143. procedure StartTransaction; override;
  144. constructor Create(AOwner : TComponent); override;
  145. destructor Destroy; override;
  146. property Handle: Pointer read GetHandle;
  147. procedure EndTransaction; override;
  148. published
  149. property Action : TCommitRollbackAction read FAction write FAction;
  150. property Database;
  151. property Params : TStringList read FParams write SetParams;
  152. end;
  153. { TCustomSQLQuery }
  154. TCustomSQLQuery = class (Tbufdataset)
  155. private
  156. FCursor : TSQLCursor;
  157. FUpdateable : boolean;
  158. FTableName : string;
  159. FSQL : TStringList;
  160. FUpdateSQL,
  161. FInsertSQL,
  162. FDeleteSQL : TStringList;
  163. FIsEOF : boolean;
  164. FLoadingFieldDefs : boolean;
  165. FReadOnly : boolean;
  166. FUpdateMode : TUpdateMode;
  167. FParams : TParams;
  168. FusePrimaryKeyAsKey : Boolean;
  169. FSQLBuf : String;
  170. FWhereStartPos : integer;
  171. FWhereStopPos : integer;
  172. FParseSQL : boolean;
  173. FMasterLink : TMasterParamsDatalink;
  174. // FSchemaInfo : TSchemaInfo;
  175. FServerFilterText : string;
  176. FServerFiltered : Boolean;
  177. FServerIndexDefs : TServerIndexDefs;
  178. // Used by SetSchemaType
  179. FSchemaType : TSchemaType;
  180. FSchemaObjectName : string;
  181. FSchemaPattern : string;
  182. FUpdateQry,
  183. FDeleteQry,
  184. FInsertQry : TCustomSQLQuery;
  185. procedure FreeFldBuffers;
  186. function GetServerIndexDefs: TServerIndexDefs;
  187. function GetStatementType : TStatementType;
  188. procedure SetDeleteSQL(const AValue: TStringlist);
  189. procedure SetInsertSQL(const AValue: TStringlist);
  190. procedure SetReadOnly(AValue : Boolean);
  191. procedure SetParseSQL(AValue : Boolean);
  192. procedure SetSQL(const AValue: TStringlist);
  193. procedure SetUpdateSQL(const AValue: TStringlist);
  194. procedure SetUsePrimaryKeyAsKey(AValue : Boolean);
  195. procedure SetUpdateMode(AValue : TUpdateMode);
  196. procedure OnChangeSQL(Sender : TObject);
  197. procedure OnChangeModifySQL(Sender : TObject);
  198. procedure Execute;
  199. Function SQLParser(var ASQL : string) : TStatementType;
  200. procedure ApplyFilter;
  201. Function AddFilter(SQLstr : string) : string;
  202. protected
  203. // abstract & virtual methods of TBufDataset
  204. function Fetch : boolean; override;
  205. function LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  206. // abstract & virtual methods of TDataset
  207. procedure UpdateServerIndexDefs; virtual;
  208. procedure SetDatabase(Value : TDatabase); override;
  209. Procedure SetTransaction(Value : TDBTransaction); override;
  210. procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
  211. procedure InternalClose; override;
  212. procedure InternalInitFieldDefs; override;
  213. procedure InternalOpen; override;
  214. function GetCanModify: Boolean; override;
  215. procedure ApplyRecUpdate(UpdateKind : TUpdateKind); override;
  216. Function IsPrepared : Boolean; virtual;
  217. Procedure SetActive (Value : Boolean); override;
  218. procedure SetServerFiltered(Value: Boolean); virtual;
  219. procedure SetServerFilterText(const Value: string); virtual;
  220. Function GetDataSource : TDatasource; override;
  221. Procedure SetDataSource(AValue : TDatasource);
  222. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField); override;
  223. procedure BeforeRefreshOpenCursor; override;
  224. public
  225. procedure Prepare; virtual;
  226. procedure UnPrepare; virtual;
  227. procedure ExecSQL; virtual;
  228. constructor Create(AOwner : TComponent); override;
  229. destructor Destroy; override;
  230. procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
  231. property Prepared : boolean read IsPrepared;
  232. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  233. function RowsAffected: TRowsCount; virtual;
  234. protected
  235. // redeclared data set properties
  236. property Active;
  237. property Filter;
  238. property Filtered;
  239. // property FilterOptions;
  240. property BeforeOpen;
  241. property AfterOpen;
  242. property BeforeClose;
  243. property AfterClose;
  244. property BeforeInsert;
  245. property AfterInsert;
  246. property BeforeEdit;
  247. property AfterEdit;
  248. property BeforePost;
  249. property AfterPost;
  250. property BeforeCancel;
  251. property AfterCancel;
  252. property BeforeDelete;
  253. property AfterDelete;
  254. property BeforeScroll;
  255. property AfterScroll;
  256. property OnCalcFields;
  257. property OnDeleteError;
  258. property OnEditError;
  259. property OnFilterRecord;
  260. property OnNewRecord;
  261. property OnPostError;
  262. property AutoCalcFields;
  263. property Database;
  264. // protected
  265. property SchemaType : TSchemaType read FSchemaType default stNoSchema;
  266. property Transaction;
  267. property ReadOnly : Boolean read FReadOnly write SetReadOnly;
  268. property SQL : TStringlist read FSQL write SetSQL;
  269. property UpdateSQL : TStringlist read FUpdateSQL write SetUpdateSQL;
  270. property InsertSQL : TStringlist read FInsertSQL write SetInsertSQL;
  271. property DeleteSQL : TStringlist read FDeleteSQL write SetDeleteSQL;
  272. property Params : TParams read FParams write FParams;
  273. property UpdateMode : TUpdateMode read FUpdateMode write SetUpdateMode default upWhereKeyOnly;
  274. property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey default true;
  275. property StatementType : TStatementType read GetStatementType;
  276. property ParseSQL : Boolean read FParseSQL write SetParseSQL default true;
  277. Property DataSource : TDatasource Read GetDataSource Write SetDatasource;
  278. property ServerFilter: string read FServerFilterText write SetServerFilterText;
  279. property ServerFiltered: Boolean read FServerFiltered write SetServerFiltered default False;
  280. property ServerIndexDefs : TServerIndexDefs read GetServerIndexDefs;
  281. end;
  282. { TSQLQuery }
  283. TSQLQuery = Class(TCustomSQLQuery)
  284. public
  285. property SchemaType;
  286. Published
  287. // TDataset stuff
  288. Property Active;
  289. Property AutoCalcFields;
  290. Property Filter;
  291. Property Filtered;
  292. Property AfterCancel;
  293. Property AfterClose;
  294. Property AfterDelete;
  295. Property AfterEdit;
  296. Property AfterInsert;
  297. Property AfterOpen;
  298. Property AfterPost;
  299. Property AfterScroll;
  300. Property BeforeCancel;
  301. Property BeforeClose;
  302. Property BeforeDelete;
  303. Property BeforeEdit;
  304. Property BeforeInsert;
  305. Property BeforeOpen;
  306. Property BeforePost;
  307. Property BeforeScroll;
  308. Property OnCalcFields;
  309. Property OnDeleteError;
  310. Property OnEditError;
  311. Property OnFilterRecord;
  312. Property OnNewRecord;
  313. Property OnPostError;
  314. // property SchemaInfo default stNoSchema;
  315. property Database;
  316. property Transaction;
  317. property ReadOnly;
  318. property SQL;
  319. property UpdateSQL;
  320. property InsertSQL;
  321. property DeleteSQL;
  322. property IndexDefs;
  323. property Params;
  324. property UpdateMode;
  325. property UsePrimaryKeyAsKey;
  326. property ParseSQL;
  327. Property DataSource;
  328. property ServerFilter;
  329. property ServerFiltered;
  330. property ServerIndexDefs;
  331. end;
  332. { TSQLScript }
  333. TSQLScript = class (TCustomSQLscript)
  334. private
  335. FOnDirective: TSQLScriptDirectiveEvent;
  336. FQuery : TCustomSQLQuery;
  337. FDatabase : TDatabase;
  338. FTransaction : TDBTransaction;
  339. protected
  340. procedure ExecuteStatement (SQLStatement: TStrings; var StopExecution: Boolean); override;
  341. procedure ExecuteDirective (Directive, Argument: String; var StopExecution: Boolean); override;
  342. procedure ExecuteCommit; override;
  343. Procedure SetDatabase (Value : TDatabase); virtual;
  344. Procedure SetTransaction(Value : TDBTransaction); virtual;
  345. Procedure CheckDatabase;
  346. public
  347. constructor Create(AOwner : TComponent); override;
  348. destructor Destroy; override;
  349. procedure Execute; override;
  350. procedure ExecuteScript;
  351. published
  352. Property DataBase : TDatabase Read FDatabase Write SetDatabase;
  353. Property Transaction : TDBTransaction Read FTransaction Write SetTransaction;
  354. property OnDirective: TSQLScriptDirectiveEvent read FOnDirective write FOnDirective;
  355. property Directives;
  356. property Defines;
  357. property Script;
  358. property Terminator;
  359. property CommentsinSQL;
  360. property UseSetTerm;
  361. property UseCommit;
  362. property UseDefines;
  363. property OnException;
  364. end;
  365. { TSQLConnector }
  366. TSQLConnector = Class(TSQLConnection)
  367. private
  368. FProxy : TSQLConnection;
  369. FConnectorType: String;
  370. procedure SetConnectorType(const AValue: String);
  371. protected
  372. procedure SetTransaction(Value : TSQLTransaction);override;
  373. procedure DoInternalConnect; override;
  374. procedure DoInternalDisconnect; override;
  375. Procedure CheckProxy;
  376. Procedure CreateProxy; virtual;
  377. Procedure FreeProxy; virtual;
  378. function StrToStatementType(s : string) : TStatementType; override;
  379. function GetAsSQLText(Field : TField) : string; overload; override;
  380. function GetAsSQLText(Param : TParam) : string; overload; override;
  381. function GetHandle : pointer; override;
  382. Function AllocateCursorHandle : TSQLCursor; override;
  383. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
  384. Function AllocateTransactionHandle : TSQLHandle; override;
  385. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
  386. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
  387. function Fetch(cursor : TSQLCursor) : boolean; override;
  388. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
  389. procedure UnPrepareStatement(cursor : TSQLCursor); override;
  390. procedure FreeFldBuffers(cursor : TSQLCursor); override;
  391. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  392. function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
  393. function GetTransactionHandle(trans : TSQLHandle): pointer; override;
  394. function Commit(trans : TSQLHandle) : boolean; override;
  395. function RollBack(trans : TSQLHandle) : boolean; override;
  396. function StartdbTransaction(trans : TSQLHandle; aParams : string) : boolean; override;
  397. procedure CommitRetaining(trans : TSQLHandle); override;
  398. procedure RollBackRetaining(trans : TSQLHandle); override;
  399. procedure UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string); override;
  400. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; override;
  401. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); override;
  402. Property Proxy : TSQLConnection Read FProxy;
  403. Published
  404. Property ConnectorType : String Read FConnectorType Write SetConnectorType;
  405. end;
  406. TSQLConnectionClass = Class of TSQLConnection;
  407. { TConnectionDef }
  408. TConnectionDef = Class(TPersistent)
  409. Class Function TypeName : String; virtual;
  410. Class Function ConnectionClass : TSQLConnectionClass; virtual;
  411. Class Function Description : String; virtual;
  412. Procedure ApplyParams(Params : TStrings; AConnection : TSQLConnection); virtual;
  413. end;
  414. TConnectionDefClass = class of TConnectionDef;
  415. Procedure RegisterConnection(Def : TConnectionDefClass);
  416. Procedure UnRegisterConnection(Def : TConnectionDefClass);
  417. Procedure UnRegisterConnection(ConnectionName : String);
  418. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  419. Procedure GetConnectionList(List : TSTrings);
  420. implementation
  421. uses dbconst, strutils;
  422. { TSQLConnection }
  423. function TSQLConnection.StrToStatementType(s : string) : TStatementType;
  424. var T : TStatementType;
  425. begin
  426. S:=Lowercase(s);
  427. For t:=stselect to strollback do
  428. if (S=StatementTokens[t]) then
  429. Exit(t);
  430. end;
  431. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  432. begin
  433. if FTransaction<>value then
  434. begin
  435. if Assigned(FTransaction) and FTransaction.Active then
  436. DatabaseError(SErrAssTransaction);
  437. if Assigned(Value) then
  438. Value.Database := Self;
  439. FTransaction := Value;
  440. If Assigned(FTransaction) and (FTransaction.Database=Nil) then
  441. FTransaction.Database:=Self;
  442. end;
  443. end;
  444. procedure TSQLConnection.UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string);
  445. begin
  446. // Empty abstract
  447. end;
  448. procedure TSQLConnection.DoInternalConnect;
  449. begin
  450. if (DatabaseName = '') then
  451. DatabaseError(SErrNoDatabaseName,self);
  452. end;
  453. procedure TSQLConnection.DoInternalDisconnect;
  454. begin
  455. end;
  456. destructor TSQLConnection.Destroy;
  457. begin
  458. inherited Destroy;
  459. end;
  460. procedure TSQLConnection.StartTransaction;
  461. begin
  462. if not assigned(Transaction) then
  463. DatabaseError(SErrConnTransactionnSet)
  464. else
  465. Transaction.StartTransaction;
  466. end;
  467. procedure TSQLConnection.EndTransaction;
  468. begin
  469. if not assigned(Transaction) then
  470. DatabaseError(SErrConnTransactionnSet)
  471. else
  472. Transaction.EndTransaction;
  473. end;
  474. Procedure TSQLConnection.ExecuteDirect(SQL: String);
  475. begin
  476. ExecuteDirect(SQL,FTransaction);
  477. end;
  478. Procedure TSQLConnection.ExecuteDirect(SQL: String; ATransaction : TSQLTransaction);
  479. var Cursor : TSQLCursor;
  480. begin
  481. if not assigned(ATransaction) then
  482. DatabaseError(SErrTransactionnSet);
  483. if not Connected then Open;
  484. if not ATransaction.Active then ATransaction.StartTransaction;
  485. try
  486. SQL := TrimRight(SQL);
  487. if SQL = '' then
  488. DatabaseError(SErrNoStatement);
  489. Cursor := AllocateCursorHandle;
  490. Cursor.FStatementType := stNone;
  491. PrepareStatement(cursor,ATransaction,SQL,Nil);
  492. execute(cursor,ATransaction, Nil);
  493. UnPrepareStatement(Cursor);
  494. finally;
  495. DeAllocateCursorHandle(Cursor);
  496. end;
  497. end;
  498. function TSQLConnection.GetPort: cardinal;
  499. begin
  500. result := StrToIntDef(Params.Values['Port'],0);
  501. end;
  502. procedure TSQLConnection.Setport(const AValue: cardinal);
  503. begin
  504. if AValue<>0 then
  505. params.Values['Port']:=IntToStr(AValue)
  506. else with params do if IndexOfName('Port') > -1 then
  507. Delete(IndexOfName('Port'));
  508. end;
  509. procedure TSQLConnection.GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
  510. var qry : TCustomSQLQuery;
  511. begin
  512. if not assigned(Transaction) then
  513. DatabaseError(SErrConnTransactionnSet);
  514. qry := TCustomSQLQuery.Create(nil);
  515. qry.transaction := Transaction;
  516. qry.database := Self;
  517. with qry do
  518. begin
  519. ParseSQL := False;
  520. SetSchemaInfo(ASchemaType,ASchemaObjectName,'');
  521. open;
  522. AList.Clear;
  523. while not eof do
  524. begin
  525. AList.Append(trim(fieldbyname(AReturnField).asstring));
  526. Next;
  527. end;
  528. end;
  529. qry.free;
  530. end;
  531. function TSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
  532. begin
  533. Result := -1;
  534. end;
  535. constructor TSQLConnection.Create(AOwner: TComponent);
  536. begin
  537. inherited Create(AOwner);
  538. FSQLServerFormatSettings.DecimalSeparator:='.';
  539. end;
  540. procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
  541. begin
  542. if not systemtables then GetDBInfo(stTables,'','table_name',List)
  543. else GetDBInfo(stSysTables,'','table_name',List);
  544. end;
  545. procedure TSQLConnection.GetProcedureNames(List: TStrings);
  546. begin
  547. GetDBInfo(stProcedures,'','proc_name',List);
  548. end;
  549. procedure TSQLConnection.GetFieldNames(const TableName: string; List: TStrings);
  550. begin
  551. GetDBInfo(stColumns,TableName,'column_name',List);
  552. end;
  553. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  554. begin
  555. if (not assigned(field)) or field.IsNull then Result := 'Null'
  556. else case field.DataType of
  557. ftString : Result := '''' + field.asstring + '''';
  558. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Field.AsDateTime) + '''';
  559. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Field.AsDateTime) + ''''
  560. else
  561. Result := field.asstring;
  562. end; {case}
  563. end;
  564. function TSQLConnection.GetAsSQLText(Param: TParam) : string;
  565. begin
  566. if (not assigned(param)) or param.IsNull then Result := 'Null'
  567. else case param.DataType of
  568. ftString : Result := '''' + param.asstring + '''';
  569. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Param.AsDateTime) + '''';
  570. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Param.AsDateTime) + '''';
  571. ftFloat : Result := '''' + FloatToStr(Param.AsFloat, FSQLServerFormatSettings) + ''''
  572. else
  573. Result := Param.asstring;
  574. end; {case}
  575. end;
  576. function TSQLConnection.GetHandle: pointer;
  577. begin
  578. Result := nil;
  579. end;
  580. procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
  581. begin
  582. // empty
  583. end;
  584. function TSQLConnection.GetSchemaInfoSQL( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string;
  585. begin
  586. DatabaseError(SMetadataUnavailable);
  587. end;
  588. procedure TSQLConnection.CreateDB;
  589. begin
  590. DatabaseError(SNotSupported);
  591. end;
  592. procedure TSQLConnection.DropDB;
  593. begin
  594. DatabaseError(SNotSupported);
  595. end;
  596. { TSQLTransaction }
  597. procedure TSQLTransaction.EndTransaction;
  598. begin
  599. rollback;
  600. end;
  601. procedure TSQLTransaction.SetParams(const AValue: TStringList);
  602. begin
  603. FParams.Assign(AValue);
  604. end;
  605. function TSQLTransaction.GetHandle: pointer;
  606. begin
  607. Result := TSQLConnection(Database).GetTransactionHandle(FTrans);
  608. end;
  609. procedure TSQLTransaction.Commit;
  610. begin
  611. if active then
  612. begin
  613. closedatasets;
  614. if TSQLConnection(Database).commit(FTrans) then
  615. begin
  616. closeTrans;
  617. FreeAndNil(FTrans);
  618. end;
  619. end;
  620. end;
  621. procedure TSQLTransaction.CommitRetaining;
  622. begin
  623. if active then
  624. TSQLConnection(Database).commitRetaining(FTrans);
  625. end;
  626. procedure TSQLTransaction.Rollback;
  627. begin
  628. if active then
  629. begin
  630. closedatasets;
  631. if TSQLConnection(Database).RollBack(FTrans) then
  632. begin
  633. CloseTrans;
  634. FreeAndNil(FTrans);
  635. end;
  636. end;
  637. end;
  638. procedure TSQLTransaction.RollbackRetaining;
  639. begin
  640. if active then
  641. TSQLConnection(Database).RollBackRetaining(FTrans);
  642. end;
  643. procedure TSQLTransaction.StartTransaction;
  644. var db : TSQLConnection;
  645. begin
  646. if Active then
  647. DatabaseError(SErrTransAlreadyActive);
  648. db := TSQLConnection(Database);
  649. if Db = nil then
  650. DatabaseError(SErrDatabasenAssigned);
  651. if not Db.Connected then
  652. Db.Open;
  653. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  654. if Db.StartdbTransaction(FTrans,FParams.CommaText) then OpenTrans;
  655. end;
  656. constructor TSQLTransaction.Create(AOwner : TComponent);
  657. begin
  658. inherited Create(AOwner);
  659. FParams := TStringList.Create;
  660. end;
  661. destructor TSQLTransaction.Destroy;
  662. begin
  663. Rollback;
  664. FreeAndNil(FParams);
  665. inherited Destroy;
  666. end;
  667. Procedure TSQLTransaction.SetDatabase(Value : TDatabase);
  668. begin
  669. If Value<>Database then
  670. begin
  671. if assigned(value) and not (Value is TSQLConnection) then
  672. DatabaseErrorFmt(SErrNotASQLConnection,[value.Name],self);
  673. CheckInactive;
  674. If Assigned(Database) then
  675. with TSQLConnection(DataBase) do
  676. if Transaction = self then Transaction := nil;
  677. inherited SetDatabase(Value);
  678. If Assigned(Database) and not (csLoading in ComponentState) then
  679. If (TSQLConnection(DataBase).Transaction=Nil) then
  680. TSQLConnection(DataBase).Transaction:=Self;
  681. end;
  682. end;
  683. { TCustomSQLQuery }
  684. procedure TCustomSQLQuery.OnChangeSQL(Sender : TObject);
  685. var ConnOptions : TConnOptions;
  686. begin
  687. UnPrepare;
  688. FSchemaType:=stNoSchema;
  689. if (FSQL <> nil) then
  690. begin
  691. if assigned(DataBase) then
  692. ConnOptions := TSQLConnection(DataBase).ConnOptions
  693. else
  694. ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
  695. Fparams.ParseSQL(FSQL.Text,True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase);
  696. If Assigned(FMasterLink) then
  697. FMasterLink.RefreshParamNames;
  698. end;
  699. end;
  700. procedure TCustomSQLQuery.OnChangeModifySQL(Sender : TObject);
  701. begin
  702. CheckInactive;
  703. end;
  704. Procedure TCustomSQLQuery.SetTransaction(Value : TDBTransaction);
  705. begin
  706. UnPrepare;
  707. inherited;
  708. If (Transaction<>Nil) and (Database=Nil) then
  709. Database:=TSQLTransaction(Transaction).Database;
  710. end;
  711. procedure TCustomSQLQuery.SetDatabase(Value : TDatabase);
  712. var db : tsqlconnection;
  713. begin
  714. if (Database <> Value) then
  715. begin
  716. if assigned(value) and not (Value is TSQLConnection) then
  717. DatabaseErrorFmt(SErrNotASQLConnection,[value.Name],self);
  718. UnPrepare;
  719. if assigned(FCursor) then TSQLConnection(DataBase).DeAllocateCursorHandle(FCursor);
  720. db := TSQLConnection(Value);
  721. inherited setdatabase(value);
  722. if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
  723. transaction := Db.Transaction;
  724. OnChangeSQL(Self);
  725. end;
  726. end;
  727. Function TCustomSQLQuery.IsPrepared : Boolean;
  728. begin
  729. Result := Assigned(FCursor) and FCursor.FPrepared;
  730. end;
  731. Function TCustomSQLQuery.AddFilter(SQLstr : string) : string;
  732. begin
  733. if FWhereStartPos = 0 then
  734. SQLstr := SQLstr + ' where (' + Filter + ')'
  735. else if FWhereStopPos > 0 then
  736. system.insert(' and ('+ServerFilter+') ',SQLstr,FWhereStopPos+1)
  737. else
  738. system.insert(' where ('+ServerFilter+') ',SQLstr,FWhereStartPos);
  739. Result := SQLstr;
  740. end;
  741. procedure TCustomSQLQuery.ApplyFilter;
  742. var S : String;
  743. begin
  744. FreeFldBuffers;
  745. TSQLConnection(Database).UnPrepareStatement(FCursor);
  746. FIsEOF := False;
  747. inherited internalclose;
  748. s := FSQLBuf;
  749. if ServerFiltered then s := AddFilter(s);
  750. TSQLConnection(Database).PrepareStatement(Fcursor,(transaction as tsqltransaction),S,FParams);
  751. Execute;
  752. inherited InternalOpen;
  753. First;
  754. end;
  755. Procedure TCustomSQLQuery.SetActive (Value : Boolean);
  756. begin
  757. inherited SetActive(Value);
  758. // The query is UnPrepared, so that if a transaction closes all datasets
  759. // they also get unprepared
  760. if not Value and IsPrepared then UnPrepare;
  761. end;
  762. procedure TCustomSQLQuery.SetServerFiltered(Value: Boolean);
  763. begin
  764. if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
  765. if (ServerFiltered <> Value) then
  766. begin
  767. FServerFiltered := Value;
  768. if active then ApplyFilter;
  769. end;
  770. end;
  771. procedure TCustomSQLQuery.SetServerFilterText(const Value: string);
  772. begin
  773. if Value <> ServerFilter then
  774. begin
  775. FServerFilterText := Value;
  776. if active then ApplyFilter;
  777. end;
  778. end;
  779. procedure TCustomSQLQuery.Prepare;
  780. var
  781. db : tsqlconnection;
  782. sqltr : tsqltransaction;
  783. StmType: TStatementType;
  784. begin
  785. if not IsPrepared then
  786. begin
  787. db := TSQLConnection(Database);
  788. sqltr := (transaction as tsqltransaction);
  789. if not assigned(Db) then
  790. DatabaseError(SErrDatabasenAssigned);
  791. if not assigned(sqltr) then
  792. DatabaseError(SErrTransactionnSet);
  793. if not Db.Connected then db.Open;
  794. if not sqltr.Active then sqltr.StartTransaction;
  795. if FSchemaType=stNoSchema then
  796. FSQLBuf := TrimRight(FSQL.Text)
  797. else
  798. FSQLBuf := db.GetSchemaInfoSQL(FSchemaType, FSchemaObjectName, FSchemaPattern);
  799. if FSQLBuf = '' then
  800. DatabaseError(SErrNoStatement);
  801. StmType:=SQLParser(FSQLBuf);
  802. // There may no error occur between the allocation of the cursor and
  803. // the preparation of the cursor. Because internalclose (which is called in
  804. // case of an exception) assumes that allocated cursors are also prepared,
  805. // and thus calls unprepare.
  806. // A call to unprepare while the cursor is not prepared at all can lead to
  807. // unpredictable results.
  808. if not assigned(fcursor) then
  809. FCursor := Db.AllocateCursorHandle;
  810. FCursor.FStatementType:=StmType;
  811. FCursor.FSchemaType := FSchemaType;
  812. if ServerFiltered then
  813. Db.PrepareStatement(Fcursor,sqltr,AddFilter(FSQLBuf),FParams)
  814. else
  815. Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
  816. if (FCursor.FStatementType in [stSelect,stExecProcedure]) then
  817. FCursor.FInitFieldDef := True;
  818. end;
  819. end;
  820. procedure TCustomSQLQuery.UnPrepare;
  821. begin
  822. CheckInactive;
  823. if IsPrepared then with TSQLConnection(DataBase) do
  824. UnPrepareStatement(FCursor);
  825. end;
  826. procedure TCustomSQLQuery.FreeFldBuffers;
  827. begin
  828. if assigned(FCursor) then TSQLConnection(Database).FreeFldBuffers(FCursor);
  829. end;
  830. function TCustomSQLQuery.GetServerIndexDefs: TServerIndexDefs;
  831. begin
  832. Result := FServerIndexDefs;
  833. end;
  834. function TCustomSQLQuery.Fetch : boolean;
  835. begin
  836. if not (Fcursor.FStatementType in [stSelect,stExecProcedure]) then
  837. Exit;
  838. if not FIsEof then FIsEOF := not TSQLConnection(Database).Fetch(Fcursor);
  839. Result := not FIsEOF;
  840. // A stored procedure is always at EOF after its first fetch
  841. if FCursor.FStatementType = stExecProcedure then FIsEOF := True;
  842. end;
  843. procedure TCustomSQLQuery.Execute;
  844. begin
  845. If (FParams.Count>0) and Assigned(FMasterLink) then
  846. FMasterLink.CopyParamsFromMaster(False);
  847. TSQLConnection(Database).execute(Fcursor,Transaction as tsqltransaction, FParams);
  848. end;
  849. function TCustomSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  850. begin
  851. result := TSQLConnection(Database).LoadField(FCursor,FieldDef,buffer, Createblob)
  852. end;
  853. function TCustomSQLQuery.RowsAffected: TRowsCount;
  854. begin
  855. Result := -1;
  856. if not Assigned(Database) then Exit;
  857. //assert(Database is TSQLConnection);
  858. Result := TSQLConnection(Database).RowsAffected(FCursor);
  859. end;
  860. procedure TCustomSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  861. begin
  862. // not implemented - sql dataset
  863. end;
  864. procedure TCustomSQLQuery.InternalClose;
  865. begin
  866. if not IsReadFromPacket then
  867. begin
  868. if StatementType in [stSelect,stExecProcedure] then FreeFldBuffers;
  869. // Database and FCursor could be nil, for example if the database is not assigned, and .open is called
  870. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then TSQLConnection(database).UnPrepareStatement(FCursor);
  871. end;
  872. if DefaultFields then
  873. DestroyFields;
  874. FIsEOF := False;
  875. if assigned(FUpdateQry) then FreeAndNil(FUpdateQry);
  876. if assigned(FInsertQry) then FreeAndNil(FInsertQry);
  877. if assigned(FDeleteQry) then FreeAndNil(FDeleteQry);
  878. // FRecordSize := 0;
  879. inherited internalclose;
  880. end;
  881. procedure TCustomSQLQuery.InternalInitFieldDefs;
  882. begin
  883. if FLoadingFieldDefs then
  884. Exit;
  885. FLoadingFieldDefs := True;
  886. try
  887. FieldDefs.Clear;
  888. TSQLConnection(Database).AddFieldDefs(fcursor,FieldDefs);
  889. finally
  890. FLoadingFieldDefs := False;
  891. FCursor.FInitFieldDef := false;
  892. end;
  893. end;
  894. function TCustomSQLQuery.SQLParser(var ASQL : string) : TStatementType;
  895. type TParsePart = (ppStart,ppSelect,ppWhere,ppFrom,ppOrder,ppComment,ppGroup,ppBogus);
  896. Var
  897. PSQL,CurrentP,
  898. PhraseP, PStatementPart : pchar;
  899. S : string;
  900. ParsePart : TParsePart;
  901. StrLength : Integer;
  902. EndOfComment : Boolean;
  903. BracketCount : Integer;
  904. ConnOptions : TConnOptions;
  905. FFromPart : String;
  906. begin
  907. PSQL:=Pchar(ASQL);
  908. ParsePart := ppStart;
  909. CurrentP := PSQL-1;
  910. PhraseP := PSQL;
  911. FWhereStartPos := 0;
  912. FWhereStopPos := 0;
  913. ConnOptions := TSQLConnection(DataBase).ConnOptions;
  914. FUpdateable := False;
  915. repeat
  916. begin
  917. inc(CurrentP);
  918. EndOfComment := SkipComments(CurrentP,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
  919. if EndOfcomment then dec(currentp);
  920. if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;
  921. // skip everything between bracket, since it could be a sub-select, and
  922. // further nothing between brackets could be interesting for the parser.
  923. if currentp^='(' then
  924. begin
  925. inc(currentp);
  926. BracketCount := 0;
  927. while (currentp^ <> #0) and ((currentp^ <> ')') or (BracketCount > 0 )) do
  928. begin
  929. if currentp^ = '(' then inc(bracketcount)
  930. else if currentp^ = ')' then dec(bracketcount);
  931. inc(currentp);
  932. end;
  933. EndOfComment := True;
  934. end;
  935. if EndOfComment or (CurrentP^ in [' ',#13,#10,#9,#0,';']) then
  936. begin
  937. if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
  938. begin
  939. strLength := CurrentP-PhraseP;
  940. Setlength(S,strLength);
  941. if strLength > 0 then Move(PhraseP^,S[1],(strLength));
  942. s := uppercase(s);
  943. case ParsePart of
  944. ppStart : begin
  945. Result := TSQLConnection(Database).StrToStatementType(s);
  946. if Result = stSelect then ParsePart := ppSelect
  947. else break;
  948. if not FParseSQL then break;
  949. PStatementPart := CurrentP;
  950. end;
  951. ppSelect : begin
  952. if s = 'FROM' then
  953. begin
  954. ParsePart := ppFrom;
  955. PhraseP := CurrentP;
  956. PStatementPart := CurrentP;
  957. end;
  958. end;
  959. ppFrom : begin
  960. if (s = 'WHERE') or (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  961. begin
  962. if (s = 'WHERE') then
  963. begin
  964. ParsePart := ppWhere;
  965. StrLength := PhraseP-PStatementPart;
  966. end
  967. else if (s = 'GROUP') then
  968. begin
  969. ParsePart := ppGroup;
  970. StrLength := PhraseP-PStatementPart;
  971. end
  972. else if (s = 'ORDER') then
  973. begin
  974. ParsePart := ppOrder;
  975. StrLength := PhraseP-PStatementPart
  976. end
  977. else
  978. begin
  979. ParsePart := ppBogus;
  980. StrLength := CurrentP-PStatementPart;
  981. end;
  982. if Result = stSelect then
  983. begin
  984. Setlength(FFromPart,StrLength);
  985. Move(PStatementPart^,FFromPart[1],(StrLength));
  986. FFrompart := trim(FFrompart);
  987. // Meta-data requests and are never updateable select-statements
  988. // from more then one table are not updateable
  989. if (FSchemaType=stNoSchema) and
  990. (ExtractStrings([',',' '],[],pchar(FFromPart),nil) = 1) then
  991. begin
  992. FUpdateable := True;
  993. FTableName := FFromPart;
  994. end;
  995. end;
  996. FWhereStartPos := PStatementPart-PSQL+StrLength+1;
  997. PStatementPart := CurrentP;
  998. end;
  999. end;
  1000. ppWhere : begin
  1001. if (s = 'ORDER') or (s = 'GROUP') or (CurrentP^=#0) or (CurrentP^=';') then
  1002. begin
  1003. ParsePart := ppBogus;
  1004. FWhereStartPos := PStatementPart-PSQL;
  1005. if (s = 'ORDER') or (s = 'GROUP') then
  1006. FWhereStopPos := PhraseP-PSQL+1
  1007. else
  1008. FWhereStopPos := CurrentP-PSQL+1;
  1009. end
  1010. else if (s = 'UNION') then
  1011. begin
  1012. ParsePart := ppBogus;
  1013. FUpdateable := False;
  1014. end;
  1015. end;
  1016. end; {case}
  1017. end;
  1018. PhraseP := CurrentP+1;
  1019. end
  1020. end;
  1021. until CurrentP^=#0;
  1022. if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
  1023. begin
  1024. system.insert('(',ASQL,FWhereStartPos+1);
  1025. inc(FWhereStopPos);
  1026. system.insert(')',ASQL,FWhereStopPos);
  1027. end
  1028. end;
  1029. procedure TCustomSQLQuery.InternalOpen;
  1030. var tel, fieldc : integer;
  1031. f : TField;
  1032. s : string;
  1033. IndexFields : TStrings;
  1034. ReadFromFile: Boolean;
  1035. begin
  1036. ReadFromFile:=IsReadFromPacket;
  1037. if ReadFromFile then
  1038. begin
  1039. if not assigned(fcursor) then
  1040. FCursor := TSQLConnection(Database).AllocateCursorHandle;
  1041. FCursor.FStatementType:=stSelect;
  1042. FUpdateable:=True;
  1043. end
  1044. else
  1045. Prepare;
  1046. if FCursor.FStatementType in [stSelect,stExecProcedure] then
  1047. begin
  1048. if not ReadFromFile then
  1049. begin
  1050. // Call UpdateServerIndexDefs before Execute, to avoid problems with connections
  1051. // which do not allow processing multiple recordsets at a time. (Microsoft
  1052. // calls this MARS, see bug 13241)
  1053. if DefaultFields and FUpdateable and FusePrimaryKeyAsKey then
  1054. UpdateServerIndexDefs;
  1055. Execute;
  1056. // InternalInitFieldDef is only called after a prepare. i.e. not twice if
  1057. // a dataset is opened - closed - opened.
  1058. if FCursor.FInitFieldDef then InternalInitFieldDefs;
  1059. if DefaultFields then
  1060. begin
  1061. CreateFields;
  1062. if FUpdateable then
  1063. begin
  1064. if FusePrimaryKeyAsKey then
  1065. begin
  1066. for tel := 0 to ServerIndexDefs.count-1 do
  1067. begin
  1068. if ixPrimary in ServerIndexDefs[tel].options then
  1069. begin
  1070. IndexFields := TStringList.Create;
  1071. ExtractStrings([';'],[' '],pchar(ServerIndexDefs[tel].fields),IndexFields);
  1072. for fieldc := 0 to IndexFields.Count-1 do
  1073. begin
  1074. F := Findfield(IndexFields[fieldc]);
  1075. if F <> nil then
  1076. F.ProviderFlags := F.ProviderFlags + [pfInKey];
  1077. end;
  1078. IndexFields.Free;
  1079. end;
  1080. end;
  1081. end;
  1082. end;
  1083. end
  1084. else
  1085. BindFields(True);
  1086. end
  1087. else
  1088. BindFields(True);
  1089. if not ReadOnly and not FUpdateable and (FSchemaType=stNoSchema) then
  1090. begin
  1091. if (trim(FDeleteSQL.Text) <> '') or (trim(FUpdateSQL.Text) <> '') or
  1092. (trim(FInsertSQL.Text) <> '') then FUpdateable := True;
  1093. end
  1094. end
  1095. else
  1096. DatabaseError(SErrNoSelectStatement,Self);
  1097. inherited InternalOpen;
  1098. end;
  1099. // public part
  1100. procedure TCustomSQLQuery.ExecSQL;
  1101. begin
  1102. try
  1103. Prepare;
  1104. Execute;
  1105. finally
  1106. // FCursor has to be assigned, or else the prepare went wrong before PrepareStatment was
  1107. // called, so UnPrepareStatement shoudn't be called either
  1108. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then TSQLConnection(database).UnPrepareStatement(Fcursor);
  1109. end;
  1110. end;
  1111. constructor TCustomSQLQuery.Create(AOwner : TComponent);
  1112. begin
  1113. inherited Create(AOwner);
  1114. FParams := TParams.create(self);
  1115. FSQL := TStringList.Create;
  1116. FSQL.OnChange := @OnChangeSQL;
  1117. FUpdateSQL := TStringList.Create;
  1118. FUpdateSQL.OnChange := @OnChangeModifySQL;
  1119. FInsertSQL := TStringList.Create;
  1120. FInsertSQL.OnChange := @OnChangeModifySQL;
  1121. FDeleteSQL := TStringList.Create;
  1122. FDeleteSQL.OnChange := @OnChangeModifySQL;
  1123. FServerIndexDefs := TServerIndexDefs.Create(Self);
  1124. FReadOnly := false;
  1125. FParseSQL := True;
  1126. FServerFiltered := False;
  1127. FServerFilterText := '';
  1128. FSchemaType:=stNoSchema;
  1129. FSchemaObjectName:='';
  1130. FSchemaPattern:='';
  1131. // Delphi has upWhereAll as default, but since strings and oldvalue's don't work yet
  1132. // (variants) set it to upWhereKeyOnly
  1133. FUpdateMode := upWhereKeyOnly;
  1134. FUsePrimaryKeyAsKey := True;
  1135. end;
  1136. destructor TCustomSQLQuery.Destroy;
  1137. begin
  1138. if Active then Close;
  1139. UnPrepare;
  1140. if assigned(FCursor) then TSQLConnection(Database).DeAllocateCursorHandle(FCursor);
  1141. FreeAndNil(FMasterLink);
  1142. FreeAndNil(FParams);
  1143. FreeAndNil(FSQL);
  1144. FreeAndNil(FInsertSQL);
  1145. FreeAndNil(FDeleteSQL);
  1146. FreeAndNil(FUpdateSQL);
  1147. FServerIndexDefs.Free;
  1148. inherited Destroy;
  1149. end;
  1150. procedure TCustomSQLQuery.SetReadOnly(AValue : Boolean);
  1151. begin
  1152. CheckInactive;
  1153. FReadOnly:=AValue;
  1154. end;
  1155. procedure TCustomSQLQuery.SetParseSQL(AValue : Boolean);
  1156. begin
  1157. CheckInactive;
  1158. if not AValue then
  1159. begin
  1160. FServerFiltered := False;
  1161. FParseSQL := False;
  1162. end
  1163. else
  1164. FParseSQL := True;
  1165. end;
  1166. procedure TCustomSQLQuery.SetSQL(const AValue: TStringlist);
  1167. begin
  1168. FSQL.Assign(AValue);
  1169. end;
  1170. procedure TCustomSQLQuery.SetUpdateSQL(const AValue: TStringlist);
  1171. begin
  1172. FUpdateSQL.Assign(AValue);
  1173. end;
  1174. procedure TCustomSQLQuery.SetUsePrimaryKeyAsKey(AValue : Boolean);
  1175. begin
  1176. if not Active then FusePrimaryKeyAsKey := AValue
  1177. else
  1178. begin
  1179. // Just temporary, this should be possible in the future
  1180. DatabaseError(SActiveDataset);
  1181. end;
  1182. end;
  1183. Procedure TCustomSQLQuery.UpdateServerIndexDefs;
  1184. begin
  1185. FServerIndexDefs.Clear;
  1186. if assigned(DataBase) and (FTableName<>'') then
  1187. TSQLConnection(DataBase).UpdateIndexDefs(ServerIndexDefs,FTableName);
  1188. end;
  1189. Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
  1190. var FieldNamesQuoteChar : string;
  1191. procedure InitialiseModifyQuery(var qry : TCustomSQLQuery; aSQL: String);
  1192. begin
  1193. qry := TCustomSQLQuery.Create(nil);
  1194. with qry do
  1195. begin
  1196. ParseSQL := False;
  1197. DataBase := Self.DataBase;
  1198. Transaction := Self.Transaction;
  1199. SQL.text := aSQL;
  1200. end;
  1201. end;
  1202. procedure UpdateWherePart(var sql_where : string;x : integer);
  1203. begin
  1204. if (pfInKey in Fields[x].ProviderFlags) or
  1205. ((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
  1206. ((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
  1207. sql_where := sql_where + '(' + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar + '= :' + FieldNamesQuoteChar + 'OLD_' + fields[x].FieldName + FieldNamesQuoteChar +') and ';
  1208. end;
  1209. function ModifyRecQuery : string;
  1210. var x : integer;
  1211. sql_set : string;
  1212. sql_where : string;
  1213. begin
  1214. sql_set := '';
  1215. sql_where := '';
  1216. for x := 0 to Fields.Count -1 do
  1217. begin
  1218. UpdateWherePart(sql_where,x);
  1219. if (pfInUpdate in Fields[x].ProviderFlags) then
  1220. sql_set := sql_set +FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar +'=:' + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar + ',';
  1221. end;
  1222. if length(sql_set) = 0 then DatabaseErrorFmt(sNoUpdateFields,['update'],self);
  1223. setlength(sql_set,length(sql_set)-1);
  1224. if length(sql_where) = 0 then DatabaseErrorFmt(sNoWhereFields,['update'],self);
  1225. setlength(sql_where,length(sql_where)-5);
  1226. result := 'update ' + FTableName + ' set ' + sql_set + ' where ' + sql_where;
  1227. end;
  1228. function InsertRecQuery : string;
  1229. var x : integer;
  1230. sql_fields : string;
  1231. sql_values : string;
  1232. begin
  1233. sql_fields := '';
  1234. sql_values := '';
  1235. for x := 0 to Fields.Count -1 do
  1236. begin
  1237. if (not fields[x].IsNull) and (pfInUpdate in Fields[x].ProviderFlags) then
  1238. begin
  1239. sql_fields := sql_fields + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar + ',';
  1240. sql_values := sql_values + ':' + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar +',';
  1241. end;
  1242. end;
  1243. if length(sql_fields) = 0 then DatabaseErrorFmt(sNoUpdateFields,['insert'],self);
  1244. setlength(sql_fields,length(sql_fields)-1);
  1245. setlength(sql_values,length(sql_values)-1);
  1246. result := 'insert into ' + FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
  1247. end;
  1248. function DeleteRecQuery : string;
  1249. var x : integer;
  1250. sql_where : string;
  1251. begin
  1252. sql_where := '';
  1253. for x := 0 to Fields.Count -1 do
  1254. UpdateWherePart(sql_where,x);
  1255. if length(sql_where) = 0 then DatabaseErrorFmt(sNoWhereFields,['delete'],self);
  1256. setlength(sql_where,length(sql_where)-5);
  1257. result := 'delete from ' + FTableName + ' where ' + sql_where;
  1258. end;
  1259. var qry : TCustomSQLQuery;
  1260. x : integer;
  1261. Fld : TField;
  1262. begin
  1263. if sqQuoteFieldnames in TSQLConnection(DataBase).ConnOptions then
  1264. FieldNamesQuoteChar := '"'
  1265. else
  1266. FieldNamesQuoteChar := '';
  1267. case UpdateKind of
  1268. ukModify : begin
  1269. if not assigned(FUpdateQry) then
  1270. begin
  1271. if (trim(FUpdateSQL.Text)<> '') then
  1272. InitialiseModifyQuery(FUpdateQry,FUpdateSQL.Text)
  1273. else
  1274. InitialiseModifyQuery(FUpdateQry,ModifyRecQuery);
  1275. end;
  1276. qry := FUpdateQry;
  1277. end;
  1278. ukInsert : begin
  1279. if not assigned(FInsertQry) then
  1280. begin
  1281. if (trim(FInsertSQL.Text)<> '') then
  1282. InitialiseModifyQuery(FInsertQry,FInsertSQL.Text)
  1283. else
  1284. InitialiseModifyQuery(FInsertQry,InsertRecQuery);
  1285. end;
  1286. qry := FInsertQry;
  1287. end;
  1288. ukDelete : begin
  1289. if not assigned(FDeleteQry) then
  1290. begin
  1291. if (trim(FDeleteSQL.Text)<> '') then
  1292. InitialiseModifyQuery(FDeleteQry,FDeleteSQL.Text)
  1293. else
  1294. InitialiseModifyQuery(FDeleteQry,DeleteRecQuery);
  1295. end;
  1296. qry := FDeleteQry;
  1297. end;
  1298. end;
  1299. assert(qry.sql.Text<>'');
  1300. with qry do
  1301. begin
  1302. for x := 0 to Params.Count-1 do with params[x] do if leftstr(name,4)='OLD_' then
  1303. begin
  1304. Fld := self.FieldByName(copy(name,5,length(name)-4));
  1305. AssignFieldValue(Fld,Fld.OldValue);
  1306. end
  1307. else
  1308. begin
  1309. Fld := self.FieldByName(name);
  1310. AssignFieldValue(Fld,Fld.Value);
  1311. end;
  1312. execsql;
  1313. end;
  1314. end;
  1315. Function TCustomSQLQuery.GetCanModify: Boolean;
  1316. begin
  1317. // the test for assigned(FCursor) is needed for the case that the dataset isn't opened
  1318. if assigned(FCursor) and (FCursor.FStatementType = stSelect) then
  1319. Result:= FUpdateable and (not FReadOnly)
  1320. else
  1321. Result := False;
  1322. end;
  1323. procedure TCustomSQLQuery.SetUpdateMode(AValue : TUpdateMode);
  1324. begin
  1325. FUpdateMode := AValue;
  1326. end;
  1327. procedure TCustomSQLQuery.SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string);
  1328. begin
  1329. FSchemaType:=ASchemaType;
  1330. FSchemaObjectName:=ASchemaObjectName;
  1331. FSchemaPattern:=ASchemaPattern;
  1332. end;
  1333. procedure TCustomSQLQuery.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1334. ABlobBuf: PBufBlobField);
  1335. begin
  1336. TSQLConnection(DataBase).LoadBlobIntoBuffer(FieldDef, ABlobBuf, FCursor,(Transaction as tsqltransaction));
  1337. end;
  1338. procedure TCustomSQLQuery.BeforeRefreshOpenCursor;
  1339. begin
  1340. // This is only necessary because TIBConnection can not re-open a
  1341. // prepared cursor. In fact this is wrong, but has never led to
  1342. // problems because in SetActive(false) queries are always
  1343. // unprepared. (which is also wrong, but has to be fixed later)
  1344. if IsPrepared then with TSQLConnection(DataBase) do
  1345. UnPrepareStatement(FCursor);
  1346. end;
  1347. function TCustomSQLQuery.GetStatementType : TStatementType;
  1348. begin
  1349. if assigned(FCursor) then Result := FCursor.FStatementType
  1350. else Result := stNone;
  1351. end;
  1352. procedure TCustomSQLQuery.SetDeleteSQL(const AValue: TStringlist);
  1353. begin
  1354. FDeleteQry.Assign(AValue);
  1355. end;
  1356. procedure TCustomSQLQuery.SetInsertSQL(const AValue: TStringlist);
  1357. begin
  1358. FInsertQry.Assign(AValue);
  1359. end;
  1360. Procedure TCustomSQLQuery.SetDataSource(AVAlue : TDatasource);
  1361. Var
  1362. DS : TDatasource;
  1363. begin
  1364. DS:=DataSource;
  1365. If (AValue<>DS) then
  1366. begin
  1367. If Assigned(AValue) and (AValue.Dataset=Self) then
  1368. DatabaseError(SErrCircularDataSourceReferenceNotAllowed,Self);
  1369. If Assigned(DS) then
  1370. DS.RemoveFreeNotification(Self);
  1371. If Assigned(AValue) then
  1372. begin
  1373. AValue.FreeNotification(Self);
  1374. If (FMasterLink=Nil) then
  1375. FMasterLink:=TMasterParamsDataLink.Create(Self);
  1376. FMasterLink.Datasource:=AValue;
  1377. end
  1378. else
  1379. FreeAndNil(FMasterLink);
  1380. end;
  1381. end;
  1382. Function TCustomSQLQuery.GetDataSource : TDatasource;
  1383. begin
  1384. If Assigned(FMasterLink) then
  1385. Result:=FMasterLink.DataSource
  1386. else
  1387. Result:=Nil;
  1388. end;
  1389. procedure TCustomSQLQuery.Notification(AComponent: TComponent; Operation: TOperation);
  1390. begin
  1391. Inherited;
  1392. If (Operation=opRemove) and (AComponent=DataSource) then
  1393. DataSource:=Nil;
  1394. end;
  1395. { TSQLScript }
  1396. procedure TSQLScript.ExecuteStatement(SQLStatement: TStrings;
  1397. var StopExecution: Boolean);
  1398. begin
  1399. fquery.SQL.assign(SQLStatement);
  1400. fquery.ExecSQL;
  1401. end;
  1402. procedure TSQLScript.ExecuteDirective(Directive, Argument: String;
  1403. var StopExecution: Boolean);
  1404. begin
  1405. if assigned (FOnDirective) then
  1406. FOnDirective (Self, Directive, Argument, StopExecution);
  1407. end;
  1408. procedure TSQLScript.ExecuteCommit;
  1409. begin
  1410. if FTransaction is TSQLTransaction then
  1411. TSQLTransaction(FTransaction).CommitRetaining
  1412. else
  1413. begin
  1414. FTransaction.Active := false;
  1415. FTransaction.Active := true;
  1416. end;
  1417. end;
  1418. procedure TSQLScript.SetDatabase(Value: TDatabase);
  1419. begin
  1420. FDatabase := Value;
  1421. end;
  1422. procedure TSQLScript.SetTransaction(Value: TDBTransaction);
  1423. begin
  1424. FTransaction := Value;
  1425. end;
  1426. procedure TSQLScript.CheckDatabase;
  1427. begin
  1428. If (FDatabase=Nil) then
  1429. DatabaseError(SErrNoDatabaseAvailable,Self)
  1430. end;
  1431. constructor TSQLScript.Create(AOwner: TComponent);
  1432. begin
  1433. inherited Create(AOwner);
  1434. FQuery := TCustomSQLQuery.Create(nil);
  1435. end;
  1436. destructor TSQLScript.Destroy;
  1437. begin
  1438. FQuery.Free;
  1439. inherited Destroy;
  1440. end;
  1441. procedure TSQLScript.Execute;
  1442. begin
  1443. FQuery.DataBase := FDatabase;
  1444. FQuery.Transaction := FTransaction;
  1445. inherited Execute;
  1446. end;
  1447. procedure TSQLScript.ExecuteScript;
  1448. begin
  1449. Execute;
  1450. end;
  1451. { Connection definitions }
  1452. Var
  1453. ConnDefs : TStringList;
  1454. Procedure CheckDefs;
  1455. begin
  1456. If (ConnDefs=Nil) then
  1457. begin
  1458. ConnDefs:=TStringList.Create;
  1459. ConnDefs.Sorted:=True;
  1460. ConnDefs.Duplicates:=dupError;
  1461. end;
  1462. end;
  1463. Procedure DoneDefs;
  1464. Var
  1465. I : Integer;
  1466. begin
  1467. If Assigned(ConnDefs) then
  1468. begin
  1469. For I:=ConnDefs.Count-1 downto 0 do
  1470. begin
  1471. ConnDefs.Objects[i].Free;
  1472. ConnDefs.Delete(I);
  1473. end;
  1474. FreeAndNil(ConnDefs);
  1475. end;
  1476. end;
  1477. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  1478. Var
  1479. I : Integer;
  1480. begin
  1481. CheckDefs;
  1482. I:=ConnDefs.IndexOf(ConnectorName);
  1483. If (I<>-1) then
  1484. Result:=TConnectionDef(ConnDefs.Objects[i])
  1485. else
  1486. Result:=Nil;
  1487. end;
  1488. procedure RegisterConnection(Def: TConnectionDefClass);
  1489. Var
  1490. I : Integer;
  1491. begin
  1492. CheckDefs;
  1493. I:=ConnDefs.IndexOf(Def.TypeName);
  1494. If (I=-1) then
  1495. ConnDefs.AddObject(Def.TypeName,Def.Create)
  1496. else
  1497. begin
  1498. ConnDefs.Objects[I].Free;
  1499. ConnDefs.Objects[I]:=Def.Create;
  1500. end;
  1501. end;
  1502. procedure UnRegisterConnection(Def: TConnectionDefClass);
  1503. begin
  1504. UnRegisterConnection(Def.TypeName);
  1505. end;
  1506. procedure UnRegisterConnection(ConnectionName: String);
  1507. Var
  1508. I : Integer;
  1509. begin
  1510. if (ConnDefs<>Nil) then
  1511. begin
  1512. I:=ConnDefs.IndexOf(ConnectionName);
  1513. If (I<>-1) then
  1514. begin
  1515. ConnDefs.Objects[I].Free;
  1516. ConnDefs.Delete(I);
  1517. end;
  1518. end;
  1519. end;
  1520. procedure GetConnectionList(List: TSTrings);
  1521. begin
  1522. CheckDefs;
  1523. List.Text:=ConnDefs.Text;
  1524. end;
  1525. { TSQLConnector }
  1526. procedure TSQLConnector.SetConnectorType(const AValue: String);
  1527. begin
  1528. if FConnectorType<>AValue then
  1529. begin
  1530. CheckDisconnected;
  1531. If Assigned(FProxy) then
  1532. FreeProxy;
  1533. FConnectorType:=AValue;
  1534. end;
  1535. end;
  1536. procedure TSQLConnector.SetTransaction(Value: TSQLTransaction);
  1537. begin
  1538. inherited SetTransaction(Value);
  1539. If Assigned(FProxy) and (FProxy.Transaction<>Value) then
  1540. FProxy.Transaction:=Value;
  1541. end;
  1542. procedure TSQLConnector.DoInternalConnect;
  1543. Var
  1544. D : TConnectionDef;
  1545. begin
  1546. inherited DoInternalConnect;
  1547. CreateProxy;
  1548. FProxy.DatabaseName:=Self.DatabaseName;
  1549. FProxy.HostName:=Self.HostName;
  1550. FProxy.UserName:=Self.UserName;
  1551. FProxy.Password:=Self.Password;
  1552. FProxy.Transaction:=Self.Transaction;
  1553. D:=GetConnectionDef(ConnectorType);
  1554. D.ApplyParams(Params,FProxy);
  1555. FProxy.Connected:=True;
  1556. end;
  1557. procedure TSQLConnector.DoInternalDisconnect;
  1558. begin
  1559. FProxy.Connected:=False;
  1560. inherited DoInternalDisconnect;
  1561. end;
  1562. procedure TSQLConnector.CheckProxy;
  1563. begin
  1564. If (FProxy=Nil) then
  1565. CreateProxy;
  1566. end;
  1567. procedure TSQLConnector.CreateProxy;
  1568. Var
  1569. D : TConnectionDef;
  1570. begin
  1571. D:=GetConnectionDef(ConnectorType);
  1572. If (D=Nil) then
  1573. DatabaseErrorFmt(SErrUnknownConnectorType,[ConnectorType],Self);
  1574. FProxy:=D.ConnectionClass.Create(Self);
  1575. end;
  1576. procedure TSQLConnector.FreeProxy;
  1577. begin
  1578. FProxy.Connected:=False;
  1579. FreeAndNil(FProxy);
  1580. end;
  1581. function TSQLConnector.StrToStatementType(s: string): TStatementType;
  1582. begin
  1583. CheckProxy;
  1584. Result:=FProxy.StrToStatementType(s);
  1585. end;
  1586. function TSQLConnector.GetAsSQLText(Field: TField): string;
  1587. begin
  1588. CheckProxy;
  1589. Result:=FProxy.GetAsSQLText(Field);
  1590. end;
  1591. function TSQLConnector.GetAsSQLText(Param: TParam): string;
  1592. begin
  1593. CheckProxy;
  1594. Result:=FProxy.GetAsSQLText(Param);
  1595. end;
  1596. function TSQLConnector.GetHandle: pointer;
  1597. begin
  1598. CheckProxy;
  1599. Result:=FProxy.GetHandle;
  1600. end;
  1601. function TSQLConnector.AllocateCursorHandle: TSQLCursor;
  1602. begin
  1603. CheckProxy;
  1604. Result:=FProxy.AllocateCursorHandle;
  1605. end;
  1606. procedure TSQLConnector.DeAllocateCursorHandle(var cursor: TSQLCursor);
  1607. begin
  1608. CheckProxy;
  1609. FProxy.DeAllocateCursorHandle(cursor);
  1610. end;
  1611. function TSQLConnector.AllocateTransactionHandle: TSQLHandle;
  1612. begin
  1613. CheckProxy;
  1614. Result:=FProxy.AllocateTransactionHandle;
  1615. end;
  1616. procedure TSQLConnector.PrepareStatement(cursor: TSQLCursor;
  1617. ATransaction: TSQLTransaction; buf: string; AParams: TParams);
  1618. begin
  1619. CheckProxy;
  1620. FProxy.PrepareStatement(cursor, ATransaction, buf, AParams);
  1621. end;
  1622. procedure TSQLConnector.Execute(cursor: TSQLCursor;
  1623. atransaction: tSQLtransaction; AParams: TParams);
  1624. begin
  1625. CheckProxy;
  1626. FProxy.Execute(cursor, atransaction, AParams);
  1627. end;
  1628. function TSQLConnector.Fetch(cursor: TSQLCursor): boolean;
  1629. begin
  1630. CheckProxy;
  1631. Result:=FProxy.Fetch(cursor);
  1632. end;
  1633. procedure TSQLConnector.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TfieldDefs
  1634. );
  1635. begin
  1636. CheckProxy;
  1637. FProxy.AddFieldDefs(cursor, FieldDefs);
  1638. end;
  1639. procedure TSQLConnector.UnPrepareStatement(cursor: TSQLCursor);
  1640. begin
  1641. CheckProxy;
  1642. FProxy.UnPrepareStatement(cursor);
  1643. end;
  1644. procedure TSQLConnector.FreeFldBuffers(cursor: TSQLCursor);
  1645. begin
  1646. CheckProxy;
  1647. FProxy.FreeFldBuffers(cursor);
  1648. end;
  1649. function TSQLConnector.LoadField(cursor: TSQLCursor; FieldDef: TfieldDef;
  1650. buffer: pointer; out CreateBlob: boolean): boolean;
  1651. begin
  1652. CheckProxy;
  1653. Result:=FProxy.LoadField(cursor, FieldDef, buffer, CreateBlob);
  1654. end;
  1655. function TSQLConnector.RowsAffected(cursor: TSQLCursor): TRowsCount;
  1656. begin
  1657. CheckProxy;
  1658. Result := FProxy.RowsAffected(cursor);
  1659. end;
  1660. function TSQLConnector.GetTransactionHandle(trans: TSQLHandle): pointer;
  1661. begin
  1662. CheckProxy;
  1663. Result:=FProxy.GetTransactionHandle(trans);
  1664. end;
  1665. function TSQLConnector.Commit(trans: TSQLHandle): boolean;
  1666. begin
  1667. CheckProxy;
  1668. Result:=FProxy.Commit(trans);
  1669. end;
  1670. function TSQLConnector.RollBack(trans: TSQLHandle): boolean;
  1671. begin
  1672. CheckProxy;
  1673. Result:=FProxy.RollBack(trans);
  1674. end;
  1675. function TSQLConnector.StartdbTransaction(trans: TSQLHandle; aParams: string
  1676. ): boolean;
  1677. begin
  1678. CheckProxy;
  1679. Result:=FProxy.StartdbTransaction(trans, aParams);
  1680. end;
  1681. procedure TSQLConnector.CommitRetaining(trans: TSQLHandle);
  1682. begin
  1683. CheckProxy;
  1684. FProxy.CommitRetaining(trans);
  1685. end;
  1686. procedure TSQLConnector.RollBackRetaining(trans: TSQLHandle);
  1687. begin
  1688. CheckProxy;
  1689. FProxy.RollBackRetaining(trans);
  1690. end;
  1691. procedure TSQLConnector.UpdateIndexDefs(IndexDefs: TIndexDefs;
  1692. TableName: string);
  1693. begin
  1694. CheckProxy;
  1695. FProxy.UpdateIndexDefs(IndexDefs, TableName);
  1696. end;
  1697. function TSQLConnector.GetSchemaInfoSQL(SchemaType: TSchemaType;
  1698. SchemaObjectName, SchemaPattern: string): string;
  1699. begin
  1700. CheckProxy;
  1701. Result:=FProxy.GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern
  1702. );
  1703. end;
  1704. procedure TSQLConnector.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1705. ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction: TSQLTransaction);
  1706. begin
  1707. CheckProxy;
  1708. FProxy.LoadBlobIntoBuffer(FieldDef, ABlobBuf, cursor, ATransaction);
  1709. end;
  1710. { TConnectionDef }
  1711. class function TConnectionDef.TypeName: String;
  1712. begin
  1713. Result:='';
  1714. end;
  1715. class function TConnectionDef.ConnectionClass: TSQLConnectionClass;
  1716. begin
  1717. Result:=Nil;
  1718. end;
  1719. class function TConnectionDef.Description: String;
  1720. begin
  1721. Result:='';
  1722. end;
  1723. procedure TConnectionDef.ApplyParams(Params: TStrings;
  1724. AConnection: TSQLConnection);
  1725. begin
  1726. AConnection.Params.Assign(Params);
  1727. end;
  1728. { TServerIndexDefs }
  1729. constructor TServerIndexDefs.create(ADataset: TDataset);
  1730. begin
  1731. if not (ADataset is TCustomSQLQuery) then
  1732. DatabaseErrorFmt(SErrNotASQLQuery,[ADataset.Name]);
  1733. inherited create(ADataset);
  1734. end;
  1735. procedure TServerIndexDefs.Update;
  1736. begin
  1737. if (not updated) and assigned(Dataset) then
  1738. begin
  1739. TCustomSQLQuery(Dataset).UpdateServerIndexDefs;
  1740. updated := True;
  1741. end;
  1742. end;
  1743. Initialization
  1744. Finalization
  1745. DoneDefs;
  1746. end.