sqldb.pp 62 KB

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