sqldb.pp 76 KB

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