sqldb.pp 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194
  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. { TSQLConnection }
  446. function TSQLConnection.StrToStatementType(s : string) : TStatementType;
  447. var T : TStatementType;
  448. begin
  449. S:=Lowercase(s);
  450. For t:=stselect to strollback do
  451. if (S=StatementTokens[t]) then
  452. Exit(t);
  453. end;
  454. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  455. begin
  456. if FTransaction<>value then
  457. begin
  458. if Assigned(FTransaction) and FTransaction.Active then
  459. DatabaseError(SErrAssTransaction);
  460. if Assigned(Value) then
  461. Value.Database := Self;
  462. FTransaction := Value;
  463. If Assigned(FTransaction) and (FTransaction.Database=Nil) then
  464. FTransaction.Database:=Self;
  465. end;
  466. end;
  467. procedure TSQLConnection.UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string);
  468. begin
  469. // Empty abstract
  470. end;
  471. procedure TSQLConnection.DoInternalConnect;
  472. begin
  473. if (DatabaseName = '') then
  474. DatabaseError(SErrNoDatabaseName,self);
  475. end;
  476. procedure TSQLConnection.DoInternalDisconnect;
  477. begin
  478. end;
  479. destructor TSQLConnection.Destroy;
  480. begin
  481. inherited Destroy;
  482. end;
  483. procedure TSQLConnection.StartTransaction;
  484. begin
  485. if not assigned(Transaction) then
  486. DatabaseError(SErrConnTransactionnSet)
  487. else
  488. Transaction.StartTransaction;
  489. end;
  490. procedure TSQLConnection.EndTransaction;
  491. begin
  492. if not assigned(Transaction) then
  493. DatabaseError(SErrConnTransactionnSet)
  494. else
  495. Transaction.EndTransaction;
  496. end;
  497. Procedure TSQLConnection.ExecuteDirect(SQL: String);
  498. begin
  499. ExecuteDirect(SQL,FTransaction);
  500. end;
  501. Procedure TSQLConnection.ExecuteDirect(SQL: String; ATransaction : TSQLTransaction);
  502. var Cursor : TSQLCursor;
  503. begin
  504. if not assigned(ATransaction) then
  505. DatabaseError(SErrTransactionnSet);
  506. if not Connected then Open;
  507. if not ATransaction.Active then ATransaction.StartTransaction;
  508. try
  509. SQL := TrimRight(SQL);
  510. if SQL = '' then
  511. DatabaseError(SErrNoStatement);
  512. Cursor := AllocateCursorHandle;
  513. Cursor.FStatementType := stNone;
  514. PrepareStatement(cursor,ATransaction,SQL,Nil);
  515. execute(cursor,ATransaction, Nil);
  516. UnPrepareStatement(Cursor);
  517. finally;
  518. DeAllocateCursorHandle(Cursor);
  519. end;
  520. end;
  521. function TSQLConnection.GetPort: cardinal;
  522. begin
  523. result := StrToIntDef(Params.Values['Port'],0);
  524. end;
  525. procedure TSQLConnection.Setport(const AValue: cardinal);
  526. begin
  527. if AValue<>0 then
  528. params.Values['Port']:=IntToStr(AValue)
  529. else with params do if IndexOfName('Port') > -1 then
  530. Delete(IndexOfName('Port'));
  531. end;
  532. procedure TSQLConnection.GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
  533. var qry : TCustomSQLQuery;
  534. begin
  535. if not assigned(Transaction) then
  536. DatabaseError(SErrConnTransactionnSet);
  537. qry := TCustomSQLQuery.Create(nil);
  538. qry.transaction := Transaction;
  539. qry.database := Self;
  540. with qry do
  541. begin
  542. ParseSQL := False;
  543. SetSchemaInfo(ASchemaType,ASchemaObjectName,'');
  544. open;
  545. AList.Clear;
  546. while not eof do
  547. begin
  548. AList.Append(trim(fieldbyname(AReturnField).asstring));
  549. Next;
  550. end;
  551. end;
  552. qry.free;
  553. end;
  554. function TSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
  555. begin
  556. Result := -1;
  557. end;
  558. constructor TSQLConnection.Create(AOwner: TComponent);
  559. begin
  560. inherited Create(AOwner);
  561. FSQLServerFormatSettings.DecimalSeparator:='.';
  562. FFieldNameQuoteChars:=DoubleQuotes;
  563. end;
  564. procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
  565. begin
  566. if not systemtables then GetDBInfo(stTables,'','table_name',List)
  567. else GetDBInfo(stSysTables,'','table_name',List);
  568. end;
  569. procedure TSQLConnection.GetProcedureNames(List: TStrings);
  570. begin
  571. GetDBInfo(stProcedures,'','proc_name',List);
  572. end;
  573. procedure TSQLConnection.GetFieldNames(const TableName: string; List: TStrings);
  574. begin
  575. GetDBInfo(stColumns,TableName,'column_name',List);
  576. end;
  577. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  578. begin
  579. if (not assigned(field)) or field.IsNull then Result := 'Null'
  580. else case field.DataType of
  581. ftString : Result := '''' + field.asstring + '''';
  582. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Field.AsDateTime) + '''';
  583. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Field.AsDateTime) + ''''
  584. else
  585. Result := field.asstring;
  586. end; {case}
  587. end;
  588. function TSQLConnection.GetAsSQLText(Param: TParam) : string;
  589. begin
  590. if (not assigned(param)) or param.IsNull then Result := 'Null'
  591. else case param.DataType of
  592. ftString : Result := '''' + param.asstring + '''';
  593. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Param.AsDateTime) + '''';
  594. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:mm:ss',Param.AsDateTime) + '''';
  595. ftFloat : Result := '''' + FloatToStr(Param.AsFloat, FSQLServerFormatSettings) + ''''
  596. else
  597. Result := Param.asstring;
  598. end; {case}
  599. end;
  600. function TSQLConnection.GetHandle: pointer;
  601. begin
  602. Result := nil;
  603. end;
  604. function TSQLConnection.LogEvent(EventType: TDBEventType): Boolean;
  605. begin
  606. Result:=(Assigned(FOnLog) or Assigned(GlobalDBLogHook)) and (EventType in LogEvents);
  607. end;
  608. procedure TSQLConnection.Log(EventType: TDBEventType; const Msg: String);
  609. Var
  610. M : String;
  611. begin
  612. If LogEvent(EventType) then
  613. begin
  614. If Assigned(FonLog) then
  615. FOnLog(Self,EventType,Msg);
  616. If Assigned(GlobalDBLogHook) then
  617. begin
  618. If (Name<>'') then
  619. M:=Name+' : '+Msg
  620. else
  621. M:=ClassName+' : '+Msg;
  622. GlobalDBLogHook(Self,EventType,M);
  623. end;
  624. end;
  625. end;
  626. procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
  627. begin
  628. // empty
  629. end;
  630. function TSQLConnection.GetSchemaInfoSQL( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string;
  631. begin
  632. DatabaseError(SMetadataUnavailable);
  633. end;
  634. procedure TSQLConnection.CreateDB;
  635. begin
  636. DatabaseError(SNotSupported);
  637. end;
  638. procedure TSQLConnection.DropDB;
  639. begin
  640. DatabaseError(SNotSupported);
  641. end;
  642. { TSQLTransaction }
  643. procedure TSQLTransaction.EndTransaction;
  644. begin
  645. rollback;
  646. end;
  647. procedure TSQLTransaction.SetParams(const AValue: TStringList);
  648. begin
  649. FParams.Assign(AValue);
  650. end;
  651. function TSQLTransaction.GetHandle: pointer;
  652. begin
  653. Result := TSQLConnection(Database).GetTransactionHandle(FTrans);
  654. end;
  655. procedure TSQLTransaction.Commit;
  656. begin
  657. if active then
  658. begin
  659. closedatasets;
  660. If LogEvent(detCommit) then
  661. Log(detCommit,SCommitting);
  662. if TSQLConnection(Database).commit(FTrans) then
  663. begin
  664. closeTrans;
  665. FreeAndNil(FTrans);
  666. end;
  667. end;
  668. end;
  669. procedure TSQLTransaction.CommitRetaining;
  670. begin
  671. if active then
  672. begin
  673. If LogEvent(detCommit) then
  674. Log(detCommit,SCommitRetaining);
  675. TSQLConnection(Database).commitRetaining(FTrans);
  676. end;
  677. end;
  678. procedure TSQLTransaction.Rollback;
  679. begin
  680. if active then
  681. begin
  682. closedatasets;
  683. If LogEvent(detRollback) then
  684. Log(detRollback,SRollingBack);
  685. if TSQLConnection(Database).RollBack(FTrans) then
  686. begin
  687. CloseTrans;
  688. FreeAndNil(FTrans);
  689. end;
  690. end;
  691. end;
  692. procedure TSQLTransaction.RollbackRetaining;
  693. begin
  694. if active then
  695. begin
  696. If LogEvent(detRollback) then
  697. Log(detRollback,SRollBackRetaining);
  698. TSQLConnection(Database).RollBackRetaining(FTrans);
  699. end;
  700. end;
  701. procedure TSQLTransaction.StartTransaction;
  702. var db : TSQLConnection;
  703. begin
  704. if Active then
  705. DatabaseError(SErrTransAlreadyActive);
  706. db := TSQLConnection(Database);
  707. if Db = nil then
  708. DatabaseError(SErrDatabasenAssigned);
  709. if not Db.Connected then
  710. Db.Open;
  711. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  712. if Db.StartdbTransaction(FTrans,FParams.CommaText) then OpenTrans;
  713. end;
  714. constructor TSQLTransaction.Create(AOwner : TComponent);
  715. begin
  716. inherited Create(AOwner);
  717. FParams := TStringList.Create;
  718. end;
  719. destructor TSQLTransaction.Destroy;
  720. begin
  721. Rollback;
  722. FreeAndNil(FParams);
  723. inherited Destroy;
  724. end;
  725. Procedure TSQLTransaction.SetDatabase(Value : TDatabase);
  726. begin
  727. If Value<>Database then
  728. begin
  729. if assigned(value) and not (Value is TSQLConnection) then
  730. DatabaseErrorFmt(SErrNotASQLConnection,[value.Name],self);
  731. CheckInactive;
  732. If Assigned(Database) then
  733. with TSQLConnection(DataBase) do
  734. if Transaction = self then Transaction := nil;
  735. inherited SetDatabase(Value);
  736. If Assigned(Database) and not (csLoading in ComponentState) then
  737. If (TSQLConnection(DataBase).Transaction=Nil) then
  738. TSQLConnection(DataBase).Transaction:=Self;
  739. end;
  740. end;
  741. function TSQLTransaction.LogEvent(EventType: TDBEventType): Boolean;
  742. begin
  743. Result:=Assigned(Database) and TSQLConnection(Database).LogEvent(EventType);
  744. end;
  745. procedure TSQLTransaction.Log(EventType: TDBEventType; const Msg: String);
  746. Var
  747. M : String;
  748. begin
  749. If LogEVent(EventType) then
  750. begin
  751. If (Name<>'') then
  752. M:=Name+' : '+Msg
  753. else
  754. M:=Msg;
  755. TSQLConnection(Database).Log(EventType,M);
  756. end;
  757. end;
  758. { TCustomSQLQuery }
  759. procedure TCustomSQLQuery.OnChangeSQL(Sender : TObject);
  760. var ConnOptions : TConnOptions;
  761. begin
  762. UnPrepare;
  763. FSchemaType:=stNoSchema;
  764. if (FSQL <> nil) then
  765. begin
  766. if assigned(DataBase) then
  767. ConnOptions := TSQLConnection(DataBase).ConnOptions
  768. else
  769. ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
  770. Fparams.ParseSQL(FSQL.Text,True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase);
  771. If Assigned(FMasterLink) then
  772. FMasterLink.RefreshParamNames;
  773. end;
  774. end;
  775. function TCustomSQLQuery.ParamByName(Const AParamName : String) : TParam;
  776. begin
  777. Result:=Params.ParamByName(AParamName);
  778. end;
  779. procedure TCustomSQLQuery.OnChangeModifySQL(Sender : TObject);
  780. begin
  781. CheckInactive;
  782. end;
  783. Procedure TCustomSQLQuery.SetTransaction(Value : TDBTransaction);
  784. begin
  785. UnPrepare;
  786. inherited;
  787. If (Transaction<>Nil) and (Database=Nil) then
  788. Database:=TSQLTransaction(Transaction).Database;
  789. end;
  790. procedure TCustomSQLQuery.SetDatabase(Value : TDatabase);
  791. var db : tsqlconnection;
  792. begin
  793. if (Database <> Value) then
  794. begin
  795. if assigned(value) and not (Value is TSQLConnection) then
  796. DatabaseErrorFmt(SErrNotASQLConnection,[value.Name],self);
  797. UnPrepare;
  798. if assigned(FCursor) then TSQLConnection(DataBase).DeAllocateCursorHandle(FCursor);
  799. db := TSQLConnection(Value);
  800. inherited setdatabase(value);
  801. if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
  802. transaction := Db.Transaction;
  803. OnChangeSQL(Self);
  804. end;
  805. end;
  806. Function TCustomSQLQuery.IsPrepared : Boolean;
  807. begin
  808. Result := Assigned(FCursor) and FCursor.FPrepared;
  809. end;
  810. Function TCustomSQLQuery.AddFilter(SQLstr : string) : string;
  811. begin
  812. if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
  813. begin
  814. system.insert('(',SQLstr,FWhereStartPos+1);
  815. system.insert(')',SQLstr,FWhereStopPos+1);
  816. end;
  817. if FWhereStartPos = 0 then
  818. SQLstr := SQLstr + ' where (' + Filter + ')'
  819. else if FWhereStopPos > 0 then
  820. system.insert(' and ('+ServerFilter+') ',SQLstr,FWhereStopPos+2)
  821. else
  822. system.insert(' where ('+ServerFilter+') ',SQLstr,FWhereStartPos);
  823. Result := SQLstr;
  824. end;
  825. procedure TCustomSQLQuery.ApplyFilter;
  826. var S : String;
  827. begin
  828. FreeFldBuffers;
  829. TSQLConnection(Database).UnPrepareStatement(FCursor);
  830. FIsEOF := False;
  831. inherited internalclose;
  832. s := FSQLBuf;
  833. if ServerFiltered then s := AddFilter(s);
  834. TSQLConnection(Database).PrepareStatement(Fcursor,(transaction as tsqltransaction),S,FParams);
  835. Execute;
  836. inherited InternalOpen;
  837. First;
  838. end;
  839. Procedure TCustomSQLQuery.SetActive (Value : Boolean);
  840. begin
  841. inherited SetActive(Value);
  842. // The query is UnPrepared, so that if a transaction closes all datasets
  843. // they also get unprepared
  844. if not Value and IsPrepared then UnPrepare;
  845. end;
  846. procedure TCustomSQLQuery.SetServerFiltered(Value: Boolean);
  847. begin
  848. if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
  849. if (ServerFiltered <> Value) then
  850. begin
  851. FServerFiltered := Value;
  852. if active then ApplyFilter;
  853. end;
  854. end;
  855. procedure TCustomSQLQuery.SetServerFilterText(const Value: string);
  856. begin
  857. if Value <> ServerFilter then
  858. begin
  859. FServerFilterText := Value;
  860. if active then ApplyFilter;
  861. end;
  862. end;
  863. procedure TCustomSQLQuery.Prepare;
  864. var
  865. db : tsqlconnection;
  866. sqltr : tsqltransaction;
  867. StmType: TStatementType;
  868. begin
  869. if not IsPrepared then
  870. begin
  871. db := TSQLConnection(Database);
  872. sqltr := (transaction as tsqltransaction);
  873. if not assigned(Db) then
  874. DatabaseError(SErrDatabasenAssigned);
  875. if not assigned(sqltr) then
  876. DatabaseError(SErrTransactionnSet);
  877. if not Db.Connected then db.Open;
  878. if not sqltr.Active then sqltr.StartTransaction;
  879. if FSchemaType=stNoSchema then
  880. FSQLBuf := TrimRight(FSQL.Text)
  881. else
  882. FSQLBuf := db.GetSchemaInfoSQL(FSchemaType, FSchemaObjectName, FSchemaPattern);
  883. if FSQLBuf = '' then
  884. DatabaseError(SErrNoStatement);
  885. StmType:=SQLParser(FSQLBuf);
  886. // There may no error occur between the allocation of the cursor and
  887. // the preparation of the cursor. Because internalclose (which is called in
  888. // case of an exception) assumes that allocated cursors are also prepared,
  889. // and thus calls unprepare.
  890. // A call to unprepare while the cursor is not prepared at all can lead to
  891. // unpredictable results.
  892. if not assigned(fcursor) then
  893. FCursor := Db.AllocateCursorHandle;
  894. FCursor.FStatementType:=StmType;
  895. FCursor.FSchemaType := FSchemaType;
  896. if ServerFiltered then
  897. begin
  898. If LogEvent(detprepare) then
  899. Log(detPrepare,AddFilter(FSQLBuf));
  900. Db.PrepareStatement(Fcursor,sqltr,AddFilter(FSQLBuf),FParams)
  901. end
  902. else
  903. begin
  904. If LogEvent(detprepare) then
  905. Log(detPrepare,FSQLBuf);
  906. Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
  907. end;
  908. if (FCursor.FStatementType in [stSelect,stExecProcedure]) then
  909. FCursor.FInitFieldDef := True;
  910. end;
  911. end;
  912. procedure TCustomSQLQuery.UnPrepare;
  913. begin
  914. CheckInactive;
  915. if IsPrepared then with TSQLConnection(DataBase) do
  916. UnPrepareStatement(FCursor);
  917. end;
  918. procedure TCustomSQLQuery.FreeFldBuffers;
  919. begin
  920. if assigned(FCursor) then TSQLConnection(Database).FreeFldBuffers(FCursor);
  921. end;
  922. function TCustomSQLQuery.GetServerIndexDefs: TServerIndexDefs;
  923. begin
  924. Result := FServerIndexDefs;
  925. end;
  926. function TCustomSQLQuery.Fetch : boolean;
  927. begin
  928. if not (Fcursor.FStatementType in [stSelect,stExecProcedure]) then
  929. Exit;
  930. if not FIsEof then FIsEOF := not TSQLConnection(Database).Fetch(Fcursor);
  931. Result := not FIsEOF;
  932. // A stored procedure is always at EOF after its first fetch
  933. if FCursor.FStatementType = stExecProcedure then FIsEOF := True;
  934. end;
  935. procedure TCustomSQLQuery.Execute;
  936. begin
  937. If (FParams.Count>0) and Assigned(FMasterLink) then
  938. FMasterLink.CopyParamsFromMaster(False);
  939. If LogEvent(detExecute) then
  940. Log(detExecute,FSQLBuf);
  941. TSQLConnection(Database).execute(Fcursor,Transaction as tsqltransaction, FParams);
  942. end;
  943. function TCustomSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  944. begin
  945. result := TSQLConnection(Database).LoadField(FCursor,FieldDef,buffer, Createblob)
  946. end;
  947. function TCustomSQLQuery.RowsAffected: TRowsCount;
  948. begin
  949. Result := -1;
  950. if not Assigned(Database) then Exit;
  951. //assert(Database is TSQLConnection);
  952. Result := TSQLConnection(Database).RowsAffected(FCursor);
  953. end;
  954. procedure TCustomSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  955. begin
  956. // not implemented - sql dataset
  957. end;
  958. procedure TCustomSQLQuery.InternalClose;
  959. begin
  960. if not IsReadFromPacket then
  961. begin
  962. if StatementType in [stSelect,stExecProcedure] then FreeFldBuffers;
  963. // Database and FCursor could be nil, for example if the database is not assigned, and .open is called
  964. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then TSQLConnection(database).UnPrepareStatement(FCursor);
  965. end;
  966. if DefaultFields then
  967. DestroyFields;
  968. FIsEOF := False;
  969. if assigned(FUpdateQry) then FreeAndNil(FUpdateQry);
  970. if assigned(FInsertQry) then FreeAndNil(FInsertQry);
  971. if assigned(FDeleteQry) then FreeAndNil(FDeleteQry);
  972. // FRecordSize := 0;
  973. inherited internalclose;
  974. end;
  975. procedure TCustomSQLQuery.InternalInitFieldDefs;
  976. begin
  977. if FLoadingFieldDefs then
  978. Exit;
  979. FLoadingFieldDefs := True;
  980. try
  981. FieldDefs.Clear;
  982. TSQLConnection(Database).AddFieldDefs(fcursor,FieldDefs);
  983. finally
  984. FLoadingFieldDefs := False;
  985. FCursor.FInitFieldDef := false;
  986. end;
  987. end;
  988. function TCustomSQLQuery.SQLParser(const ASQL : string) : TStatementType;
  989. type TParsePart = (ppStart,ppSelect,ppWhere,ppFrom,ppOrder,ppComment,ppGroup,ppBogus);
  990. Var
  991. PSQL,CurrentP,
  992. PhraseP, PStatementPart : pchar;
  993. S : string;
  994. ParsePart : TParsePart;
  995. StrLength : Integer;
  996. EndOfComment : Boolean;
  997. BracketCount : Integer;
  998. ConnOptions : TConnOptions;
  999. FFromPart : String;
  1000. begin
  1001. PSQL:=Pchar(ASQL);
  1002. ParsePart := ppStart;
  1003. CurrentP := PSQL-1;
  1004. PhraseP := PSQL;
  1005. FWhereStartPos := 0;
  1006. FWhereStopPos := 0;
  1007. ConnOptions := TSQLConnection(DataBase).ConnOptions;
  1008. FUpdateable := False;
  1009. repeat
  1010. begin
  1011. inc(CurrentP);
  1012. EndOfComment := SkipComments(CurrentP,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
  1013. if EndOfcomment then dec(currentp);
  1014. if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;
  1015. // skip everything between bracket, since it could be a sub-select, and
  1016. // further nothing between brackets could be interesting for the parser.
  1017. if currentp^='(' then
  1018. begin
  1019. inc(currentp);
  1020. BracketCount := 0;
  1021. while (currentp^ <> #0) and ((currentp^ <> ')') or (BracketCount > 0 )) do
  1022. begin
  1023. if currentp^ = '(' then inc(bracketcount)
  1024. else if currentp^ = ')' then dec(bracketcount);
  1025. inc(currentp);
  1026. end;
  1027. EndOfComment := True;
  1028. end;
  1029. if EndOfComment or (CurrentP^ in [' ',#13,#10,#9,#0,';']) then
  1030. begin
  1031. if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
  1032. begin
  1033. strLength := CurrentP-PhraseP;
  1034. Setlength(S,strLength);
  1035. if strLength > 0 then Move(PhraseP^,S[1],(strLength));
  1036. s := uppercase(s);
  1037. case ParsePart of
  1038. ppStart : begin
  1039. Result := TSQLConnection(Database).StrToStatementType(s);
  1040. if Result = stSelect then ParsePart := ppSelect
  1041. else break;
  1042. if not FParseSQL then break;
  1043. PStatementPart := CurrentP;
  1044. end;
  1045. ppSelect : begin
  1046. if s = 'FROM' then
  1047. begin
  1048. ParsePart := ppFrom;
  1049. PhraseP := CurrentP;
  1050. PStatementPart := CurrentP;
  1051. end;
  1052. end;
  1053. ppFrom : begin
  1054. if (s = 'WHERE') or (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') or (CurrentP^=#0) or (CurrentP^=';') then
  1055. begin
  1056. if (s = 'WHERE') then
  1057. begin
  1058. ParsePart := ppWhere;
  1059. StrLength := PhraseP-PStatementPart;
  1060. end
  1061. else if (s = 'GROUP') then
  1062. begin
  1063. ParsePart := ppGroup;
  1064. StrLength := PhraseP-PStatementPart;
  1065. end
  1066. else if (s = 'ORDER') then
  1067. begin
  1068. ParsePart := ppOrder;
  1069. StrLength := PhraseP-PStatementPart
  1070. end
  1071. else if (s = 'LIMIT') then
  1072. begin
  1073. ParsePart := ppBogus;
  1074. StrLength := PhraseP-PStatementPart
  1075. end
  1076. else
  1077. begin
  1078. ParsePart := ppBogus;
  1079. StrLength := CurrentP-PStatementPart;
  1080. end;
  1081. if Result = stSelect then
  1082. begin
  1083. Setlength(FFromPart,StrLength);
  1084. Move(PStatementPart^,FFromPart[1],(StrLength));
  1085. FFrompart := trim(FFrompart);
  1086. // Meta-data requests and are never updateable select-statements
  1087. // from more then one table are not updateable
  1088. if (FSchemaType=stNoSchema) and
  1089. (ExtractStrings([',',' '],[],pchar(FFromPart),nil) = 1) then
  1090. begin
  1091. FUpdateable := True;
  1092. FTableName := FFromPart;
  1093. end;
  1094. end;
  1095. FWhereStartPos := PStatementPart-PSQL+StrLength+1;
  1096. PStatementPart := CurrentP;
  1097. end;
  1098. end;
  1099. ppWhere : begin
  1100. if (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') or (CurrentP^=#0) or (CurrentP^=';') then
  1101. begin
  1102. ParsePart := ppBogus;
  1103. FWhereStartPos := PStatementPart-PSQL;
  1104. if (s = 'ORDER') or (s = 'GROUP') or (s = 'LIMIT') then
  1105. FWhereStopPos := PhraseP-PSQL+1
  1106. else
  1107. FWhereStopPos := CurrentP-PSQL+1;
  1108. end
  1109. else if (s = 'UNION') then
  1110. begin
  1111. ParsePart := ppBogus;
  1112. FUpdateable := False;
  1113. end;
  1114. end;
  1115. end; {case}
  1116. end;
  1117. PhraseP := CurrentP+1;
  1118. end
  1119. end;
  1120. until CurrentP^=#0;
  1121. end;
  1122. procedure TCustomSQLQuery.InternalOpen;
  1123. var tel, fieldc : integer;
  1124. f : TField;
  1125. s : string;
  1126. IndexFields : TStrings;
  1127. ReadFromFile: Boolean;
  1128. begin
  1129. ReadFromFile:=IsReadFromPacket;
  1130. if ReadFromFile then
  1131. begin
  1132. if not assigned(fcursor) then
  1133. FCursor := TSQLConnection(Database).AllocateCursorHandle;
  1134. FCursor.FStatementType:=stSelect;
  1135. FUpdateable:=True;
  1136. end
  1137. else
  1138. Prepare;
  1139. if FCursor.FStatementType in [stSelect,stExecProcedure] then
  1140. begin
  1141. if not ReadFromFile then
  1142. begin
  1143. // Call UpdateServerIndexDefs before Execute, to avoid problems with connections
  1144. // which do not allow processing multiple recordsets at a time. (Microsoft
  1145. // calls this MARS, see bug 13241)
  1146. if DefaultFields and FUpdateable and FusePrimaryKeyAsKey and (not IsUniDirectional) then
  1147. UpdateServerIndexDefs;
  1148. Execute;
  1149. // InternalInitFieldDef is only called after a prepare. i.e. not twice if
  1150. // a dataset is opened - closed - opened.
  1151. if FCursor.FInitFieldDef then InternalInitFieldDefs;
  1152. if DefaultFields then
  1153. begin
  1154. CreateFields;
  1155. if FUpdateable and (not IsUniDirectional) then
  1156. begin
  1157. if FusePrimaryKeyAsKey then
  1158. begin
  1159. for tel := 0 to ServerIndexDefs.count-1 do
  1160. begin
  1161. if ixPrimary in ServerIndexDefs[tel].options then
  1162. begin
  1163. IndexFields := TStringList.Create;
  1164. ExtractStrings([';'],[' '],pchar(ServerIndexDefs[tel].fields),IndexFields);
  1165. for fieldc := 0 to IndexFields.Count-1 do
  1166. begin
  1167. F := Findfield(IndexFields[fieldc]);
  1168. if F <> nil then
  1169. F.ProviderFlags := F.ProviderFlags + [pfInKey];
  1170. end;
  1171. IndexFields.Free;
  1172. end;
  1173. end;
  1174. end;
  1175. end;
  1176. end
  1177. else
  1178. BindFields(True);
  1179. end
  1180. else
  1181. BindFields(True);
  1182. if not ReadOnly and not FUpdateable and (FSchemaType=stNoSchema) then
  1183. begin
  1184. if (trim(FDeleteSQL.Text) <> '') or (trim(FUpdateSQL.Text) <> '') or
  1185. (trim(FInsertSQL.Text) <> '') then FUpdateable := True;
  1186. end
  1187. end
  1188. else
  1189. DatabaseError(SErrNoSelectStatement,Self);
  1190. inherited InternalOpen;
  1191. end;
  1192. // public part
  1193. procedure TCustomSQLQuery.ExecSQL;
  1194. begin
  1195. try
  1196. Prepare;
  1197. Execute;
  1198. finally
  1199. // FCursor has to be assigned, or else the prepare went wrong before PrepareStatment was
  1200. // called, so UnPrepareStatement shoudn't be called either
  1201. if (not IsPrepared) and (assigned(database)) and (assigned(FCursor)) then TSQLConnection(database).UnPrepareStatement(Fcursor);
  1202. end;
  1203. end;
  1204. constructor TCustomSQLQuery.Create(AOwner : TComponent);
  1205. begin
  1206. inherited Create(AOwner);
  1207. FParams := TParams.create(self);
  1208. FSQL := TStringList.Create;
  1209. FSQL.OnChange := @OnChangeSQL;
  1210. FUpdateSQL := TStringList.Create;
  1211. FUpdateSQL.OnChange := @OnChangeModifySQL;
  1212. FInsertSQL := TStringList.Create;
  1213. FInsertSQL.OnChange := @OnChangeModifySQL;
  1214. FDeleteSQL := TStringList.Create;
  1215. FDeleteSQL.OnChange := @OnChangeModifySQL;
  1216. FServerIndexDefs := TServerIndexDefs.Create(Self);
  1217. FReadOnly := false;
  1218. FParseSQL := True;
  1219. FServerFiltered := False;
  1220. FServerFilterText := '';
  1221. FSchemaType:=stNoSchema;
  1222. FSchemaObjectName:='';
  1223. FSchemaPattern:='';
  1224. // Delphi has upWhereAll as default, but since strings and oldvalue's don't work yet
  1225. // (variants) set it to upWhereKeyOnly
  1226. FUpdateMode := upWhereKeyOnly;
  1227. FUsePrimaryKeyAsKey := True;
  1228. end;
  1229. destructor TCustomSQLQuery.Destroy;
  1230. begin
  1231. if Active then Close;
  1232. UnPrepare;
  1233. if assigned(FCursor) then TSQLConnection(Database).DeAllocateCursorHandle(FCursor);
  1234. FreeAndNil(FMasterLink);
  1235. FreeAndNil(FParams);
  1236. FreeAndNil(FSQL);
  1237. FreeAndNil(FInsertSQL);
  1238. FreeAndNil(FDeleteSQL);
  1239. FreeAndNil(FUpdateSQL);
  1240. FServerIndexDefs.Free;
  1241. inherited Destroy;
  1242. end;
  1243. procedure TCustomSQLQuery.SetReadOnly(AValue : Boolean);
  1244. begin
  1245. CheckInactive;
  1246. FReadOnly:=AValue;
  1247. end;
  1248. procedure TCustomSQLQuery.SetParseSQL(AValue : Boolean);
  1249. begin
  1250. CheckInactive;
  1251. if not AValue then
  1252. begin
  1253. FServerFiltered := False;
  1254. FParseSQL := False;
  1255. end
  1256. else
  1257. FParseSQL := True;
  1258. end;
  1259. procedure TCustomSQLQuery.SetSQL(const AValue: TStringlist);
  1260. begin
  1261. FSQL.Assign(AValue);
  1262. end;
  1263. procedure TCustomSQLQuery.SetUpdateSQL(const AValue: TStringlist);
  1264. begin
  1265. FUpdateSQL.Assign(AValue);
  1266. end;
  1267. procedure TCustomSQLQuery.SetUsePrimaryKeyAsKey(AValue : Boolean);
  1268. begin
  1269. if not Active then FusePrimaryKeyAsKey := AValue
  1270. else
  1271. begin
  1272. // Just temporary, this should be possible in the future
  1273. DatabaseError(SActiveDataset);
  1274. end;
  1275. end;
  1276. Procedure TCustomSQLQuery.UpdateServerIndexDefs;
  1277. begin
  1278. FServerIndexDefs.Clear;
  1279. if assigned(DataBase) and (FTableName<>'') then
  1280. TSQLConnection(DataBase).UpdateIndexDefs(ServerIndexDefs,FTableName);
  1281. end;
  1282. Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
  1283. var FieldNamesQuoteChars : TQuoteChars;
  1284. procedure InitialiseModifyQuery(var qry : TCustomSQLQuery; aSQL: String);
  1285. begin
  1286. qry := TCustomSQLQuery.Create(nil);
  1287. with qry do
  1288. begin
  1289. ParseSQL := False;
  1290. DataBase := Self.DataBase;
  1291. Transaction := Self.Transaction;
  1292. SQL.text := aSQL;
  1293. end;
  1294. end;
  1295. procedure UpdateWherePart(var sql_where : string;x : integer);
  1296. begin
  1297. if (pfInKey in Fields[x].ProviderFlags) or
  1298. ((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
  1299. ((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
  1300. sql_where := sql_where + '(' + FieldNamesQuoteChars[0] + fields[x].FieldName + FieldNamesQuoteChars[1] + '= :"' + 'OLD_' + fields[x].FieldName + '") and ';
  1301. end;
  1302. function ModifyRecQuery : string;
  1303. var x : integer;
  1304. sql_set : string;
  1305. sql_where : string;
  1306. begin
  1307. sql_set := '';
  1308. sql_where := '';
  1309. for x := 0 to Fields.Count -1 do
  1310. begin
  1311. UpdateWherePart(sql_where,x);
  1312. if (pfInUpdate in Fields[x].ProviderFlags) then
  1313. sql_set := sql_set +FieldNamesQuoteChars[0] + fields[x].FieldName + FieldNamesQuoteChars[1] +'=:"' + fields[x].FieldName + '",';
  1314. end;
  1315. if length(sql_set) = 0 then DatabaseErrorFmt(sNoUpdateFields,['update'],self);
  1316. setlength(sql_set,length(sql_set)-1);
  1317. if length(sql_where) = 0 then DatabaseErrorFmt(sNoWhereFields,['update'],self);
  1318. setlength(sql_where,length(sql_where)-5);
  1319. result := 'update ' + FTableName + ' set ' + sql_set + ' where ' + sql_where;
  1320. end;
  1321. function InsertRecQuery : string;
  1322. var x : integer;
  1323. sql_fields : string;
  1324. sql_values : string;
  1325. begin
  1326. sql_fields := '';
  1327. sql_values := '';
  1328. for x := 0 to Fields.Count -1 do
  1329. begin
  1330. if (not fields[x].IsNull) and (pfInUpdate in Fields[x].ProviderFlags) then
  1331. begin
  1332. sql_fields := sql_fields + FieldNamesQuoteChars[0] + fields[x].FieldName + FieldNamesQuoteChars[1] + ',';
  1333. sql_values := sql_values + ':"' + fields[x].FieldName + '",';
  1334. end;
  1335. end;
  1336. if length(sql_fields) = 0 then DatabaseErrorFmt(sNoUpdateFields,['insert'],self);
  1337. setlength(sql_fields,length(sql_fields)-1);
  1338. setlength(sql_values,length(sql_values)-1);
  1339. result := 'insert into ' + FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
  1340. end;
  1341. function DeleteRecQuery : string;
  1342. var x : integer;
  1343. sql_where : string;
  1344. begin
  1345. sql_where := '';
  1346. for x := 0 to Fields.Count -1 do
  1347. UpdateWherePart(sql_where,x);
  1348. if length(sql_where) = 0 then DatabaseErrorFmt(sNoWhereFields,['delete'],self);
  1349. setlength(sql_where,length(sql_where)-5);
  1350. result := 'delete from ' + FTableName + ' where ' + sql_where;
  1351. end;
  1352. var qry : TCustomSQLQuery;
  1353. x : integer;
  1354. Fld : TField;
  1355. begin
  1356. FieldNamesQuoteChars := TSQLConnection(DataBase).FieldNameQuoteChars;
  1357. case UpdateKind of
  1358. ukModify : begin
  1359. if not assigned(FUpdateQry) then
  1360. begin
  1361. if (trim(FUpdateSQL.Text)<> '') then
  1362. InitialiseModifyQuery(FUpdateQry,FUpdateSQL.Text)
  1363. else
  1364. InitialiseModifyQuery(FUpdateQry,ModifyRecQuery);
  1365. end;
  1366. qry := FUpdateQry;
  1367. end;
  1368. ukInsert : begin
  1369. if not assigned(FInsertQry) then
  1370. begin
  1371. if (trim(FInsertSQL.Text)<> '') then
  1372. InitialiseModifyQuery(FInsertQry,FInsertSQL.Text)
  1373. else
  1374. InitialiseModifyQuery(FInsertQry,InsertRecQuery);
  1375. end;
  1376. qry := FInsertQry;
  1377. end;
  1378. ukDelete : begin
  1379. if not assigned(FDeleteQry) then
  1380. begin
  1381. if (trim(FDeleteSQL.Text)<> '') then
  1382. InitialiseModifyQuery(FDeleteQry,FDeleteSQL.Text)
  1383. else
  1384. InitialiseModifyQuery(FDeleteQry,DeleteRecQuery);
  1385. end;
  1386. qry := FDeleteQry;
  1387. end;
  1388. end;
  1389. assert(qry.sql.Text<>'');
  1390. with qry do
  1391. begin
  1392. for x := 0 to Params.Count-1 do with params[x] do if leftstr(name,4)='OLD_' then
  1393. begin
  1394. Fld := self.FieldByName(copy(name,5,length(name)-4));
  1395. AssignFieldValue(Fld,Fld.OldValue);
  1396. end
  1397. else
  1398. begin
  1399. Fld := self.FieldByName(name);
  1400. AssignFieldValue(Fld,Fld.Value);
  1401. end;
  1402. execsql;
  1403. end;
  1404. end;
  1405. Function TCustomSQLQuery.GetCanModify: Boolean;
  1406. begin
  1407. // the test for assigned(FCursor) is needed for the case that the dataset isn't opened
  1408. if assigned(FCursor) and (FCursor.FStatementType = stSelect) then
  1409. Result:= FUpdateable and (not FReadOnly) and (not IsUniDirectional)
  1410. else
  1411. Result := False;
  1412. end;
  1413. procedure TCustomSQLQuery.SetUpdateMode(AValue : TUpdateMode);
  1414. begin
  1415. FUpdateMode := AValue;
  1416. end;
  1417. procedure TCustomSQLQuery.SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string);
  1418. begin
  1419. FSchemaType:=ASchemaType;
  1420. FSchemaObjectName:=ASchemaObjectName;
  1421. FSchemaPattern:=ASchemaPattern;
  1422. end;
  1423. procedure TCustomSQLQuery.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1424. ABlobBuf: PBufBlobField);
  1425. begin
  1426. TSQLConnection(DataBase).LoadBlobIntoBuffer(FieldDef, ABlobBuf, FCursor,(Transaction as tsqltransaction));
  1427. end;
  1428. procedure TCustomSQLQuery.BeforeRefreshOpenCursor;
  1429. begin
  1430. // This is only necessary because TIBConnection can not re-open a
  1431. // prepared cursor. In fact this is wrong, but has never led to
  1432. // problems because in SetActive(false) queries are always
  1433. // unprepared. (which is also wrong, but has to be fixed later)
  1434. if IsPrepared then with TSQLConnection(DataBase) do
  1435. UnPrepareStatement(FCursor);
  1436. end;
  1437. function TCustomSQLQuery.LogEvent(EventType: TDBEventType): Boolean;
  1438. begin
  1439. Result:=Assigned(Database) and TSQLConnection(Database).LogEvent(EventType);
  1440. end;
  1441. procedure TCustomSQLQuery.Log(EventType: TDBEventType; const Msg: String);
  1442. Var
  1443. M : String;
  1444. begin
  1445. If LogEvent(EventType) then
  1446. begin
  1447. M:=Msg;
  1448. If (Name<>'') then
  1449. M:=Name+' : '+M;
  1450. TSQLConnection(Database).Log(EventType,M);
  1451. end;
  1452. end;
  1453. function TCustomSQLQuery.GetStatementType : TStatementType;
  1454. begin
  1455. if assigned(FCursor) then Result := FCursor.FStatementType
  1456. else Result := stNone;
  1457. end;
  1458. procedure TCustomSQLQuery.SetDeleteSQL(const AValue: TStringlist);
  1459. begin
  1460. FDeleteSQL.Assign(AValue);
  1461. end;
  1462. procedure TCustomSQLQuery.SetInsertSQL(const AValue: TStringlist);
  1463. begin
  1464. FInsertSQL.Assign(AValue);
  1465. end;
  1466. Procedure TCustomSQLQuery.SetDataSource(AVAlue : TDatasource);
  1467. Var
  1468. DS : TDatasource;
  1469. begin
  1470. DS:=DataSource;
  1471. If (AValue<>DS) then
  1472. begin
  1473. If Assigned(AValue) and (AValue.Dataset=Self) then
  1474. DatabaseError(SErrCircularDataSourceReferenceNotAllowed,Self);
  1475. If Assigned(DS) then
  1476. DS.RemoveFreeNotification(Self);
  1477. If Assigned(AValue) then
  1478. begin
  1479. AValue.FreeNotification(Self);
  1480. If (FMasterLink=Nil) then
  1481. FMasterLink:=TMasterParamsDataLink.Create(Self);
  1482. FMasterLink.Datasource:=AValue;
  1483. end
  1484. else
  1485. FreeAndNil(FMasterLink);
  1486. end;
  1487. end;
  1488. Function TCustomSQLQuery.GetDataSource : TDatasource;
  1489. begin
  1490. If Assigned(FMasterLink) then
  1491. Result:=FMasterLink.DataSource
  1492. else
  1493. Result:=Nil;
  1494. end;
  1495. procedure TCustomSQLQuery.Notification(AComponent: TComponent; Operation: TOperation);
  1496. begin
  1497. Inherited;
  1498. If (Operation=opRemove) and (AComponent=DataSource) then
  1499. DataSource:=Nil;
  1500. end;
  1501. { TSQLScript }
  1502. procedure TSQLScript.ExecuteStatement(SQLStatement: TStrings;
  1503. var StopExecution: Boolean);
  1504. begin
  1505. fquery.SQL.assign(SQLStatement);
  1506. fquery.ExecSQL;
  1507. end;
  1508. procedure TSQLScript.ExecuteDirective(Directive, Argument: String;
  1509. var StopExecution: Boolean);
  1510. begin
  1511. if assigned (FOnDirective) then
  1512. FOnDirective (Self, Directive, Argument, StopExecution);
  1513. end;
  1514. procedure TSQLScript.ExecuteCommit;
  1515. begin
  1516. if FTransaction is TSQLTransaction then
  1517. TSQLTransaction(FTransaction).CommitRetaining
  1518. else
  1519. begin
  1520. FTransaction.Active := false;
  1521. FTransaction.Active := true;
  1522. end;
  1523. end;
  1524. procedure TSQLScript.SetDatabase(Value: TDatabase);
  1525. begin
  1526. FDatabase := Value;
  1527. end;
  1528. procedure TSQLScript.SetTransaction(Value: TDBTransaction);
  1529. begin
  1530. FTransaction := Value;
  1531. end;
  1532. procedure TSQLScript.CheckDatabase;
  1533. begin
  1534. If (FDatabase=Nil) then
  1535. DatabaseError(SErrNoDatabaseAvailable,Self)
  1536. end;
  1537. constructor TSQLScript.Create(AOwner: TComponent);
  1538. begin
  1539. inherited Create(AOwner);
  1540. FQuery := TCustomSQLQuery.Create(nil);
  1541. end;
  1542. destructor TSQLScript.Destroy;
  1543. begin
  1544. FQuery.Free;
  1545. inherited Destroy;
  1546. end;
  1547. procedure TSQLScript.Execute;
  1548. begin
  1549. FQuery.DataBase := FDatabase;
  1550. FQuery.Transaction := FTransaction;
  1551. inherited Execute;
  1552. end;
  1553. procedure TSQLScript.ExecuteScript;
  1554. begin
  1555. Execute;
  1556. end;
  1557. { Connection definitions }
  1558. Var
  1559. ConnDefs : TStringList;
  1560. Procedure CheckDefs;
  1561. begin
  1562. If (ConnDefs=Nil) then
  1563. begin
  1564. ConnDefs:=TStringList.Create;
  1565. ConnDefs.Sorted:=True;
  1566. ConnDefs.Duplicates:=dupError;
  1567. end;
  1568. end;
  1569. Procedure DoneDefs;
  1570. Var
  1571. I : Integer;
  1572. begin
  1573. If Assigned(ConnDefs) then
  1574. begin
  1575. For I:=ConnDefs.Count-1 downto 0 do
  1576. begin
  1577. ConnDefs.Objects[i].Free;
  1578. ConnDefs.Delete(I);
  1579. end;
  1580. FreeAndNil(ConnDefs);
  1581. end;
  1582. end;
  1583. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  1584. Var
  1585. I : Integer;
  1586. begin
  1587. CheckDefs;
  1588. I:=ConnDefs.IndexOf(ConnectorName);
  1589. If (I<>-1) then
  1590. Result:=TConnectionDef(ConnDefs.Objects[i])
  1591. else
  1592. Result:=Nil;
  1593. end;
  1594. procedure RegisterConnection(Def: TConnectionDefClass);
  1595. Var
  1596. I : Integer;
  1597. begin
  1598. CheckDefs;
  1599. I:=ConnDefs.IndexOf(Def.TypeName);
  1600. If (I=-1) then
  1601. ConnDefs.AddObject(Def.TypeName,Def.Create)
  1602. else
  1603. begin
  1604. ConnDefs.Objects[I].Free;
  1605. ConnDefs.Objects[I]:=Def.Create;
  1606. end;
  1607. end;
  1608. procedure UnRegisterConnection(Def: TConnectionDefClass);
  1609. begin
  1610. UnRegisterConnection(Def.TypeName);
  1611. end;
  1612. procedure UnRegisterConnection(ConnectionName: String);
  1613. Var
  1614. I : Integer;
  1615. begin
  1616. if (ConnDefs<>Nil) then
  1617. begin
  1618. I:=ConnDefs.IndexOf(ConnectionName);
  1619. If (I<>-1) then
  1620. begin
  1621. ConnDefs.Objects[I].Free;
  1622. ConnDefs.Delete(I);
  1623. end;
  1624. end;
  1625. end;
  1626. procedure GetConnectionList(List: TSTrings);
  1627. begin
  1628. CheckDefs;
  1629. List.Text:=ConnDefs.Text;
  1630. end;
  1631. { TSQLConnector }
  1632. procedure TSQLConnector.SetConnectorType(const AValue: String);
  1633. begin
  1634. if FConnectorType<>AValue then
  1635. begin
  1636. CheckDisconnected;
  1637. If Assigned(FProxy) then
  1638. FreeProxy;
  1639. FConnectorType:=AValue;
  1640. end;
  1641. end;
  1642. procedure TSQLConnector.SetTransaction(Value: TSQLTransaction);
  1643. begin
  1644. inherited SetTransaction(Value);
  1645. If Assigned(FProxy) and (FProxy.Transaction<>Value) then
  1646. FProxy.Transaction:=Value;
  1647. end;
  1648. procedure TSQLConnector.DoInternalConnect;
  1649. Var
  1650. D : TConnectionDef;
  1651. begin
  1652. inherited DoInternalConnect;
  1653. CreateProxy;
  1654. FProxy.DatabaseName:=Self.DatabaseName;
  1655. FProxy.HostName:=Self.HostName;
  1656. FProxy.UserName:=Self.UserName;
  1657. FProxy.Password:=Self.Password;
  1658. FProxy.Transaction:=Self.Transaction;
  1659. D:=GetConnectionDef(ConnectorType);
  1660. D.ApplyParams(Params,FProxy);
  1661. FProxy.Connected:=True;
  1662. end;
  1663. procedure TSQLConnector.DoInternalDisconnect;
  1664. begin
  1665. FProxy.Connected:=False;
  1666. inherited DoInternalDisconnect;
  1667. end;
  1668. procedure TSQLConnector.CheckProxy;
  1669. begin
  1670. If (FProxy=Nil) then
  1671. CreateProxy;
  1672. end;
  1673. procedure TSQLConnector.CreateProxy;
  1674. Var
  1675. D : TConnectionDef;
  1676. begin
  1677. D:=GetConnectionDef(ConnectorType);
  1678. If (D=Nil) then
  1679. DatabaseErrorFmt(SErrUnknownConnectorType,[ConnectorType],Self);
  1680. FProxy:=D.ConnectionClass.Create(Self);
  1681. end;
  1682. procedure TSQLConnector.FreeProxy;
  1683. begin
  1684. FProxy.Connected:=False;
  1685. FreeAndNil(FProxy);
  1686. end;
  1687. function TSQLConnector.StrToStatementType(s: string): TStatementType;
  1688. begin
  1689. CheckProxy;
  1690. Result:=FProxy.StrToStatementType(s);
  1691. end;
  1692. function TSQLConnector.GetAsSQLText(Field: TField): string;
  1693. begin
  1694. CheckProxy;
  1695. Result:=FProxy.GetAsSQLText(Field);
  1696. end;
  1697. function TSQLConnector.GetAsSQLText(Param: TParam): string;
  1698. begin
  1699. CheckProxy;
  1700. Result:=FProxy.GetAsSQLText(Param);
  1701. end;
  1702. function TSQLConnector.GetHandle: pointer;
  1703. begin
  1704. CheckProxy;
  1705. Result:=FProxy.GetHandle;
  1706. end;
  1707. function TSQLConnector.AllocateCursorHandle: TSQLCursor;
  1708. begin
  1709. CheckProxy;
  1710. Result:=FProxy.AllocateCursorHandle;
  1711. end;
  1712. procedure TSQLConnector.DeAllocateCursorHandle(var cursor: TSQLCursor);
  1713. begin
  1714. CheckProxy;
  1715. FProxy.DeAllocateCursorHandle(cursor);
  1716. end;
  1717. function TSQLConnector.AllocateTransactionHandle: TSQLHandle;
  1718. begin
  1719. CheckProxy;
  1720. Result:=FProxy.AllocateTransactionHandle;
  1721. end;
  1722. procedure TSQLConnector.PrepareStatement(cursor: TSQLCursor;
  1723. ATransaction: TSQLTransaction; buf: string; AParams: TParams);
  1724. begin
  1725. CheckProxy;
  1726. FProxy.PrepareStatement(cursor, ATransaction, buf, AParams);
  1727. end;
  1728. procedure TSQLConnector.Execute(cursor: TSQLCursor;
  1729. atransaction: tSQLtransaction; AParams: TParams);
  1730. begin
  1731. CheckProxy;
  1732. FProxy.Execute(cursor, atransaction, AParams);
  1733. end;
  1734. function TSQLConnector.Fetch(cursor: TSQLCursor): boolean;
  1735. begin
  1736. CheckProxy;
  1737. Result:=FProxy.Fetch(cursor);
  1738. end;
  1739. procedure TSQLConnector.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TfieldDefs
  1740. );
  1741. begin
  1742. CheckProxy;
  1743. FProxy.AddFieldDefs(cursor, FieldDefs);
  1744. end;
  1745. procedure TSQLConnector.UnPrepareStatement(cursor: TSQLCursor);
  1746. begin
  1747. CheckProxy;
  1748. FProxy.UnPrepareStatement(cursor);
  1749. end;
  1750. procedure TSQLConnector.FreeFldBuffers(cursor: TSQLCursor);
  1751. begin
  1752. CheckProxy;
  1753. FProxy.FreeFldBuffers(cursor);
  1754. end;
  1755. function TSQLConnector.LoadField(cursor: TSQLCursor; FieldDef: TfieldDef;
  1756. buffer: pointer; out CreateBlob: boolean): boolean;
  1757. begin
  1758. CheckProxy;
  1759. Result:=FProxy.LoadField(cursor, FieldDef, buffer, CreateBlob);
  1760. end;
  1761. function TSQLConnector.RowsAffected(cursor: TSQLCursor): TRowsCount;
  1762. begin
  1763. CheckProxy;
  1764. Result := FProxy.RowsAffected(cursor);
  1765. end;
  1766. function TSQLConnector.GetTransactionHandle(trans: TSQLHandle): pointer;
  1767. begin
  1768. CheckProxy;
  1769. Result:=FProxy.GetTransactionHandle(trans);
  1770. end;
  1771. function TSQLConnector.Commit(trans: TSQLHandle): boolean;
  1772. begin
  1773. CheckProxy;
  1774. Result:=FProxy.Commit(trans);
  1775. end;
  1776. function TSQLConnector.RollBack(trans: TSQLHandle): boolean;
  1777. begin
  1778. CheckProxy;
  1779. Result:=FProxy.RollBack(trans);
  1780. end;
  1781. function TSQLConnector.StartdbTransaction(trans: TSQLHandle; aParams: string
  1782. ): boolean;
  1783. begin
  1784. CheckProxy;
  1785. Result:=FProxy.StartdbTransaction(trans, aParams);
  1786. end;
  1787. procedure TSQLConnector.CommitRetaining(trans: TSQLHandle);
  1788. begin
  1789. CheckProxy;
  1790. FProxy.CommitRetaining(trans);
  1791. end;
  1792. procedure TSQLConnector.RollBackRetaining(trans: TSQLHandle);
  1793. begin
  1794. CheckProxy;
  1795. FProxy.RollBackRetaining(trans);
  1796. end;
  1797. procedure TSQLConnector.UpdateIndexDefs(IndexDefs: TIndexDefs;
  1798. TableName: string);
  1799. begin
  1800. CheckProxy;
  1801. FProxy.UpdateIndexDefs(IndexDefs, TableName);
  1802. end;
  1803. function TSQLConnector.GetSchemaInfoSQL(SchemaType: TSchemaType;
  1804. SchemaObjectName, SchemaPattern: string): string;
  1805. begin
  1806. CheckProxy;
  1807. Result:=FProxy.GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern
  1808. );
  1809. end;
  1810. procedure TSQLConnector.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  1811. ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction: TSQLTransaction);
  1812. begin
  1813. CheckProxy;
  1814. FProxy.LoadBlobIntoBuffer(FieldDef, ABlobBuf, cursor, ATransaction);
  1815. end;
  1816. { TConnectionDef }
  1817. class function TConnectionDef.TypeName: String;
  1818. begin
  1819. Result:='';
  1820. end;
  1821. class function TConnectionDef.ConnectionClass: TSQLConnectionClass;
  1822. begin
  1823. Result:=Nil;
  1824. end;
  1825. class function TConnectionDef.Description: String;
  1826. begin
  1827. Result:='';
  1828. end;
  1829. procedure TConnectionDef.ApplyParams(Params: TStrings;
  1830. AConnection: TSQLConnection);
  1831. begin
  1832. AConnection.Params.Assign(Params);
  1833. end;
  1834. { TServerIndexDefs }
  1835. constructor TServerIndexDefs.create(ADataset: TDataset);
  1836. begin
  1837. if not (ADataset is TCustomSQLQuery) then
  1838. DatabaseErrorFmt(SErrNotASQLQuery,[ADataset.Name]);
  1839. inherited create(ADataset);
  1840. end;
  1841. procedure TServerIndexDefs.Update;
  1842. begin
  1843. if (not updated) and assigned(Dataset) then
  1844. begin
  1845. TCustomSQLQuery(Dataset).UpdateServerIndexDefs;
  1846. updated := True;
  1847. end;
  1848. end;
  1849. Initialization
  1850. Finalization
  1851. DoneDefs;
  1852. end.