sqldb.pp 74 KB

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