sqldb.pp 58 KB

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