sqldb.pp 74 KB

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