sqldb.pp 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674
  1. {
  2. Copyright (c) 2004-2014 by Joost van der Sluis, FPC contributors
  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, stSequences);
  18. const
  19. TSchemaObjectNames: array[TSchemaType] of String = ('???', 'table_name',
  20. '???', 'procedure_name', 'column_name', 'param_name',
  21. 'index_name', 'package_name', 'schema_name','sequence');
  22. type
  23. TStatementType = (stUnknown, stSelect, stInsert, stUpdate, stDelete,
  24. stDDL, stGetSegment, stPutSegment, stExecProcedure,
  25. stStartTrans, stCommit, stRollback, stSelectForUpd);
  26. TRowsCount = LargeInt;
  27. TSQLStatementInfo = Record
  28. StatementType : TStatementType;
  29. TableName : String;
  30. Updateable : Boolean;
  31. WhereStartPos ,
  32. WhereStopPos : integer;
  33. end;
  34. TSQLConnection = class;
  35. TSQLTransaction = class;
  36. TCustomSQLQuery = class;
  37. TCustomSQLStatement = Class;
  38. TSQLQuery = class;
  39. TSQLScript = class;
  40. TDBEventType = (detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack, detParamValue, detActualSQL);
  41. TDBEventTypes = set of TDBEventType;
  42. TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;
  43. TSQLHandle = Class(TObject)
  44. end;
  45. { TSQLCursor }
  46. TSQLCursor = Class(TSQLHandle)
  47. public
  48. FPrepared : Boolean;
  49. FSelectable : Boolean;
  50. FInitFieldDef : Boolean;
  51. FStatementType : TStatementType;
  52. FSchemaType : TSchemaType;
  53. end;
  54. { ESQLDatabaseError}
  55. ESQLDatabaseError = class(EDatabaseError)
  56. public
  57. ErrorCode: integer;
  58. SQLState : string;
  59. constructor CreateFmt(const Fmt: string; const Args: array of const;
  60. Comp : TComponent; AErrorCode: integer; ASQLState: string); overload;
  61. end;
  62. { TSQLDBFieldDef }
  63. TSQLDBFieldDef = Class(TFieldDef)
  64. private
  65. FData: Pointer;
  66. Public
  67. Property SQLDBData : Pointer Read FData Write FData;
  68. end;
  69. { TSQLDBFieldDefs }
  70. TSQLDBFieldDefs = Class(TFieldDefs)
  71. Protected
  72. Class Function FieldDefClass : TFieldDefClass; override;
  73. end;
  74. { TSQLDBParam }
  75. TSQLDBParam = Class(TParam)
  76. private
  77. FFieldDef: TFieldDef;
  78. FData : Pointer;
  79. Public
  80. Property FieldDef : TFieldDef Read FFieldDef Write FFieldDef;
  81. Property SQLDBData : Pointer Read FData Write FData;
  82. end;
  83. { TSQLDBParams }
  84. TSQLDBParams = Class(TParams)
  85. Protected
  86. Class Function ParamClass : TParamClass; override;
  87. end;
  88. TQuoteChars = array[0..1] of char;
  89. const
  90. SingleQuotes : TQuoteChars = ('''','''');
  91. DoubleQuotes : TQuoteChars = ('"','"');
  92. LogAllEvents = [detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack];
  93. LogAllEventsExtra = [detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack, detParamValue,detActualSQL];
  94. StatementTokens : Array[TStatementType] of string = ('(unknown)', 'select',
  95. 'insert', 'update', 'delete',
  96. 'create', 'get', 'put', 'execute',
  97. 'start','commit','rollback', '?'
  98. );
  99. type
  100. { TServerIndexDefs }
  101. TServerIndexDefs = class(TIndexDefs)
  102. Private
  103. public
  104. constructor Create(ADataSet: TDataSet); override;
  105. procedure Update; override;
  106. end;
  107. TSqlObjectIdentifierList = class;
  108. { TSqlObjectIdenfier }
  109. TSqlObjectIdenfier = class(TCollectionItem)
  110. private
  111. FObjectName: String;
  112. FSchemaName: String;
  113. public
  114. constructor Create(ACollection: TSqlObjectIdentifierList; Const AObjectName: String; Const ASchemaName: String = '');
  115. property SchemaName: String read FSchemaName write FSchemaName;
  116. property ObjectName: String read FObjectName write FObjectName;
  117. end;
  118. { TSqlObjectIdentifierList }
  119. TSqlObjectIdentifierList = class(TCollection)
  120. private
  121. function GetIdentifier(Index: integer): TSqlObjectIdenfier;
  122. procedure SetIdentifier(Index: integer; AValue: TSqlObjectIdenfier);
  123. public
  124. function AddIdentifier: TSqlObjectIdenfier; overload;
  125. function AddIdentifier(Const AObjectName: String; Const ASchemaName: String = ''): TSqlObjectIdenfier; overload;
  126. property Identifiers[Index: integer]: TSqlObjectIdenfier read GetIdentifier write SetIdentifier; default;
  127. end;
  128. type
  129. { TSQLConnection }
  130. TConnOption = (sqSupportParams, sqSupportEmptyDatabaseName, sqEscapeSlash, sqEscapeRepeat, sqImplicitTransaction, sqLastInsertID, sqSupportReturning);
  131. TConnOptions= set of TConnOption;
  132. TSQLConnectionOption = (scoExplicitConnect, scoApplyUpdatesChecksRowsAffected);
  133. TSQLConnectionOptions = Set of TSQLConnectionOption;
  134. TConnInfoType=(citAll=-1, citServerType, citServerVersion, citServerVersionString, citClientName, citClientVersion);
  135. TSQLConnection = class (TDatabase)
  136. private
  137. FFieldNameQuoteChars : TQuoteChars;
  138. FOptions : TSQLConnectionOptions;
  139. FPassword : string;
  140. FTransaction : TSQLTransaction;
  141. FUserName : string;
  142. FHostName : string;
  143. FCharSet : string;
  144. FRole : String;
  145. FStatements : TFPList;
  146. FLogEvents: TDBEventTypes;
  147. FOnLog: TDBLogNotifyEvent;
  148. function GetPort: cardinal;
  149. procedure SetOptions(AValue: TSQLConnectionOptions);
  150. procedure SetPort(const AValue: cardinal);
  151. function AttemptCommit(trans : TSQLHandle) : boolean;
  152. function AttemptRollBack(trans : TSQLHandle) : boolean;
  153. protected
  154. FConnOptions : TConnOptions;
  155. FSQLFormatSettings : TFormatSettings;
  156. // Updating of DB records is moved out of TSQLQuery.
  157. // It is done here, so descendents can override it and implement DB-specific.
  158. // One day, this may be factored out to a TSQLResolver class.
  159. // The following allow construction of update queries. They can be adapted as needed by descendents to fit the DB engine.
  160. procedure AddFieldToUpdateWherePart(var sql_where: string; UpdateMode : TUpdateMode; F: TField); virtual;
  161. function ConstructInsertSQL(Query: TCustomSQLQuery; Var ReturningClause : Boolean): string; virtual;
  162. function ConstructUpdateSQL(Query: TCustomSQLQuery; Var ReturningClause : Boolean): string; virtual;
  163. function ConstructDeleteSQL(Query: TCustomSQLQuery): string; virtual;
  164. function ConstructRefreshSQL(Query: TCustomSQLQuery; UpdateKind : TUpdateKind): string; virtual;
  165. function InitialiseUpdateStatement(Query: TCustomSQLQuery; var qry: TCustomSQLQuery): TCustomSQLQuery;
  166. procedure ApplyFieldUpdate(C : TSQLCursor; P: TSQLDBParam; F: TField; UseOldValue: Boolean); virtual;
  167. // This is the call that updates a record, it used to be in TSQLQuery.
  168. procedure ApplyRecUpdate(Query : TCustomSQLQuery; UpdateKind : TUpdateKind); virtual;
  169. function RefreshLastInsertID(Query : TCustomSQLQuery; Field : TField): Boolean; virtual;
  170. procedure GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
  171. procedure SetTransaction(Value : TSQLTransaction); virtual;
  172. procedure DoInternalConnect; override;
  173. procedure DoInternalDisconnect; override;
  174. function GetAsSQLText(Field : TField) : string; overload; virtual;
  175. function GetAsSQLText(Param : TParam) : string; overload; virtual;
  176. function GetHandle : pointer; virtual;
  177. Function LogEvent(EventType : TDBEventType) : Boolean;
  178. Procedure LogParams(Const AParams : TParams); virtual;
  179. Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
  180. Procedure RegisterStatement(S : TCustomSQLStatement);
  181. Procedure UnRegisterStatement(S : TCustomSQLStatement);
  182. Function AllocateCursorHandle : TSQLCursor; virtual; abstract;
  183. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); virtual; abstract;
  184. function StrToStatementType(s : string) : TStatementType; virtual;
  185. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); virtual; abstract;
  186. procedure UnPrepareStatement(cursor : TSQLCursor); virtual; abstract;
  187. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
  188. function RowsAffected(cursor: TSQLCursor): TRowsCount; virtual;
  189. function Fetch(cursor : TSQLCursor) : boolean; virtual; abstract;
  190. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); virtual; abstract;
  191. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; virtual; abstract;
  192. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); virtual; abstract;
  193. procedure FreeFldBuffers(cursor : TSQLCursor); virtual;
  194. Function AllocateTransactionHandle : TSQLHandle; virtual; abstract;
  195. function GetTransactionHandle(trans : TSQLHandle): pointer; virtual; abstract;
  196. function Commit(trans : TSQLHandle) : boolean; virtual; abstract;
  197. function RollBack(trans : TSQLHandle) : boolean; virtual; abstract;
  198. function StartImplicitTransaction(trans : TSQLHandle; aParams : string) : boolean; virtual;
  199. function StartDBTransaction(trans : TSQLHandle; aParams : string) : boolean; virtual; abstract;
  200. procedure CommitRetaining(trans : TSQLHandle); virtual; abstract;
  201. procedure RollBackRetaining(trans : TSQLHandle); virtual; abstract;
  202. procedure UpdateIndexDefs(IndexDefs : TIndexDefs; TableName : string); virtual;
  203. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; virtual;
  204. function GetNextValueSQL(const SequenceName: string; IncrementBy: Integer): string; virtual;
  205. Procedure MaybeConnect;
  206. Property Statements : TFPList Read FStatements;
  207. property Port: cardinal read GetPort write SetPort;
  208. public
  209. property Handle: Pointer read GetHandle;
  210. property FieldNameQuoteChars: TQuoteChars read FFieldNameQuoteChars write FFieldNameQuoteChars;
  211. constructor Create(AOwner: TComponent); override;
  212. destructor Destroy; override;
  213. procedure StartTransaction; override;
  214. procedure EndTransaction; override;
  215. procedure ExecuteDirect(SQL : String); overload; virtual;
  216. procedure ExecuteDirect(SQL : String; ATransaction : TSQLTransaction); overload; virtual;
  217. // Unified version
  218. function GetObjectNames(ASchemaType: TSchemaType; AList : TSqlObjectIdentifierList): Integer; virtual;
  219. // Older versions.
  220. procedure GetTableNames(List : TStrings; SystemTables : Boolean = false); virtual;
  221. procedure GetProcedureNames(List : TStrings); virtual;
  222. procedure GetFieldNames(const TableName : string; List : TStrings); virtual;
  223. procedure GetSchemaNames(List: TStrings); virtual;
  224. procedure GetSequenceNames(List: TStrings); virtual;
  225. function GetConnectionInfo(InfoType:TConnInfoType): string; virtual;
  226. function GetStatementInfo(const ASQL: string): TSQLStatementInfo; virtual;
  227. procedure CreateDB; virtual;
  228. procedure DropDB; virtual;
  229. function GetNextValue(const SequenceName: string; IncrementBy: integer=1): Int64; virtual;
  230. property ConnOptions: TConnOptions read FConnOptions;
  231. published
  232. property Password : string read FPassword write FPassword;
  233. property Transaction : TSQLTransaction read FTransaction write SetTransaction;
  234. property UserName : string read FUserName write FUserName;
  235. property CharSet : string read FCharSet write FCharSet;
  236. property HostName : string Read FHostName Write FHostName;
  237. Property OnLog : TDBLogNotifyEvent Read FOnLog Write FOnLog;
  238. Property LogEvents : TDBEventTypes Read FLogEvents Write FLogEvents Default LogAllEvents;
  239. Property Options : TSQLConnectionOptions Read FOptions Write SetOptions;
  240. Property Role : String read FRole write FRole;
  241. property Connected;
  242. property DatabaseName;
  243. property KeepConnection;
  244. property LoginPrompt;
  245. property Params;
  246. property OnLogin;
  247. end;
  248. { TSQLTransaction }
  249. TCommitRollbackAction = (caNone, caCommit, caCommitRetaining, caRollback,
  250. caRollbackRetaining);
  251. TSQLTransactionOption = (stoUseImplicit, stoExplicitStart);
  252. TSQLTransactionOptions = Set of TSQLTransactionOption;
  253. TSQLTransaction = class (TDBTransaction)
  254. private
  255. FOptions : TSQLTransactionOptions;
  256. FTrans : TSQLHandle;
  257. FAction : TCommitRollbackAction;
  258. FParams : TStringList;
  259. function GetSQLConnection: TSQLConnection;
  260. procedure SetOptions(AValue: TSQLTransactionOptions);
  261. procedure SetParams(const AValue: TStringList);
  262. procedure SetSQLConnection(AValue: TSQLConnection);
  263. protected
  264. Procedure MaybeStartTransaction;
  265. Function AllowClose(DS: TDBDataset): Boolean; override;
  266. function GetHandle : Pointer; virtual;
  267. Procedure SetDatabase (Value : TDatabase); override;
  268. Function LogEvent(EventType : TDBEventType) : Boolean;
  269. Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
  270. public
  271. constructor Create(AOwner : TComponent); override;
  272. destructor Destroy; override;
  273. procedure Commit; override;
  274. procedure CommitRetaining; override;
  275. procedure Rollback; override;
  276. procedure RollbackRetaining; override;
  277. procedure StartTransaction; override;
  278. procedure EndTransaction; override;
  279. property Handle: Pointer read GetHandle;
  280. Property SQLConnection : TSQLConnection Read GetSQLConnection Write SetSQLConnection;
  281. published
  282. property Action : TCommitRollbackAction read FAction write FAction Default caRollBack;
  283. property Database;
  284. property Params : TStringList read FParams write SetParams;
  285. Property Options : TSQLTransactionOptions Read FOptions Write SetOptions;
  286. end;
  287. { TCustomSQLStatement }
  288. TCustomSQLStatement = Class(TComponent)
  289. Private
  290. FCursor : TSQLCursor;
  291. FDatabase: TSQLConnection;
  292. FParamCheck: Boolean;
  293. FParams: TParams;
  294. FSQL: TStrings;
  295. FOrigSQL : String;
  296. FServerSQL : String;
  297. FTransaction: TSQLTransaction;
  298. FParseSQL: Boolean;
  299. FDataLink : TDataLink;
  300. FRowsAffected : TRowsCount;
  301. procedure SetDatabase(AValue: TSQLConnection);
  302. procedure SetParams(AValue: TParams);
  303. procedure SetSQL(AValue: TStrings);
  304. procedure SetTransaction(AValue: TSQLTransaction);
  305. Function GetPrepared : Boolean;
  306. Protected
  307. Function CreateDataLink : TDataLink; virtual;
  308. procedure OnChangeSQL(Sender : TObject); virtual;
  309. function GetDataSource: TDataSource; Virtual;
  310. procedure SetDataSource(AValue: TDataSource); virtual;
  311. Procedure CopyParamsFromMaster(CopyBound : Boolean); virtual;
  312. procedure AllocateCursor;
  313. procedure DeAllocateCursor;
  314. Function GetSchemaType : TSchemaType; virtual;
  315. Function GetSchemaObjectName : String; virtual;
  316. Function GetSchemaPattern: String; virtual;
  317. Function IsSelectable : Boolean ; virtual;
  318. procedure GetStatementInfo(var ASQL: String; out Info: TSQLStatementInfo); virtual;
  319. Procedure DoExecute; virtual;
  320. procedure DoPrepare; virtual;
  321. procedure DoUnPrepare; virtual;
  322. Function CreateParams : TSQLDBParams; virtual;
  323. Function LogEvent(EventType : TDBEventType) : Boolean;
  324. Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
  325. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  326. Property Cursor : TSQLCursor read FCursor;
  327. Property Database : TSQLConnection Read FDatabase Write SetDatabase;
  328. Property Transaction : TSQLTransaction Read FTransaction Write SetTransaction;
  329. Property SQL : TStrings Read FSQL Write SetSQL;
  330. Property Params : TParams Read FParams Write SetParams;
  331. Property DataSource : TDataSource Read GetDataSource Write SetDataSource;
  332. Property ParseSQL : Boolean Read FParseSQL Write FParseSQL;
  333. Property ParamCheck : Boolean Read FParamCheck Write FParamCheck default true;
  334. Public
  335. constructor Create(AOwner : TComponent); override;
  336. destructor Destroy; override;
  337. Procedure Prepare;
  338. Procedure Execute;
  339. Procedure Unprepare;
  340. function ParamByName(Const AParamName : String) : TParam;
  341. function RowsAffected: TRowsCount; virtual;
  342. Property Prepared : boolean read GetPrepared;
  343. end;
  344. TSQLStatement = Class(TCustomSQLStatement)
  345. Published
  346. Property Database;
  347. Property DataSource;
  348. Property ParamCheck;
  349. Property Params;
  350. Property ParseSQL;
  351. Property SQL;
  352. Property Transaction;
  353. end;
  354. { TSQLSequence }
  355. TSQLSequenceApplyEvent = (saeOnNewRecord, saeOnPost);
  356. TSQLSequence = class(TPersistent)
  357. private
  358. FQuery: TCustomSQLQuery;
  359. FFieldName: String;
  360. FSequenceName: String;
  361. FIncrementBy: Integer;
  362. FApplyEvent: TSQLSequenceApplyEvent;
  363. public
  364. constructor Create(AQuery: TCustomSQLQuery);
  365. procedure Assign(Source: TPersistent); override;
  366. procedure Apply;
  367. function GetNextValue: Int64;
  368. published
  369. property FieldName: String read FFieldName write FFieldName;
  370. property SequenceName: String read FSequenceName write FSequenceName;
  371. property IncrementBy: Integer read FIncrementBy write FIncrementBy default 1;
  372. property ApplyEvent: TSQLSequenceApplyEvent read FApplyEvent write FApplyEvent default saeOnNewRecord;
  373. end;
  374. { TCustomSQLQuery }
  375. TSQLQueryOption = (sqoKeepOpenOnCommit, sqoAutoApplyUpdates, sqoAutoCommit, sqoCancelUpdatesOnRefresh, sqoRefreshUsingSelect);
  376. TSQLQueryOptions = Set of TSQLQueryOption;
  377. TCustomSQLQuery = class (TCustomBufDataset)
  378. private
  379. FOptions : TSQLQueryOptions;
  380. FSchemaType : TSchemaType;
  381. FUpdateable : boolean;
  382. FTableName : string;
  383. FStatement : TCustomSQLStatement;
  384. FInsertSQL,
  385. FUpdateSQL,
  386. FDeleteSQL,
  387. FRefreshSQL : TStringList;
  388. FIsEOF : boolean;
  389. FLoadingFieldDefs : boolean;
  390. FUpdateMode : TUpdateMode;
  391. FusePrimaryKeyAsKey : Boolean;
  392. FWhereStartPos : integer;
  393. FWhereStopPos : integer;
  394. FServerFilterText : string;
  395. FServerFiltered : Boolean;
  396. FServerIndexDefs : TServerIndexDefs;
  397. // Used by SetSchemaType
  398. FSchemaObjectName : string;
  399. FSchemaPattern : string;
  400. FInsertQry,
  401. FUpdateQry,
  402. FDeleteQry : TCustomSQLQuery;
  403. FSequence : TSQLSequence;
  404. procedure FreeFldBuffers;
  405. function GetParamCheck: Boolean;
  406. function GetParams: TParams;
  407. function GetParseSQL: Boolean;
  408. function GetServerIndexDefs: TServerIndexDefs;
  409. function GetSQL: TStringList;
  410. function GetSQLConnection: TSQLConnection;
  411. function GetSQLTransaction: TSQLTransaction;
  412. function GetStatementType : TStatementType;
  413. Function NeedLastInsertID: TField;
  414. procedure SetOptions(AValue: TSQLQueryOptions);
  415. procedure SetParamCheck(AValue: Boolean);
  416. procedure SetSQLConnection(AValue: TSQLConnection);
  417. procedure SetSQLTransaction(AValue: TSQLTransaction);
  418. procedure SetInsertSQL(const AValue: TStringList);
  419. procedure SetUpdateSQL(const AValue: TStringList);
  420. procedure SetDeleteSQL(const AValue: TStringList);
  421. procedure SetRefreshSQL(const AValue: TStringList);
  422. procedure SetParams(AValue: TParams);
  423. procedure SetParseSQL(AValue : Boolean);
  424. procedure SetSQL(const AValue: TStringList);
  425. procedure SetUsePrimaryKeyAsKey(AValue : Boolean);
  426. procedure SetUpdateMode(AValue : TUpdateMode);
  427. procedure OnChangeModifySQL(Sender : TObject);
  428. procedure Execute;
  429. procedure ApplyFilter;
  430. Function AddFilter(SQLstr : string) : string;
  431. protected
  432. Function RefreshLastInsertID(Field: TField): Boolean; virtual;
  433. Function NeedRefreshRecord (UpdateKind: TUpdateKind): Boolean; virtual;
  434. Function RefreshRecord (UpdateKind: TUpdateKind) : Boolean; virtual;
  435. Procedure ApplyReturningResult(Q : TCustomSQLQuery; UpdateKind : TUpdateKind);
  436. Function Cursor : TSQLCursor;
  437. Function LogEvent(EventType : TDBEventType) : Boolean;
  438. Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
  439. // abstract & virtual methods of TBufDataset
  440. function Fetch : boolean; override;
  441. function LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  442. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField); override;
  443. procedure ApplyRecUpdate(UpdateKind : TUpdateKind); override;
  444. procedure SetPacketRecords(aValue : integer); override;
  445. // abstract & virtual methods of TDataset
  446. procedure UpdateServerIndexDefs; virtual;
  447. procedure SetDatabase(Value : TDatabase); override;
  448. Procedure SetTransaction(Value : TDBTransaction); override;
  449. procedure InternalAddRecord(Buffer: Pointer; AAppend: Boolean); override;
  450. procedure InternalClose; override;
  451. procedure InternalInitFieldDefs; override;
  452. procedure InternalOpen; override;
  453. Procedure InternalRefresh; override;
  454. function GetCanModify: Boolean; override;
  455. Function IsPrepared : Boolean; virtual;
  456. Procedure SetActive (Value : Boolean); override;
  457. procedure SetServerFiltered(Value: Boolean); virtual;
  458. procedure SetServerFilterText(const Value: string); virtual;
  459. Function GetDataSource : TDataSource; override;
  460. Procedure SetDataSource(AValue : TDataSource);
  461. procedure BeforeRefreshOpenCursor; override;
  462. procedure SetReadOnly(AValue : Boolean); override;
  463. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  464. procedure DoOnNewRecord; override;
  465. procedure DoBeforePost; override;
  466. class function FieldDefsClass : TFieldDefsClass; override;
  467. // IProviderSupport methods
  468. function PSGetUpdateException(E: Exception; Prev: EUpdateError): EUpdateError; override;
  469. function PSGetTableName: string; override;
  470. Property TableName : String Read FTableName Write FTableName; // alternative: procedure DoGetTableName
  471. public
  472. constructor Create(AOwner : TComponent); override;
  473. destructor Destroy; override;
  474. procedure Prepare; virtual;
  475. procedure UnPrepare; virtual;
  476. procedure ExecSQL; virtual;
  477. procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
  478. function RowsAffected: TRowsCount; virtual;
  479. function ParamByName(Const AParamName : String) : TParam;
  480. Property Prepared : boolean read IsPrepared;
  481. Property SQLConnection : TSQLConnection Read GetSQLConnection Write SetSQLConnection;
  482. Property SQLTransaction: TSQLTransaction Read GetSQLTransaction Write SetSQLTransaction;
  483. // overriden TBufDataSet methods
  484. Procedure ApplyUpdates(MaxErrors: Integer); override; overload;
  485. // overriden TDataSet methods
  486. Procedure Post; override;
  487. Procedure Delete; override;
  488. protected
  489. // redeclared TDataSet properties
  490. property Active;
  491. property Filter;
  492. property Filtered;
  493. property BeforeOpen;
  494. property AfterOpen;
  495. property BeforeClose;
  496. property AfterClose;
  497. property BeforeInsert;
  498. property AfterInsert;
  499. property BeforeEdit;
  500. property AfterEdit;
  501. property BeforePost;
  502. property AfterPost;
  503. property BeforeCancel;
  504. property AfterCancel;
  505. property BeforeDelete;
  506. property AfterDelete;
  507. property BeforeScroll;
  508. property AfterScroll;
  509. property OnCalcFields;
  510. property OnDeleteError;
  511. property OnEditError;
  512. property OnFilterRecord;
  513. property OnNewRecord;
  514. property OnPostError;
  515. property AutoCalcFields;
  516. // protected
  517. property Database;
  518. property Transaction;
  519. property SchemaType : TSchemaType read FSchemaType default stNoSchema;
  520. property SQL : TStringlist read GetSQL write SetSQL;
  521. property InsertSQL : TStringList read FInsertSQL write SetInsertSQL;
  522. property UpdateSQL : TStringList read FUpdateSQL write SetUpdateSQL;
  523. property DeleteSQL : TStringList read FDeleteSQL write SetDeleteSQL;
  524. property RefreshSQL : TStringList read FRefreshSQL write SetRefreshSQL;
  525. Property Options : TSQLQueryOptions Read FOptions Write SetOptions;
  526. property Params : TParams read GetParams Write SetParams;
  527. Property ParamCheck : Boolean Read GetParamCheck Write SetParamCheck default true;
  528. property ParseSQL : Boolean read GetParseSQL write SetParseSQL default true;
  529. property UpdateMode : TUpdateMode read FUpdateMode write SetUpdateMode default upWhereKeyOnly;
  530. property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey default true;
  531. property StatementType : TStatementType read GetStatementType;
  532. Property DataSource : TDataSource Read GetDataSource Write SetDataSource;
  533. property Sequence: TSQLSequence read FSequence write FSequence;
  534. property ServerFilter: string read FServerFilterText write SetServerFilterText;
  535. property ServerFiltered: Boolean read FServerFiltered write SetServerFiltered default False;
  536. property ServerIndexDefs : TServerIndexDefs read GetServerIndexDefs;
  537. end;
  538. { TSQLQuery }
  539. TSQLQuery = Class(TCustomSQLQuery)
  540. public
  541. property SchemaType;
  542. Property StatementType;
  543. Published
  544. property MaxIndexesCount;
  545. // TDataset stuff
  546. property FieldDefs;
  547. Property Active;
  548. Property AutoCalcFields;
  549. Property Filter;
  550. Property Filtered;
  551. Property AfterCancel;
  552. Property AfterClose;
  553. Property AfterDelete;
  554. Property AfterEdit;
  555. Property AfterInsert;
  556. Property AfterOpen;
  557. Property AfterPost;
  558. Property AfterScroll;
  559. Property BeforeCancel;
  560. Property BeforeClose;
  561. Property BeforeDelete;
  562. Property BeforeEdit;
  563. Property BeforeInsert;
  564. Property BeforeOpen;
  565. Property BeforePost;
  566. Property BeforeScroll;
  567. Property OnCalcFields;
  568. Property OnDeleteError;
  569. Property OnEditError;
  570. Property OnFilterRecord;
  571. Property OnNewRecord;
  572. Property OnPostError;
  573. // property SchemaInfo default stNoSchema;
  574. property Database;
  575. property Transaction;
  576. property ReadOnly;
  577. property SQL;
  578. property InsertSQL;
  579. property UpdateSQL;
  580. property DeleteSQL;
  581. property RefreshSQL;
  582. property IndexDefs;
  583. Property Options;
  584. property Params;
  585. Property ParamCheck;
  586. property ParseSQL;
  587. property UpdateMode;
  588. property UsePrimaryKeyAsKey;
  589. Property DataSource;
  590. property Sequence;
  591. property ServerFilter;
  592. property ServerFiltered;
  593. property ServerIndexDefs;
  594. end;
  595. { TSQLScript }
  596. TSQLScript = class (TCustomSQLscript)
  597. private
  598. FOnDirective: TSQLScriptDirectiveEvent;
  599. FQuery : TCustomSQLQuery;
  600. FDatabase : TDatabase;
  601. FTransaction : TDBTransaction;
  602. protected
  603. procedure ExecuteStatement (SQLStatement: TStrings; var StopExecution: Boolean); override;
  604. procedure ExecuteDirective (Directive, Argument: String; var StopExecution: Boolean); override;
  605. procedure ExecuteCommit(CommitRetaining: boolean=true); override;
  606. Procedure SetDatabase (Value : TDatabase); virtual;
  607. Procedure SetTransaction(Value : TDBTransaction); virtual;
  608. Procedure CheckDatabase;
  609. public
  610. constructor Create(AOwner : TComponent); override;
  611. destructor Destroy; override;
  612. procedure Execute; override;
  613. procedure ExecuteScript;
  614. published
  615. Property DataBase : TDatabase Read FDatabase Write SetDatabase;
  616. Property Transaction : TDBTransaction Read FTransaction Write SetTransaction;
  617. property OnDirective: TSQLScriptDirectiveEvent read FOnDirective write FOnDirective;
  618. property Directives;
  619. property Defines;
  620. property Script;
  621. property Terminator;
  622. property CommentsinSQL;
  623. property UseSetTerm;
  624. property UseCommit;
  625. property UseDefines;
  626. property OnException;
  627. end;
  628. { TSQLConnector }
  629. TSQLConnector = Class(TSQLConnection)
  630. private
  631. FProxy : TSQLConnection;
  632. FConnectorType: String;
  633. procedure SetConnectorType(const AValue: String);
  634. protected
  635. procedure SetTransaction(Value : TSQLTransaction);override;
  636. procedure DoInternalConnect; override;
  637. procedure DoInternalDisconnect; override;
  638. Procedure CheckProxy;
  639. Procedure CreateProxy; virtual;
  640. Procedure FreeProxy; virtual;
  641. function StrToStatementType(s : string) : TStatementType; override;
  642. function GetAsSQLText(Field : TField) : string; overload; override;
  643. function GetAsSQLText(Param : TParam) : string; overload; override;
  644. function GetHandle : pointer; override;
  645. Function AllocateCursorHandle : TSQLCursor; override;
  646. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
  647. Function AllocateTransactionHandle : TSQLHandle; override;
  648. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
  649. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
  650. function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
  651. function Fetch(cursor : TSQLCursor) : boolean; override;
  652. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
  653. procedure UnPrepareStatement(cursor : TSQLCursor); override;
  654. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  655. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); override;
  656. procedure FreeFldBuffers(cursor : TSQLCursor); override;
  657. function GetTransactionHandle(trans : TSQLHandle): pointer; override;
  658. function Commit(trans : TSQLHandle) : boolean; override;
  659. function RollBack(trans : TSQLHandle) : boolean; override;
  660. function StartDBTransaction(trans : TSQLHandle; aParams : string) : boolean; override;
  661. procedure CommitRetaining(trans : TSQLHandle); override;
  662. procedure RollBackRetaining(trans : TSQLHandle); override;
  663. procedure UpdateIndexDefs(IndexDefs : TIndexDefs; TableName : string); override;
  664. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; override;
  665. Property Proxy : TSQLConnection Read FProxy;
  666. Published
  667. Property ConnectorType : String Read FConnectorType Write SetConnectorType;
  668. end;
  669. TSQLConnectionClass = Class of TSQLConnection;
  670. { TConnectionDef }
  671. TLibraryLoadFunction = Function (Const S : AnsiString) : Integer;
  672. TLibraryUnLoadFunction = Procedure;
  673. TConnectionDef = Class(TPersistent)
  674. Class Function TypeName : String; virtual;
  675. Class Function ConnectionClass : TSQLConnectionClass; virtual;
  676. Class Function Description : String; virtual;
  677. Class Function DefaultLibraryName : String; virtual;
  678. Class Function LoadFunction : TLibraryLoadFunction; virtual;
  679. Class Function UnLoadFunction : TLibraryUnLoadFunction; virtual;
  680. Class Function LoadedLibraryName : string; virtual;
  681. Procedure ApplyParams(Params : TStrings; AConnection : TSQLConnection); virtual;
  682. end;
  683. TConnectionDefClass = class of TConnectionDef;
  684. Var
  685. GlobalDBLogHook : TDBLogNotifyEvent;
  686. Procedure RegisterConnection(Def : TConnectionDefClass);
  687. Procedure UnRegisterConnection(Def : TConnectionDefClass);
  688. Procedure UnRegisterConnection(ConnectionName : String);
  689. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  690. Procedure GetConnectionList(List : TSTrings);
  691. const DefaultSQLFormatSettings : TFormatSettings = (
  692. CurrencyFormat: 1;
  693. NegCurrFormat: 5;
  694. ThousandSeparator: #0;
  695. DecimalSeparator: '.';
  696. CurrencyDecimals: 2;
  697. DateSeparator: '-';
  698. TimeSeparator: ':';
  699. ListSeparator: ' ';
  700. CurrencyString: '$';
  701. ShortDateFormat: 'yyyy-mm-dd';
  702. LongDateFormat: '';
  703. TimeAMString: '';
  704. TimePMString: '';
  705. ShortTimeFormat: 'hh:nn:ss';
  706. LongTimeFormat: 'hh:nn:ss.zzz';
  707. ShortMonthNames: ('','','','','','','','','','','','');
  708. LongMonthNames: ('','','','','','','','','','','','');
  709. ShortDayNames: ('','','','','','','');
  710. LongDayNames: ('','','','','','','');
  711. TwoDigitYearCenturyWindow: 50;
  712. );
  713. implementation
  714. uses dbconst, strutils;
  715. Const
  716. // Flags to check which fields must be refreshed.
  717. RefreshFlags : Array [ukModify..ukInsert] of TProviderFlag = (pfRefreshOnUpdate,pfRefreshOnInsert);
  718. function TimeIntervalToString(Time: TDateTime): string;
  719. var
  720. millisecond: word;
  721. second : word;
  722. minute : word;
  723. hour : word;
  724. begin
  725. DecodeTime(Time,hour,minute,second,millisecond);
  726. hour := hour + trunc(Time)*24;
  727. Result := Format('%.2d:%.2d:%.2d.%.3d',[hour,minute,second,millisecond]);
  728. end;
  729. { TSQLDBFieldDefs }
  730. class function TSQLDBFieldDefs.FieldDefClass: TFieldDefClass;
  731. begin
  732. Result:=TSQLDBFieldDef;
  733. end;
  734. { TSQLDBParams }
  735. class function TSQLDBParams.ParamClass: TParamClass;
  736. begin
  737. Result:=TSQLDBParam;
  738. end;
  739. { ESQLDatabaseError }
  740. constructor ESQLDatabaseError.CreateFmt(const Fmt: string; const Args: array of const;
  741. Comp: TComponent; AErrorCode: integer; ASQLState: string);
  742. const CompNameFmt='%s : %s';
  743. var Msg: string;
  744. begin
  745. if not assigned(Comp) then
  746. Msg := Fmt
  747. else if Comp.Name = '' then
  748. Msg := Format(CompNameFmt, [Comp.ClassName,Fmt])
  749. else
  750. Msg := Format(CompNameFmt, [Comp.Name,Fmt]);
  751. if Length(Args) = 0 then
  752. inherited Create(Msg)
  753. else
  754. inherited CreateFmt(Msg, Args);
  755. ErrorCode := AErrorCode;
  756. SQLState := ASQLState;
  757. end;
  758. { TCustomSQLStatement }
  759. procedure TCustomSQLStatement.OnChangeSQL(Sender: TObject);
  760. var
  761. ConnOptions : TConnOptions;
  762. NewParams: TSQLDBParams;
  763. begin
  764. UnPrepare;
  765. if not ParamCheck then
  766. exit;
  767. if assigned(DataBase) then
  768. ConnOptions:=DataBase.ConnOptions
  769. else
  770. ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
  771. NewParams := CreateParams;
  772. try
  773. NewParams.ParseSQL(FSQL.Text, True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions, psInterbase);
  774. NewParams.AssignValues(FParams);
  775. FParams.Assign(NewParams);
  776. finally
  777. NewParams.Free;
  778. end;
  779. end;
  780. procedure TCustomSQLStatement.SetDatabase(AValue: TSQLConnection);
  781. begin
  782. if FDatabase=AValue then Exit;
  783. UnPrepare;
  784. If Assigned(FDatabase) then
  785. begin
  786. FDatabase.UnregisterStatement(Self);
  787. FDatabase.RemoveFreeNotification(Self);
  788. end;
  789. FDatabase:=AValue;
  790. If Assigned(FDatabase) then
  791. begin
  792. FDatabase.FreeNotification(Self);
  793. FDatabase.RegisterStatement(Self);
  794. if Assigned(Database.Transaction) and (not Assigned(Transaction) or (Transaction.DataBase <> Database)) then
  795. Transaction := Database.Transaction;
  796. OnChangeSQL(Self);
  797. end;
  798. end;
  799. procedure TCustomSQLStatement.SetTransaction(AValue: TSQLTransaction);
  800. begin
  801. if FTransaction=AValue then Exit;
  802. UnPrepare;
  803. if Assigned(FTransaction) then
  804. FTransaction.RemoveFreeNotification(Self);
  805. FTransaction:=AValue;
  806. if Assigned(FTransaction) then
  807. begin
  808. FTransaction.FreeNotification(Self);
  809. if Assigned(Transaction.DataBase) and (Database <> Transaction.DataBase) then
  810. Database := Transaction.DataBase as TSQLConnection;
  811. end;
  812. end;
  813. procedure TCustomSQLStatement.SetDataSource(AValue: TDataSource);
  814. begin
  815. if GetDataSource=AValue then Exit;
  816. if (FDataLink=Nil) then
  817. FDataLink:=CreateDataLink;
  818. FDataLink.DataSource:=AValue;
  819. end;
  820. Procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound: Boolean);
  821. begin
  822. if Assigned(DataSource) and Assigned(DataSource.Dataset) then
  823. FParams.CopyParamValuesFromDataset(DataSource.Dataset,CopyBound);
  824. end;
  825. procedure TCustomSQLStatement.SetParams(AValue: TParams);
  826. begin
  827. if FParams=AValue then Exit;
  828. FParams.Assign(AValue);
  829. end;
  830. procedure TCustomSQLStatement.SetSQL(AValue: TStrings);
  831. begin
  832. if FSQL=AValue then Exit;
  833. FSQL.Assign(AValue);
  834. end;
  835. Procedure TCustomSQLStatement.DoExecute;
  836. begin
  837. FRowsAffected:=-1;
  838. If (FParams.Count>0) and Assigned(DataSource) then
  839. CopyParamsFromMaster(False);
  840. If LogEvent(detExecute) then
  841. Log(detExecute,FServerSQL);
  842. Database.Execute(FCursor,Transaction, FParams);
  843. end;
  844. Function TCustomSQLStatement.GetPrepared: Boolean;
  845. begin
  846. Result := Assigned(FCursor) and FCursor.FPrepared;
  847. end;
  848. Function TCustomSQLStatement.CreateDataLink: TDataLink;
  849. begin
  850. Result:=TDataLink.Create;
  851. end;
  852. Function TCustomSQLStatement.CreateParams: TSQLDBParams;
  853. begin
  854. Result:=TSQLDBParams.Create(Nil);
  855. end;
  856. Function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
  857. begin
  858. Result:=Assigned(Database) and Database.LogEvent(EventType);
  859. end;
  860. Procedure TCustomSQLStatement.Log(EventType: TDBEventType; Const Msg: String);
  861. Var
  862. M : String;
  863. begin
  864. If LogEvent(EventType) then
  865. begin
  866. If (Name<>'') then
  867. M:=Name
  868. else
  869. M:=ClassName;
  870. Database.Log(EventType,M+' : '+Msg);
  871. end;
  872. end;
  873. procedure TCustomSQLStatement.Notification(AComponent: TComponent;
  874. Operation: TOperation);
  875. begin
  876. inherited Notification(AComponent, Operation);
  877. if (operation=opRemove) then
  878. If (AComponent=FTransaction) then
  879. FTransaction:=Nil
  880. else if (AComponent=FDatabase) then
  881. begin
  882. UnPrepare;
  883. FDatabase:=Nil;
  884. end;
  885. end;
  886. constructor TCustomSQLStatement.Create(AOwner: TComponent);
  887. begin
  888. inherited Create(AOwner);
  889. FSQL:=TStringList.Create;
  890. TStringList(FSQL).OnChange:=@OnChangeSQL;
  891. FParams:=CreateParams;
  892. FParamCheck:=True;
  893. FParseSQL:=True;
  894. FRowsAffected:=-1;
  895. end;
  896. destructor TCustomSQLStatement.Destroy;
  897. begin
  898. UnPrepare;
  899. Transaction:=Nil;
  900. Database:=Nil;
  901. DataSource:=Nil;
  902. FreeAndNil(FDataLink);
  903. FreeAndNil(FParams);
  904. FreeAndNil(FSQL);
  905. inherited Destroy;
  906. end;
  907. Function TCustomSQLStatement.GetSchemaType: TSchemaType;
  908. begin
  909. Result:=stNoSchema
  910. end;
  911. Function TCustomSQLStatement.GetSchemaObjectName: String;
  912. begin
  913. Result:='';
  914. end;
  915. Function TCustomSQLStatement.GetSchemaPattern: String;
  916. begin
  917. Result:='';
  918. end;
  919. Function TCustomSQLStatement.IsSelectable: Boolean;
  920. begin
  921. Result:=False;
  922. end;
  923. procedure TCustomSQLStatement.GetStatementInfo(var ASQL: String; out Info: TSQLStatementInfo);
  924. begin
  925. Info:=Database.GetStatementInfo(ASQL);
  926. end;
  927. procedure TCustomSQLStatement.AllocateCursor;
  928. begin
  929. if not assigned(FCursor) then
  930. // Do this as late as possible.
  931. FCursor:=Database.AllocateCursorHandle;
  932. end;
  933. procedure TCustomSQLStatement.DeAllocateCursor;
  934. begin
  935. if Assigned(FCursor) and Assigned(Database) then
  936. DataBase.DeAllocateCursorHandle(FCursor);
  937. end;
  938. procedure TCustomSQLStatement.DoPrepare;
  939. var
  940. StmInfo: TSQLStatementInfo;
  941. begin
  942. if GetSchemaType=stNoSchema then
  943. FOrigSQL := TrimRight(FSQL.Text)
  944. else
  945. FOrigSQL := Database.GetSchemaInfoSQL(GetSchemaType, GetSchemaObjectName, GetSchemaPattern);
  946. if (FOrigSQL='') then
  947. DatabaseError(SErrNoStatement);
  948. FServerSQL:=FOrigSQL;
  949. GetStatementInfo(FServerSQL,StmInfo);
  950. AllocateCursor;
  951. FCursor.FSelectable:=True; // let PrepareStatement and/or Execute alter it
  952. FCursor.FStatementType:=StmInfo.StatementType;
  953. FCursor.FSchemaType:=GetSchemaType;
  954. If LogEvent(detPrepare) then
  955. Log(detPrepare,FServerSQL);
  956. Database.PrepareStatement(FCursor,Transaction,FServerSQL,FParams);
  957. end;
  958. Procedure TCustomSQLStatement.Prepare;
  959. begin
  960. if Prepared then exit;
  961. if not assigned(Database) then
  962. DatabaseError(SErrDatabasenAssigned);
  963. if not assigned(Transaction) then
  964. DatabaseError(SErrTransactionnSet);
  965. Database.MaybeConnect;
  966. if not Transaction.Active then
  967. Transaction.MaybeStartTransaction;
  968. try
  969. DoPrepare;
  970. except
  971. DeAllocateCursor;
  972. Raise;
  973. end;
  974. end;
  975. Procedure TCustomSQLStatement.Execute;
  976. begin
  977. Prepare;
  978. DoExecute;
  979. end;
  980. procedure TCustomSQLStatement.DoUnPrepare;
  981. begin
  982. If Assigned(FCursor) then
  983. If Assigned(Database) then
  984. begin
  985. DataBase.UnPrepareStatement(FCursor);
  986. DeAllocateCursor;
  987. end
  988. else // this should never happen. It means a cursor handle leaks in the DB itself.
  989. FreeAndNil(FCursor);
  990. end;
  991. function TCustomSQLStatement.GetDataSource: TDataSource;
  992. begin
  993. if Assigned(FDataLink) then
  994. Result:=FDataLink.DataSource
  995. else
  996. Result:=Nil;
  997. end;
  998. Procedure TCustomSQLStatement.Unprepare;
  999. begin
  1000. // Some SQLConnections does not support statement [un]preparation, but they have allocated local cursor(s)
  1001. // so let them do cleanup f.e. cancel pending queries and/or free resultset
  1002. // and also do UnRegisterStatement!
  1003. if assigned(FCursor) then
  1004. DoUnprepare;
  1005. end;
  1006. function TCustomSQLStatement.ParamByName(Const AParamName: String): TParam;
  1007. begin
  1008. Result:=FParams.ParamByName(AParamName);
  1009. end;
  1010. function TCustomSQLStatement.RowsAffected: TRowsCount;
  1011. begin
  1012. if FRowsAffected=-1 then
  1013. begin
  1014. if Assigned(Database) then
  1015. FRowsAffected:=Database.RowsAffected(FCursor);
  1016. end;
  1017. Result:=FRowsAffected;
  1018. end;
  1019. { TSQLConnection }
  1020. constructor TSQLConnection.Create(AOwner: TComponent);
  1021. begin
  1022. inherited Create(AOwner);
  1023. FSQLFormatSettings:=DefaultSQLFormatSettings;
  1024. FFieldNameQuoteChars:=DoubleQuotes;
  1025. FLogEvents:=LogAllEvents; //match Property LogEvents...Default LogAllEvents
  1026. FStatements:=TFPList.Create;
  1027. end;
  1028. destructor TSQLConnection.Destroy;
  1029. begin
  1030. Connected:=False; // needed because we want to de-allocate statements
  1031. FreeAndNil(FStatements);
  1032. inherited Destroy;
  1033. end;
  1034. function TSQLConnection.StrToStatementType(s : string) : TStatementType;
  1035. var T : TStatementType;
  1036. begin
  1037. S:=Lowercase(s);
  1038. for T:=stSelect to stRollback do
  1039. if (S=StatementTokens[T]) then
  1040. Exit(T);
  1041. Result:=stUnknown;
  1042. end;
  1043. procedure TSQLConnection.SetTransaction(Value : TSQLTransaction);
  1044. begin
  1045. if FTransaction<>value then
  1046. begin
  1047. if Assigned(FTransaction) and FTransaction.Active then
  1048. DatabaseError(SErrAssTransaction);
  1049. if Assigned(Value) then
  1050. Value.Database := Self;
  1051. FTransaction := Value;
  1052. If Assigned(FTransaction) and (FTransaction.Database=Nil) then
  1053. FTransaction.Database:=Self;
  1054. end;
  1055. end;
  1056. procedure TSQLConnection.UpdateIndexDefs(IndexDefs : TIndexDefs; TableName : string);
  1057. begin
  1058. // Empty abstract
  1059. end;
  1060. procedure TSQLConnection.DoInternalConnect;
  1061. begin
  1062. if (DatabaseName = '') and not(sqSupportEmptyDatabaseName in FConnOptions) then
  1063. DatabaseError(SErrNoDatabaseName,self);
  1064. end;
  1065. procedure TSQLConnection.DoInternalDisconnect;
  1066. Var
  1067. I : integer;
  1068. begin
  1069. For I:=0 to FStatements.Count-1 do
  1070. TCustomSQLStatement(FStatements[i]).Unprepare;
  1071. FStatements.Clear;
  1072. end;
  1073. procedure TSQLConnection.StartTransaction;
  1074. begin
  1075. if not assigned(Transaction) then
  1076. DatabaseError(SErrConnTransactionnSet)
  1077. else
  1078. Transaction.StartTransaction;
  1079. end;
  1080. procedure TSQLConnection.EndTransaction;
  1081. begin
  1082. if not assigned(Transaction) then
  1083. DatabaseError(SErrConnTransactionnSet)
  1084. else
  1085. Transaction.EndTransaction;
  1086. end;
  1087. procedure TSQLConnection.ExecuteDirect(SQL: String);
  1088. begin
  1089. ExecuteDirect(SQL,FTransaction);
  1090. end;
  1091. procedure TSQLConnection.ExecuteDirect(SQL: String;
  1092. ATransaction: TSQLTransaction);
  1093. var Cursor : TSQLCursor;
  1094. begin
  1095. if not assigned(ATransaction) then
  1096. DatabaseError(SErrTransactionnSet);
  1097. if not Connected then Open;
  1098. if not ATransaction.Active then
  1099. ATransaction.MaybeStartTransaction;
  1100. SQL := TrimRight(SQL);
  1101. if SQL = '' then
  1102. DatabaseError(SErrNoStatement);
  1103. try
  1104. Cursor := AllocateCursorHandle;
  1105. Cursor.FStatementType := stUnknown;
  1106. If LogEvent(detPrepare) then
  1107. Log(detPrepare,SQL);
  1108. PrepareStatement(Cursor,ATransaction,SQL,Nil);
  1109. try
  1110. If LogEvent(detExecute) then
  1111. Log(detExecute,SQL);
  1112. Execute(Cursor,ATransaction, Nil);
  1113. finally
  1114. UnPrepareStatement(Cursor);
  1115. end;
  1116. finally;
  1117. DeAllocateCursorHandle(Cursor);
  1118. end;
  1119. end;
  1120. function TSQLConnection.GetPort: cardinal;
  1121. begin
  1122. result := StrToIntDef(Params.Values['Port'],0);
  1123. end;
  1124. procedure TSQLConnection.SetOptions(AValue: TSQLConnectionOptions);
  1125. begin
  1126. if FOptions=AValue then Exit;
  1127. FOptions:=AValue;
  1128. end;
  1129. procedure TSQLConnection.SetPort(const AValue: cardinal);
  1130. begin
  1131. if AValue<>0 then
  1132. Params.Values['Port']:=IntToStr(AValue)
  1133. else with params do if IndexOfName('Port') > -1 then
  1134. Delete(IndexOfName('Port'));
  1135. end;
  1136. function TSQLConnection.AttemptCommit(trans: TSQLHandle): boolean;
  1137. begin
  1138. try
  1139. Result:=Commit(trans);
  1140. except
  1141. if ForcedClose then
  1142. Result:=True
  1143. else
  1144. Raise;
  1145. end;
  1146. end;
  1147. function TSQLConnection.AttemptRollBack(trans: TSQLHandle): boolean;
  1148. begin
  1149. try
  1150. Result:=Rollback(trans);
  1151. except
  1152. if ForcedClose then
  1153. Result:=True
  1154. else
  1155. Raise;
  1156. end;
  1157. end;
  1158. procedure TSQLConnection.GetDBInfo(const ASchemaType : TSchemaType; const ASchemaObjectName, AReturnField : string; AList: TStrings);
  1159. var qry : TCustomSQLQuery;
  1160. begin
  1161. if not assigned(Transaction) then
  1162. DatabaseError(SErrConnTransactionnSet);
  1163. qry := TCustomSQLQuery.Create(nil);
  1164. try
  1165. qry.transaction := Transaction;
  1166. qry.database := Self;
  1167. with qry do
  1168. begin
  1169. ParseSQL := False;
  1170. SetSchemaInfo(ASchemaType,ASchemaObjectName,'');
  1171. open;
  1172. AList.Clear;
  1173. while not eof do
  1174. begin
  1175. AList.Append(trim(fieldbyname(AReturnField).asstring));
  1176. Next;
  1177. end;
  1178. end;
  1179. finally
  1180. qry.free;
  1181. end;
  1182. end;
  1183. function TSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
  1184. begin
  1185. Result := -1;
  1186. end;
  1187. procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
  1188. begin
  1189. if not SystemTables then
  1190. GetDBInfo(stTables,'','table_name',List)
  1191. else
  1192. GetDBInfo(stSysTables,'','table_name',List);
  1193. end;
  1194. procedure TSQLConnection.GetProcedureNames(List: TStrings);
  1195. begin
  1196. GetDBInfo(stProcedures,'','procedure_name',List);
  1197. end;
  1198. procedure TSQLConnection.GetFieldNames(const TableName: string; List: TStrings);
  1199. begin
  1200. GetDBInfo(stColumns,TableName,'column_name',List);
  1201. end;
  1202. procedure TSQLConnection.GetSchemaNames(List: TStrings);
  1203. begin
  1204. GetDBInfo(stSchemata,'','SCHEMA_NAME',List);
  1205. end;
  1206. procedure TSQLConnection.GetSequenceNames(List: TStrings);
  1207. begin
  1208. GetDBInfo(stSequences,'','SEQUENCE_NAME',List);
  1209. end;
  1210. {
  1211. See if we can integrate/merge this with GetDBInfo. They are virtually identical
  1212. }
  1213. Function TSQLConnection.GetObjectNames(ASchemaType: TSchemaType; AList : TSqlObjectIdentifierList) : Integer;
  1214. var
  1215. qry : TCustomSQLQuery;
  1216. vSchemaName, vObjectName: String;
  1217. f: TField;
  1218. begin
  1219. Result:=0;
  1220. if not assigned(Transaction) then
  1221. DatabaseError(SErrConnTransactionnSet);
  1222. qry := TCustomSQLQuery.Create(nil);
  1223. try
  1224. qry.transaction := Transaction;
  1225. qry.database := Self;
  1226. with qry do
  1227. begin
  1228. ParseSQL := False;
  1229. SetSchemaInfo(ASchemaType,TSchemaObjectNames[ASchemaType],'');
  1230. open;
  1231. f:=FindField(TSchemaObjectNames[stSchemata]);
  1232. while not eof do
  1233. begin
  1234. vSchemaName:='';
  1235. if Assigned(f) then
  1236. vSchemaName:=f.AsString;
  1237. vObjectName:=FieldByName(FSchemaObjectName).AsString;
  1238. AList.AddIdentifier(vObjectName, vSchemaName);
  1239. Next;
  1240. Inc(Result);
  1241. end;
  1242. end;
  1243. finally
  1244. qry.free;
  1245. end;
  1246. end;
  1247. function TSQLConnection.GetConnectionInfo(InfoType: TConnInfoType): string;
  1248. var i: TConnInfoType;
  1249. begin
  1250. Result:='';
  1251. if InfoType = citAll then
  1252. for i:=citServerType to citClientVersion do
  1253. begin
  1254. if Result<>'' then Result:=Result+',';
  1255. Result:=Result+'"'+GetConnectionInfo(i)+'"';
  1256. end;
  1257. end;
  1258. function TSQLConnection.GetStatementInfo(const ASQL: string): TSQLStatementInfo;
  1259. type TParsePart = (ppStart,ppWith,ppSelect,ppTableName,ppFrom,ppWhere,ppGroup,ppOrder,ppBogus);
  1260. TPhraseSeparator = (sepNone, sepWhiteSpace, sepComma, sepComment, sepParentheses, sepDoubleQuote, sepEnd);
  1261. TKeyword = (kwWITH, kwSELECT, kwINSERT, kwUPDATE, kwDELETE, kwFROM, kwJOIN, kwWHERE, kwGROUP, kwORDER, kwUNION, kwROWS, kwLIMIT, kwUnknown);
  1262. const
  1263. KeywordNames: array[TKeyword] of string =
  1264. ('WITH', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'FROM', 'JOIN', 'WHERE', 'GROUP', 'ORDER', 'UNION', 'ROWS', 'LIMIT', '');
  1265. var
  1266. PSQL, CurrentP, SavedP,
  1267. PhraseP, PStatementPart : pchar;
  1268. S : string;
  1269. ParsePart : TParsePart;
  1270. BracketCount : Integer;
  1271. Separator : TPhraseSeparator;
  1272. Keyword, K : TKeyword;
  1273. begin
  1274. PSQL:=Pchar(ASQL);
  1275. ParsePart := ppStart;
  1276. CurrentP := PSQL-1;
  1277. PhraseP := PSQL;
  1278. Result.TableName := '';
  1279. Result.Updateable := False;
  1280. Result.WhereStartPos := 0;
  1281. Result.WhereStopPos := 0;
  1282. repeat
  1283. begin
  1284. inc(CurrentP);
  1285. SavedP := CurrentP;
  1286. case CurrentP^ of
  1287. ' ', #9..#13:
  1288. Separator := sepWhiteSpace;
  1289. ',':
  1290. Separator := sepComma;
  1291. #0, ';':
  1292. Separator := sepEnd;
  1293. '(':
  1294. begin
  1295. Separator := sepParentheses;
  1296. // skip everything between brackets, since it could be a sub-select, and
  1297. // further nothing between brackets could be interesting for the parser.
  1298. BracketCount := 1;
  1299. repeat
  1300. inc(CurrentP);
  1301. if CurrentP^ = '(' then inc(BracketCount)
  1302. else if CurrentP^ = ')' then dec(BracketCount);
  1303. until (CurrentP^ = #0) or (BracketCount = 0);
  1304. if CurrentP^ <> #0 then inc(CurrentP);
  1305. end;
  1306. '"','`':
  1307. if SkipComments(CurrentP, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions) then
  1308. Separator := sepDoubleQuote;
  1309. else
  1310. if SkipComments(CurrentP, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions) then
  1311. Separator := sepComment
  1312. else
  1313. Separator := sepNone;
  1314. end;
  1315. if (CurrentP > SavedP) and (SavedP > PhraseP) then
  1316. CurrentP := SavedP; // there is something before comment or left parenthesis
  1317. if Separator <> sepNone then
  1318. begin
  1319. if ((Separator in [sepWhitespace,sepComment]) and (PhraseP = SavedP)) then
  1320. PhraseP := CurrentP; // skip comments (but not parentheses) and white spaces
  1321. if (CurrentP-PhraseP > 0) or (Separator = sepEnd) then
  1322. begin
  1323. SetString(s, PhraseP, CurrentP-PhraseP);
  1324. Keyword := kwUnknown;
  1325. for K in TKeyword do
  1326. if SameText(s, KeywordNames[K]) then
  1327. begin
  1328. Keyword := K;
  1329. break;
  1330. end;
  1331. case ParsePart of
  1332. ppStart : begin
  1333. Result.StatementType := StrToStatementType(s);
  1334. case Keyword of
  1335. kwWITH : ParsePart := ppWith;
  1336. kwSELECT: ParsePart := ppSelect;
  1337. else break;
  1338. end;
  1339. end;
  1340. ppWith : begin
  1341. // WITH [RECURSIVE] CTE_name [ ( column_names ) ] AS ( CTE_query_definition ) [, ...]
  1342. // { SELECT | INSERT | UPDATE | DELETE } ...
  1343. case Keyword of
  1344. kwSELECT: Result.StatementType := stSelect;
  1345. kwINSERT: Result.StatementType := stInsert;
  1346. kwUPDATE: Result.StatementType := stUpdate;
  1347. kwDELETE: Result.StatementType := stDelete;
  1348. end;
  1349. if Result.StatementType <> stUnknown then break;
  1350. end;
  1351. ppSelect : begin
  1352. if Keyword = kwFROM then
  1353. ParsePart := ppTableName;
  1354. end;
  1355. ppTableName:
  1356. begin
  1357. // Meta-data requests are never updateable
  1358. // and select statements from more than one table
  1359. // and/or derived tables are also not updateable
  1360. if Separator in [sepWhitespace, sepComment, sepDoubleQuote, sepEnd] then
  1361. begin
  1362. Result.TableName := s;
  1363. Result.Updateable := True;
  1364. end;
  1365. ParsePart := ppFrom;
  1366. end;
  1367. ppFrom : begin
  1368. if (Keyword in [kwWHERE, kwGROUP, kwORDER, kwLIMIT, kwROWS]) or
  1369. (Separator = sepEnd) then
  1370. begin
  1371. case Keyword of
  1372. kwWHERE: ParsePart := ppWhere;
  1373. kwGROUP: ParsePart := ppGroup;
  1374. kwORDER: ParsePart := ppOrder;
  1375. else ParsePart := ppBogus;
  1376. end;
  1377. Result.WhereStartPos := PhraseP-PSQL+1;
  1378. PStatementPart := CurrentP;
  1379. end
  1380. else
  1381. // joined table or user_defined_function (...)
  1382. if (Keyword = kwJOIN) or (Separator in [sepComma, sepParentheses]) then
  1383. begin
  1384. Result.TableName := '';
  1385. Result.Updateable := False;
  1386. end;
  1387. end;
  1388. ppWhere : begin
  1389. if (Keyword in [kwGROUP, kwORDER, kwLIMIT, kwROWS]) or
  1390. (Separator = sepEnd) then
  1391. begin
  1392. ParsePart := ppBogus;
  1393. Result.WhereStartPos := PStatementPart-PSQL;
  1394. if (Separator = sepEnd) then
  1395. Result.WhereStopPos := CurrentP-PSQL+1
  1396. else
  1397. Result.WhereStopPos := PhraseP-PSQL+1;
  1398. end
  1399. else if (Keyword = kwUNION) then
  1400. begin
  1401. ParsePart := ppBogus;
  1402. Result.Updateable := False;
  1403. end;
  1404. end;
  1405. end; {case}
  1406. end;
  1407. if Separator in [sepComment, sepParentheses, sepDoubleQuote] then
  1408. dec(CurrentP);
  1409. PhraseP := CurrentP+1;
  1410. end
  1411. end;
  1412. until CurrentP^=#0;
  1413. end;
  1414. function TSQLConnection.GetAsSQLText(Field : TField) : string;
  1415. begin
  1416. if (not assigned(Field)) or Field.IsNull then Result := 'Null'
  1417. else case field.DataType of
  1418. ftString : Result := QuotedStr(Field.AsString);
  1419. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Field.AsDateTime,FSqlFormatSettings) + '''';
  1420. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz',Field.AsDateTime,FSqlFormatSettings) + '''';
  1421. ftTime : Result := QuotedStr(TimeIntervalToString(Field.AsDateTime));
  1422. else
  1423. Result := Field.AsString;
  1424. end; {case}
  1425. end;
  1426. function TSQLConnection.GetAsSQLText(Param: TParam) : string;
  1427. begin
  1428. if (not assigned(Param)) or Param.IsNull then Result := 'Null'
  1429. else case Param.DataType of
  1430. ftGuid,
  1431. ftMemo,
  1432. ftFixedChar,
  1433. ftString : Result := QuotedStr(Param.AsString);
  1434. ftDate : Result := '''' + FormatDateTime('yyyy-mm-dd',Param.AsDateTime,FSQLFormatSettings) + '''';
  1435. ftTime : Result := QuotedStr(TimeIntervalToString(Param.AsDateTime));
  1436. ftDateTime : Result := '''' + FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Param.AsDateTime, FSQLFormatSettings) + '''';
  1437. ftCurrency,
  1438. ftBcd : Result := CurrToStr(Param.AsCurrency, FSQLFormatSettings);
  1439. ftFloat : Result := FloatToStr(Param.AsFloat, FSQLFormatSettings);
  1440. ftFMTBcd : Result := stringreplace(Param.AsString, DefaultFormatSettings.DecimalSeparator, FSQLFormatSettings.DecimalSeparator, []);
  1441. else
  1442. Result := Param.AsString;
  1443. end; {case}
  1444. end;
  1445. function TSQLConnection.GetHandle: pointer;
  1446. begin
  1447. Result := nil;
  1448. end;
  1449. function TSQLConnection.LogEvent(EventType: TDBEventType): Boolean;
  1450. begin
  1451. Result:=(Assigned(FOnLog) or Assigned(GlobalDBLogHook)) and (EventType in LogEvents);
  1452. end;
  1453. procedure TSQLConnection.LogParams(const AParams: TParams);
  1454. Var
  1455. S : String;
  1456. P : TParam;
  1457. begin
  1458. if not LogEvent(detParamValue) then
  1459. Exit;
  1460. For P in AParams do
  1461. begin
  1462. if P.IsNull then
  1463. S:='<NULL>'
  1464. else if (P.DataType in ftBlobTypes) and not (P.DataType in [ftMemo, ftFmtMemo,ftWideMemo]) then
  1465. S:='<BLOB>'
  1466. else
  1467. S:=P.AsString;
  1468. Log(detParamValue,Format(SLogParamValue,[P.Name,S]));
  1469. end;
  1470. end;
  1471. procedure TSQLConnection.Log(EventType: TDBEventType; const Msg: String);
  1472. Var
  1473. M : String;
  1474. begin
  1475. If LogEvent(EventType) then
  1476. begin
  1477. If Assigned(FonLog) then
  1478. FOnLog(Self,EventType,Msg);
  1479. If Assigned(GlobalDBLogHook) then
  1480. begin
  1481. If (Name<>'') then
  1482. M:=Name+' : '+Msg
  1483. else
  1484. M:=ClassName+' : '+Msg;
  1485. GlobalDBLogHook(Self,EventType,M);
  1486. end;
  1487. end;
  1488. end;
  1489. procedure TSQLConnection.RegisterStatement(S: TCustomSQLStatement);
  1490. begin
  1491. if FStatements.IndexOf(S)=-1 then
  1492. FStatements.Add(S);
  1493. end;
  1494. procedure TSQLConnection.UnRegisterStatement(S: TCustomSQLStatement);
  1495. begin
  1496. if Assigned(FStatements) then // Can be nil, when we are destroying and datasets are uncoupled.
  1497. FStatements.Remove(S);
  1498. end;
  1499. function TSQLConnection.InitialiseUpdateStatement(Query : TCustomSQLQuery; var qry : TCustomSQLQuery): TCustomSQLQuery;
  1500. begin
  1501. if not assigned(qry) then
  1502. begin
  1503. qry := TCustomSQLQuery.Create(nil);
  1504. qry.ParseSQL := False;
  1505. qry.DataBase := Self;
  1506. qry.Transaction := Query.SQLTransaction;
  1507. qry.Unidirectional:=True;
  1508. qry.UsePrimaryKeyAsKey:=False;
  1509. qry.PacketRecords:=1;
  1510. end;
  1511. Result:=qry;
  1512. end;
  1513. procedure TSQLConnection.AddFieldToUpdateWherePart(var sql_where : string;UpdateMode : TUpdateMode; F : TField);
  1514. begin
  1515. if (pfInKey in F.ProviderFlags)
  1516. or ((UpdateMode = upWhereAll) and (pfInWhere in F.ProviderFlags))
  1517. or ((UpdateMode = UpWhereChanged) and (pfInWhere in F.ProviderFlags) and (F.Value <> F.OldValue)) then
  1518. begin
  1519. if (sql_where<>'') then
  1520. sql_where:=sql_where + ' and ';
  1521. sql_where:= sql_where + '(' + FieldNameQuoteChars[0] + F.FieldName + FieldNameQuoteChars[1];
  1522. if F.OldValue = NULL then
  1523. sql_where := sql_where + ' is null '
  1524. else
  1525. sql_where := sql_where +'= :"' + 'OLD_' + F.FieldName + '"';
  1526. sql_where:=sql_where+') ';
  1527. end;
  1528. end;
  1529. function TSQLConnection.ConstructInsertSQL(Query: TCustomSQLQuery;
  1530. var ReturningClause: Boolean): string;
  1531. var x : integer;
  1532. sql_fields : string;
  1533. sql_values : string;
  1534. returning_fields : String;
  1535. F : TField;
  1536. begin
  1537. sql_fields := '';
  1538. sql_values := '';
  1539. returning_fields := '';
  1540. for x := 0 to Query.Fields.Count -1 do
  1541. begin
  1542. F:=Query.Fields[x];
  1543. if (not F.IsNull) and (pfInUpdate in F.ProviderFlags) and (not F.ReadOnly) then
  1544. begin
  1545. sql_fields := sql_fields + FieldNameQuoteChars[0] + F.FieldName + FieldNameQuoteChars[1] + ',';
  1546. sql_values := sql_values + ':"' + F.FieldName + '",';
  1547. end;
  1548. if ReturningClause and (pfRefreshOnInsert in F.ProviderFlags) then
  1549. returning_fields := returning_fields + FieldNameQuoteChars[0] + F.FieldName + FieldNameQuoteChars[1] + ',';
  1550. end;
  1551. if length(sql_fields) = 0 then
  1552. DatabaseErrorFmt(sNoUpdateFields,['insert'],self);
  1553. setlength(sql_fields,length(sql_fields)-1);
  1554. setlength(sql_values,length(sql_values)-1);
  1555. result := 'insert into ' + Query.FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
  1556. if ReturningClause then
  1557. begin
  1558. ReturningClause:=length(returning_fields) <> 0 ;
  1559. if ReturningClause then
  1560. begin
  1561. setlength(returning_fields,length(returning_fields)-1);
  1562. Result := Result + ' returning ' + returning_fields;
  1563. end;
  1564. end;
  1565. end;
  1566. function TSQLConnection.ConstructUpdateSQL(Query: TCustomSQLQuery;
  1567. var ReturningClause: Boolean): string;
  1568. var x : integer;
  1569. F : TField;
  1570. sql_set : string;
  1571. sql_where : string;
  1572. returning_fields : String;
  1573. begin
  1574. sql_set := '';
  1575. sql_where := '';
  1576. returning_fields := '';
  1577. for x := 0 to Query.Fields.Count -1 do
  1578. begin
  1579. F:=Query.Fields[x];
  1580. AddFieldToUpdateWherePart(sql_where,Query.UpdateMode,F);
  1581. if (pfInUpdate in F.ProviderFlags) and (not F.ReadOnly) then
  1582. sql_set := sql_set +FieldNameQuoteChars[0] + F.FieldName + FieldNameQuoteChars[1] +'=:"' + F.FieldName + '",';
  1583. if ReturningClause and (pfRefreshOnUpdate in F.ProviderFlags) then
  1584. returning_fields := returning_fields + FieldNameQuoteChars[0] + F.FieldName + FieldNameQuoteChars[1] + ',';
  1585. end;
  1586. if length(sql_set) = 0 then DatabaseErrorFmt(sNoUpdateFields,['update'],self);
  1587. setlength(sql_set,length(sql_set)-1);
  1588. if length(sql_where) = 0 then DatabaseErrorFmt(sNoWhereFields,['update'],self);
  1589. result := 'update ' + Query.FTableName + ' set ' + sql_set + ' where ' + sql_where;
  1590. if ReturningClause then
  1591. begin
  1592. ReturningClause:=length(returning_fields) <> 0 ;
  1593. if ReturningClause then
  1594. begin
  1595. setlength(returning_fields,length(returning_fields)-1);
  1596. Result := Result + ' returning ' + returning_fields;
  1597. end;
  1598. end;
  1599. end;
  1600. function TSQLConnection.ConstructDeleteSQL(Query : TCustomSQLQuery) : string;
  1601. var
  1602. x : integer;
  1603. sql_where : string;
  1604. begin
  1605. sql_where := '';
  1606. for x := 0 to Query.Fields.Count -1 do
  1607. AddFieldToUpdateWherePart(sql_where,Query.UpdateMode, Query.Fields[x]);
  1608. if length(sql_where) = 0 then
  1609. DatabaseErrorFmt(sNoWhereFields,['delete'],self);
  1610. result := 'delete from ' + Query.FTableName + ' where ' + sql_where;
  1611. end;
  1612. function TSQLConnection.ConstructRefreshSQL(Query: TCustomSQLQuery; UpdateKind: TUpdateKind): string;
  1613. Var
  1614. F : TField;
  1615. PF : TProviderFlag;
  1616. Where : String;
  1617. begin
  1618. Result:=Query.RefreshSQL.Text;
  1619. if (Result='') then
  1620. begin
  1621. Where:='';
  1622. PF:=RefreshFlags[UpdateKind];
  1623. For F in Query.Fields do
  1624. begin
  1625. if PF in F.ProviderFlags then
  1626. begin
  1627. if (Result<>'') then
  1628. Result:=Result+', ';
  1629. if (F.Origin<>'') and (F.Origin<>F.FieldName) then
  1630. Result:=Result+F.Origin+' AS '+F.FieldName
  1631. else
  1632. Result:=Result+FieldNameQuoteChars[0]+F.FieldName+FieldNameQuoteChars[1]
  1633. end;
  1634. if pfInkey in F.ProviderFlags then
  1635. begin
  1636. if (Where<>'') then
  1637. Where:=Where+' AND ';
  1638. Where:=Where+'('+FieldNameQuoteChars[0]+F.FieldName+FieldNameQuoteChars[1]+' = :'+F.FieldName+')';
  1639. end;
  1640. end;
  1641. if (Where='') then
  1642. DatabaseError(SErrNoKeyFieldForRefreshClause,Query);
  1643. Result:='SELECT '+Result+' FROM '+Query.FTableName+' WHERE '+Where;
  1644. end;
  1645. end;
  1646. procedure TSQLConnection.ApplyFieldUpdate(C : TSQLCursor; P : TSQLDBParam;F : TField; UseOldValue : Boolean);
  1647. begin
  1648. if UseOldValue then
  1649. P.AssignFieldValue(F,F.OldValue)
  1650. else
  1651. P.AssignFieldValue(F,F.Value);
  1652. P.FFieldDef:=F.FieldDef;
  1653. end;
  1654. procedure TSQLConnection.ApplyRecUpdate(Query: TCustomSQLQuery; UpdateKind: TUpdateKind);
  1655. var
  1656. qry : TCustomSQLQuery;
  1657. s : string;
  1658. x : integer;
  1659. Fld : TField;
  1660. P : TParam;
  1661. B,ReturningClause : Boolean;
  1662. begin
  1663. qry:=Nil;
  1664. ReturningClause:=(sqSupportReturning in ConnOptions) and not (sqoRefreshUsingSelect in Query.Options) and (Query.RefreshSQL.Count=0);
  1665. case UpdateKind of
  1666. ukInsert : begin
  1667. s := Trim(Query.FInsertSQL.Text);
  1668. if s = '' then
  1669. s := ConstructInsertSQL(Query, ReturningClause)
  1670. else
  1671. ReturningClause := False;
  1672. qry := InitialiseUpdateStatement(Query, Query.FInsertQry);
  1673. end;
  1674. ukModify : begin
  1675. s := Trim(Query.FUpdateSQL.Text);
  1676. if s = '' then begin
  1677. //if not assigned(Query.FUpdateQry) or (Query.UpdateMode<>upWhereKeyOnly) then // first time or dynamic where part
  1678. s := ConstructUpdateSQL(Query, ReturningClause);
  1679. end
  1680. else
  1681. ReturningClause := False;
  1682. qry := InitialiseUpdateStatement(Query, Query.FUpdateQry);
  1683. end;
  1684. ukDelete : begin
  1685. s := Trim(Query.FDeleteSQL.Text);
  1686. if (s='') and (not assigned(Query.FDeleteQry) or (Query.UpdateMode<>upWhereKeyOnly)) then
  1687. s := ConstructDeleteSQL(Query);
  1688. ReturningClause := False;
  1689. qry := InitialiseUpdateStatement(Query, Query.FDeleteQry);
  1690. end;
  1691. end;
  1692. if (s<>'') and (qry.SQL.Text<>s) then
  1693. qry.SQL.Text:=s; //assign only when changed, to avoid UnPrepare/Prepare
  1694. Assert(qry.SQL.Text<>'');
  1695. for x:=0 to Qry.Params.Count-1 do
  1696. begin
  1697. P:=Qry.Params[x];
  1698. S:=p.name;
  1699. B:=SameText(leftstr(S,4),'OLD_');
  1700. if B then
  1701. Delete(S,1,4);
  1702. Fld:=Query.FieldByName(S);
  1703. ApplyFieldUpdate(Query.Cursor,P as TSQLDBParam,Fld,B);
  1704. end;
  1705. if ReturningClause then
  1706. begin
  1707. Qry.Close;
  1708. Qry.Open
  1709. end
  1710. else
  1711. Qry.Execute;
  1712. if (scoApplyUpdatesChecksRowsAffected in Options) and (Qry.RowsAffected<>1) then
  1713. begin
  1714. Qry.Close;
  1715. DatabaseErrorFmt(SErrFailedToUpdateRecord, [Qry.RowsAffected], Query);
  1716. end;
  1717. if ReturningClause then
  1718. Query.ApplyReturningResult(Qry,UpdateKind);
  1719. end;
  1720. function TSQLConnection.RefreshLastInsertID(Query: TCustomSQLQuery; Field: TField): Boolean;
  1721. begin
  1722. Result:=False;
  1723. end;
  1724. procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
  1725. begin
  1726. // empty
  1727. end;
  1728. function TSQLConnection.StartImplicitTransaction(trans: TSQLHandle; aParams: string): boolean;
  1729. begin
  1730. Result:=False;
  1731. end;
  1732. function TSQLConnection.GetSchemaInfoSQL( SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string;
  1733. begin
  1734. case SchemaType of
  1735. stProcedures: Result := 'SELECT *, ROUTINE_NAME AS PROCEDURE_NAME FROM INFORMATION_SCHEMA.ROUTINES';
  1736. stSchemata : Result := 'SELECT * FROM INFORMATION_SCHEMA.SCHEMATA';
  1737. stSequences : Result := 'SELECT * FROM INFORMATION_SCHEMA.SEQUENCES';
  1738. else DatabaseError(SMetadataUnavailable);
  1739. end;
  1740. end;
  1741. function TSQLConnection.GetNextValueSQL(const SequenceName: string; IncrementBy: Integer): string;
  1742. begin
  1743. Result := 'SELECT NEXT VALUE FOR ' + SequenceName;
  1744. end;
  1745. function TSQLConnection.GetNextValue(const SequenceName: string; IncrementBy: integer): Int64;
  1746. var
  1747. Q: TCustomSQLQuery;
  1748. begin
  1749. Result := 0;
  1750. Q := TCustomSQLQuery.Create(nil);
  1751. try
  1752. Q.DataBase := Self;
  1753. Q.Transaction := Transaction;
  1754. Q.SQL.Text := GetNextValueSQL(SequenceName, IncrementBy);
  1755. Q.Open;
  1756. if not Q.Eof then
  1757. Result := Q.Fields[0].AsLargeInt;
  1758. Q.Close;
  1759. finally
  1760. FreeAndNil(Q);
  1761. end;
  1762. end;
  1763. procedure TSQLConnection.MaybeConnect;
  1764. begin
  1765. If Not Connected then
  1766. begin
  1767. If (scoExplicitConnect in Options) then
  1768. DatabaseErrorFmt(SErrImplicitConnect,[Name]);
  1769. Connected:=True;
  1770. end;
  1771. end;
  1772. procedure TSQLConnection.CreateDB;
  1773. begin
  1774. DatabaseError(SNotSupported);
  1775. end;
  1776. procedure TSQLConnection.DropDB;
  1777. begin
  1778. DatabaseError(SNotSupported);
  1779. end;
  1780. { TSQLTransaction }
  1781. constructor TSQLTransaction.Create(AOwner : TComponent);
  1782. begin
  1783. inherited Create(AOwner);
  1784. FParams := TStringList.Create;
  1785. Action := caRollBack;
  1786. end;
  1787. destructor TSQLTransaction.Destroy;
  1788. begin
  1789. EndTransaction;
  1790. FreeAndNil(FTrans);
  1791. FreeAndNil(FParams);
  1792. inherited Destroy;
  1793. end;
  1794. procedure TSQLTransaction.EndTransaction;
  1795. begin
  1796. Case Action of
  1797. caCommit, caCommitRetaining :
  1798. Commit;
  1799. caNone,
  1800. caRollback, caRollbackRetaining :
  1801. if not (stoUseImplicit in Options) then
  1802. RollBack
  1803. else
  1804. CloseTrans;
  1805. end;
  1806. end;
  1807. procedure TSQLTransaction.SetParams(const AValue: TStringList);
  1808. begin
  1809. FParams.Assign(AValue);
  1810. end;
  1811. function TSQLTransaction.GetSQLConnection: TSQLConnection;
  1812. begin
  1813. Result:=Database as TSQLConnection;
  1814. end;
  1815. procedure TSQLTransaction.SetOptions(AValue: TSQLTransactionOptions);
  1816. begin
  1817. if FOptions=AValue then Exit;
  1818. if (stoUseImplicit in Avalue) and Assigned(SQLConnection) And Not (sqImplicitTransaction in SQLConnection.ConnOptions) then
  1819. DatabaseErrorFmt(SErrNoImplicitTransaction, [SQLConnection.ClassName]);
  1820. FOptions:=AValue;
  1821. end;
  1822. procedure TSQLTransaction.SetSQLConnection(AValue: TSQLConnection);
  1823. begin
  1824. Database:=AValue;
  1825. end;
  1826. Procedure TSQLTransaction.MaybeStartTransaction;
  1827. begin
  1828. if not Active then
  1829. begin
  1830. if (stoExplicitStart in Options) then
  1831. DatabaseErrorFmt(SErrImplictTransactionStart, [Database.Name,Name]);
  1832. StartTransaction;
  1833. end;
  1834. end;
  1835. function TSQLTransaction.GetHandle: Pointer;
  1836. begin
  1837. Result := SQLConnection.GetTransactionHandle(FTrans);
  1838. end;
  1839. Function TSQLTransaction.AllowClose(DS: TDBDataset): Boolean;
  1840. begin
  1841. if (DS is TSQLQuery) then
  1842. Result:=not (sqoKeepOpenOnCommit in TSQLQuery(DS).Options)
  1843. else
  1844. Result:=Inherited AllowClose(DS);
  1845. end;
  1846. procedure TSQLTransaction.Commit;
  1847. begin
  1848. if Active then
  1849. begin
  1850. CloseDataSets;
  1851. If LogEvent(detCommit) then
  1852. Log(detCommit,SCommitting);
  1853. if (stoUseImplicit in Options) or SQLConnection.AttemptCommit(FTrans) then
  1854. begin
  1855. CloseTrans;
  1856. FreeAndNil(FTrans);
  1857. end;
  1858. end;
  1859. end;
  1860. procedure TSQLTransaction.CommitRetaining;
  1861. begin
  1862. if Active then
  1863. begin
  1864. If LogEvent(detCommit) then
  1865. Log(detCommit,SCommitRetaining);
  1866. SQLConnection.CommitRetaining(FTrans);
  1867. end;
  1868. end;
  1869. procedure TSQLTransaction.Rollback;
  1870. begin
  1871. if Active then
  1872. begin
  1873. if (stoUseImplicit in Options) then
  1874. DatabaseError(SErrImplicitNoRollBack);
  1875. CloseDataSets;
  1876. If LogEvent(detRollback) then
  1877. Log(detRollback,SRollingBack);
  1878. if SQLConnection.AttemptRollBack(FTrans) then
  1879. begin
  1880. CloseTrans;
  1881. FreeAndNil(FTrans);
  1882. end;
  1883. end;
  1884. end;
  1885. procedure TSQLTransaction.RollbackRetaining;
  1886. begin
  1887. if Active then
  1888. begin
  1889. if (stoUseImplicit in Options) then
  1890. DatabaseError(SErrImplicitNoRollBack);
  1891. If LogEvent(detRollback) then
  1892. Log(detRollback,SRollBackRetaining);
  1893. SQLConnection.RollBackRetaining(FTrans);
  1894. end;
  1895. end;
  1896. procedure TSQLTransaction.StartTransaction;
  1897. var db : TSQLConnection;
  1898. begin
  1899. if Active then
  1900. DatabaseError(SErrTransAlreadyActive);
  1901. db := SQLConnection;
  1902. if Db = nil then
  1903. DatabaseError(SErrDatabasenAssigned);
  1904. Db.MaybeConnect;
  1905. if not assigned(FTrans) then FTrans := Db.AllocateTransactionHandle;
  1906. if (stoUseImplicit in Options) then
  1907. begin
  1908. if Db.StartImplicitTransaction(FTrans,FParams.CommaText) then
  1909. OpenTrans
  1910. end
  1911. else
  1912. begin
  1913. if Db.StartDBTransaction(FTrans,FParams.CommaText) then
  1914. OpenTrans
  1915. end;
  1916. end;
  1917. Procedure TSQLTransaction.SetDatabase(Value: TDatabase);
  1918. begin
  1919. If Value<>Database then
  1920. begin
  1921. if Assigned(Value) and not (Value is TSQLConnection) then
  1922. DatabaseErrorFmt(SErrNotASQLConnection, [Value.Name], Self);
  1923. CheckInactive;
  1924. if (stoUseImplicit in Options) and Assigned(Value) and Not (sqImplicitTransaction in TSQLConnection(Value).ConnOptions) then
  1925. DatabaseErrorFmt(SErrNoImplicitTransaction, [Value.ClassName]);
  1926. If Assigned(Database) then
  1927. if SQLConnection.Transaction = Self then SQLConnection.Transaction := nil;
  1928. inherited;
  1929. If Assigned(Database) and not (csLoading in ComponentState) then
  1930. If SQLConnection.Transaction = Nil then SQLConnection.Transaction := Self;
  1931. end;
  1932. end;
  1933. Function TSQLTransaction.LogEvent(EventType: TDBEventType): Boolean;
  1934. begin
  1935. Result:=Assigned(Database) and SQLConnection.LogEvent(EventType);
  1936. end;
  1937. Procedure TSQLTransaction.Log(EventType: TDBEventType; Const Msg: String);
  1938. Var
  1939. M : String;
  1940. begin
  1941. If LogEvent(EventType) then
  1942. begin
  1943. If (Name<>'') then
  1944. M:=Name+' : '+Msg
  1945. else
  1946. M:=Msg;
  1947. SQLConnection.Log(EventType,M);
  1948. end;
  1949. end;
  1950. { TSQLSequence }
  1951. constructor TSQLSequence.Create(AQuery: TCustomSQLQuery);
  1952. begin
  1953. inherited Create;
  1954. FQuery := AQuery;
  1955. FApplyEvent := saeOnNewRecord;
  1956. FIncrementBy := 1;
  1957. end;
  1958. procedure TSQLSequence.Assign(Source: TPersistent);
  1959. var SourceSequence: TSQLSequence;
  1960. begin
  1961. if Source is TSQLSequence then
  1962. begin
  1963. SourceSequence := TSQLSequence(Source);
  1964. FFieldName := SourceSequence.FieldName;
  1965. FSequenceName := SourceSequence.SequenceName;
  1966. FIncrementBy := SourceSequence.IncrementBy;
  1967. FApplyEvent := SourceSequence.ApplyEvent;
  1968. end
  1969. else
  1970. inherited;
  1971. end;
  1972. procedure TSQLSequence.Apply;
  1973. var Field: TField;
  1974. begin
  1975. if Assigned(FQuery) and (FSequenceName<>'') and (FFieldName<>'') then
  1976. begin
  1977. Field := FQuery.FindField(FFieldName);
  1978. if Assigned(Field) and Field.IsNull then
  1979. Field.AsLargeInt := GetNextValue;
  1980. end;
  1981. end;
  1982. function TSQLSequence.GetNextValue: Int64;
  1983. begin
  1984. if (FQuery=Nil) or (FQuery.SQLConnection=Nil) then
  1985. DatabaseError(SErrDatabasenAssigned);
  1986. Result := FQuery.SQLConnection.GetNextValue(FSequenceName, FIncrementBy);
  1987. end;
  1988. Type
  1989. { TQuerySQLStatement }
  1990. TQuerySQLStatement = Class(TCustomSQLStatement)
  1991. protected
  1992. FQuery : TCustomSQLQuery;
  1993. Function CreateDataLink : TDataLink; override;
  1994. Function GetSchemaType : TSchemaType; override;
  1995. Function GetSchemaObjectName : String; override;
  1996. Function GetSchemaPattern: String; override;
  1997. procedure GetStatementInfo(var ASQL: String; out Info: TSQLStatementInfo); override;
  1998. procedure OnChangeSQL(Sender : TObject); override;
  1999. end;
  2000. { TQuerySQLStatement }
  2001. function TQuerySQLStatement.CreateDataLink: TDataLink;
  2002. begin
  2003. Result:=TMasterParamsDataLink.Create(FQuery);
  2004. end;
  2005. function TQuerySQLStatement.GetSchemaType: TSchemaType;
  2006. begin
  2007. if Assigned(FQuery) then
  2008. Result:=FQuery.FSchemaType
  2009. else
  2010. Result:=stNoSchema;
  2011. end;
  2012. function TQuerySQLStatement.GetSchemaObjectName: String;
  2013. begin
  2014. if Assigned(FQuery) then
  2015. Result:=FQuery.FSchemaObjectname
  2016. else
  2017. Result:=inherited GetSchemaObjectName;
  2018. end;
  2019. function TQuerySQLStatement.GetSchemaPattern: String;
  2020. begin
  2021. if Assigned(FQuery) then
  2022. Result:=FQuery.FSchemaPattern
  2023. else
  2024. Result:=inherited GetSchemaPattern;
  2025. end;
  2026. procedure TQuerySQLStatement.GetStatementInfo(var ASQL: String; out Info: TSQLStatementInfo);
  2027. begin
  2028. inherited GetStatementInfo(ASQL, Info);
  2029. If Assigned(FQuery) then
  2030. // Note: practical side effect of switch off ParseSQL is that UpdateServerIndexDefs is bypassed
  2031. // which is used as performance tuning option
  2032. if (FQuery.FSchemaType = stNoSchema) and FParseSQL then
  2033. begin
  2034. FQuery.FUpdateable:=Info.Updateable;
  2035. FQuery.FTableName:=Info.TableName;
  2036. FQuery.FWhereStartPos:=Info.WhereStartPos;
  2037. FQuery.FWhereStopPos:=Info.WhereStopPos;
  2038. if FQuery.ServerFiltered then
  2039. ASQL:=FQuery.AddFilter(ASQL);
  2040. end
  2041. else
  2042. begin
  2043. FQuery.FUpdateable:=false;
  2044. FQuery.FTableName:='';
  2045. FQuery.FWhereStartPos:=0;
  2046. FQuery.FWhereStopPos:=0;
  2047. end;
  2048. end;
  2049. procedure TQuerySQLStatement.OnChangeSQL(Sender: TObject);
  2050. begin
  2051. UnPrepare;
  2052. inherited OnChangeSQL(Sender);
  2053. If ParamCheck and Assigned(FDataLink) then
  2054. (FDataLink as TMasterParamsDataLink).RefreshParamNames;
  2055. FQuery.ServerIndexDefs.Updated:=false;
  2056. end;
  2057. { TCustomSQLQuery }
  2058. constructor TCustomSQLQuery.Create(AOwner : TComponent);
  2059. Var
  2060. F : TQuerySQLStatement;
  2061. begin
  2062. inherited Create(AOwner);
  2063. F:=TQuerySQLStatement.Create(Self);
  2064. F.FQuery:=Self;
  2065. FStatement:=F;
  2066. FInsertSQL := TStringList.Create;
  2067. FInsertSQL.OnChange := @OnChangeModifySQL;
  2068. FUpdateSQL := TStringList.Create;
  2069. FUpdateSQL.OnChange := @OnChangeModifySQL;
  2070. FDeleteSQL := TStringList.Create;
  2071. FDeleteSQL.OnChange := @OnChangeModifySQL;
  2072. FRefreshSQL := TStringList.Create;
  2073. FRefreshSQL.OnChange := @OnChangeModifySQL;
  2074. FSequence := TSQLSequence.Create(Self);
  2075. FServerIndexDefs := TServerIndexDefs.Create(Self);
  2076. FServerFiltered := False;
  2077. FServerFilterText := '';
  2078. FSchemaType:=stNoSchema;
  2079. FSchemaObjectName:='';
  2080. FSchemaPattern:='';
  2081. // Delphi has upWhereAll as default, but since strings and oldvalue's don't work yet
  2082. // (variants) set it to upWhereKeyOnly
  2083. FUpdateMode := upWhereKeyOnly;
  2084. FUsePrimaryKeyAsKey := True;
  2085. end;
  2086. destructor TCustomSQLQuery.Destroy;
  2087. begin
  2088. if Active then Close;
  2089. UnPrepare;
  2090. FreeAndNil(FStatement);
  2091. FreeAndNil(FInsertSQL);
  2092. FreeAndNil(FUpdateSQL);
  2093. FreeAndNil(FDeleteSQL);
  2094. FreeAndNil(FRefreshSQL);
  2095. FreeAndNil(FSequence);
  2096. FreeAndNil(FServerIndexDefs);
  2097. inherited Destroy;
  2098. end;
  2099. function TCustomSQLQuery.ParamByName(const AParamName: String): TParam;
  2100. begin
  2101. Result:=Params.ParamByName(AParamName);
  2102. end;
  2103. procedure TCustomSQLQuery.OnChangeModifySQL(Sender : TObject);
  2104. begin
  2105. CheckInactive;
  2106. end;
  2107. procedure TCustomSQLQuery.SetDatabase(Value : TDatabase);
  2108. var DB : TSQLConnection;
  2109. begin
  2110. if Database = Value then Exit;
  2111. if Assigned(Value) and not (Value is TSQLConnection) then
  2112. DatabaseErrorFmt(SErrNotASQLConnection, [Value.Name], Self);
  2113. UnPrepare;
  2114. DB := TSQLConnection(Value);
  2115. If Assigned(FStatement) then
  2116. FStatement.Database := DB;
  2117. inherited;
  2118. if Assigned(DB) and Assigned(DB.Transaction) and (not Assigned(Transaction) or (Transaction.DataBase<>Database)) then
  2119. Transaction := DB.Transaction;
  2120. end;
  2121. procedure TCustomSQLQuery.SetTransaction(Value: TDBTransaction);
  2122. begin
  2123. if Transaction = Value then Exit;
  2124. UnPrepare;
  2125. inherited;
  2126. If Assigned(FStatement) then
  2127. FStatement.Transaction := TSQLTransaction(Value);
  2128. If Assigned(Transaction) and Assigned(Transaction.DataBase) and (Database<>Transaction.DataBase) then
  2129. Database := Transaction.Database;
  2130. end;
  2131. function TCustomSQLQuery.IsPrepared: Boolean;
  2132. begin
  2133. if Assigned(Fstatement) then
  2134. Result := FStatement.Prepared
  2135. else
  2136. Result := False;
  2137. end;
  2138. function TCustomSQLQuery.AddFilter(SQLstr: string): string;
  2139. begin
  2140. if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
  2141. begin
  2142. system.insert('(',SQLstr,FWhereStartPos+1);
  2143. system.insert(')',SQLstr,FWhereStopPos+1);
  2144. end;
  2145. if FWhereStartPos = 0 then
  2146. SQLstr := SQLstr + ' where (' + ServerFilter + ')'
  2147. else if FWhereStopPos > 0 then
  2148. system.insert(' and ('+ServerFilter+') ',SQLstr,FWhereStopPos+2)
  2149. else
  2150. system.insert(' where ('+ServerFilter+') ',SQLstr,FWhereStartPos);
  2151. Result := SQLstr;
  2152. end;
  2153. function TCustomSQLQuery.NeedRefreshRecord(UpdateKind: TUpdateKind): Boolean;
  2154. Var
  2155. PF : TProviderFlag;
  2156. I : Integer;
  2157. DoReturning : Boolean;
  2158. begin
  2159. Result:=(FRefreshSQL.Count<>0);
  2160. DoReturning:=(sqSupportReturning in SQLConnection.ConnOptions) and not (sqoRefreshUsingSelect in Options);
  2161. if Not (Result or DoReturning) then
  2162. begin
  2163. PF:=RefreshFlags[UpdateKind];
  2164. I:=0;
  2165. While (Not Result) and (I<Fields.Count) do
  2166. begin
  2167. Result:=PF in Fields[i].ProviderFlags;
  2168. Inc(I);
  2169. end;
  2170. end;
  2171. end;
  2172. function TCustomSQLQuery.RefreshRecord(UpdateKind: TUpdateKind): Boolean;
  2173. Var
  2174. Q : TCustomSQLQuery;
  2175. P : TParam;
  2176. F,FD : TField;
  2177. N : String;
  2178. begin
  2179. Result:=False;
  2180. Q:=TCustomSQLQuery.Create(Nil);
  2181. try
  2182. Q.Database:=Self.Database;
  2183. Q.Transaction:=Self.Transaction;
  2184. Q.SQL.Text:=SQLConnection.ConstructRefreshSQL(Self,UpdateKind);
  2185. For P in Q.Params do
  2186. begin
  2187. N:=P.Name;
  2188. If CompareText(Copy(N,1,4),'OLD_')=0 then
  2189. system.Delete(N,1,4);
  2190. F:=Fields.FindField(N);
  2191. if Assigned(F) then
  2192. P.AssignField(F);
  2193. end;
  2194. Q.Open;
  2195. try
  2196. if (Q.EOF and Q.BOF) then
  2197. DatabaseError(SErrRefreshEmptyResult,Self)
  2198. else
  2199. begin
  2200. if Q.RecordCount<>1 then
  2201. DatabaseErrorFmt(SErrRefreshNotSingleton,[Q.RecordCount],Self);
  2202. For F in Q.Fields do
  2203. begin
  2204. FD:=Fields.FindField(F.FieldName);
  2205. if Assigned(FD) then
  2206. begin
  2207. FD.Assign(F);
  2208. Result:=True; // We could check if the new value differs from the old, but we won't.
  2209. end;
  2210. end;
  2211. end
  2212. finally
  2213. Q.Close;
  2214. end;
  2215. finally
  2216. Q.Free;
  2217. end;
  2218. end;
  2219. procedure TCustomSQLQuery.ApplyReturningResult(Q: TCustomSQLQuery; UpdateKind : TUpdateKind);
  2220. Var
  2221. S : TDataSetState;
  2222. refreshFlag : TProviderFlag;
  2223. F : TField;
  2224. begin
  2225. RefreshFlag:=RefreshFlags[UpdateKind];
  2226. S:=SetTempState(dsRefreshFields);
  2227. try
  2228. For F in Fields do
  2229. if RefreshFlag in F.ProviderFlags then
  2230. F.Assign(Q.FieldByName(F.FieldName));
  2231. finally
  2232. RestoreState(S);
  2233. end;
  2234. end;
  2235. procedure TCustomSQLQuery.ApplyFilter;
  2236. begin
  2237. FreeFldBuffers;
  2238. FStatement.Unprepare;
  2239. FIsEOF := False;
  2240. inherited InternalClose;
  2241. FStatement.DoPrepare;
  2242. FStatement.DoExecute;
  2243. inherited InternalOpen;
  2244. First;
  2245. end;
  2246. procedure TCustomSQLQuery.SetActive(Value: Boolean);
  2247. begin
  2248. inherited SetActive(Value);
  2249. // The query is UnPrepared, so that if a transaction closes all datasets
  2250. // they also get unprepared
  2251. if not Value and IsPrepared then UnPrepare;
  2252. end;
  2253. procedure TCustomSQLQuery.SetServerFiltered(Value: Boolean);
  2254. begin
  2255. if Value and not ParseSQL then
  2256. DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
  2257. if (ServerFiltered <> Value) then
  2258. begin
  2259. FServerFiltered := Value;
  2260. if Active then ApplyFilter;
  2261. end;
  2262. end;
  2263. procedure TCustomSQLQuery.SetServerFilterText(const Value: string);
  2264. begin
  2265. if Value <> ServerFilter then
  2266. begin
  2267. FServerFilterText := Value;
  2268. if Active then ApplyFilter;
  2269. end;
  2270. end;
  2271. procedure TCustomSQLQuery.Prepare;
  2272. begin
  2273. FStatement.Prepare;
  2274. if Assigned(FStatement.FCursor) then
  2275. with FStatement.FCursor do
  2276. FInitFieldDef := FSelectable;
  2277. end;
  2278. procedure TCustomSQLQuery.UnPrepare;
  2279. begin
  2280. CheckInactive;
  2281. If Assigned(FStatement) then
  2282. FStatement.Unprepare;
  2283. end;
  2284. procedure TCustomSQLQuery.FreeFldBuffers;
  2285. begin
  2286. if assigned(Cursor) then
  2287. SQLConnection.FreeFldBuffers(Cursor);
  2288. end;
  2289. function TCustomSQLQuery.GetParamCheck: Boolean;
  2290. begin
  2291. Result:=FStatement.ParamCheck;
  2292. end;
  2293. function TCustomSQLQuery.GetParams: TParams;
  2294. begin
  2295. Result:=FStatement.Params;
  2296. end;
  2297. function TCustomSQLQuery.GetParseSQL: Boolean;
  2298. begin
  2299. Result:=FStatement.ParseSQL;
  2300. end;
  2301. function TCustomSQLQuery.GetServerIndexDefs: TServerIndexDefs;
  2302. begin
  2303. Result := FServerIndexDefs;
  2304. end;
  2305. function TCustomSQLQuery.GetSQL: TStringList;
  2306. begin
  2307. Result:=TStringList(Fstatement.SQL);
  2308. end;
  2309. function TCustomSQLQuery.GetSQLConnection: TSQLConnection;
  2310. begin
  2311. Result:=Database as TSQLConnection;
  2312. end;
  2313. function TCustomSQLQuery.GetSQLTransaction: TSQLTransaction;
  2314. begin
  2315. Result:=Transaction as TSQLTransaction;
  2316. end;
  2317. function TCustomSQLQuery.Cursor: TSQLCursor;
  2318. begin
  2319. Result:=FStatement.Cursor;
  2320. end;
  2321. function TCustomSQLQuery.Fetch : boolean;
  2322. begin
  2323. if Not Assigned(Cursor) then
  2324. Exit;
  2325. if not Cursor.FSelectable then
  2326. Exit;
  2327. If LogEvent(detFetch) then
  2328. Log(detFetch,FStatement.FServerSQL);
  2329. if not FIsEof then FIsEOF := not SQLConnection.Fetch(Cursor);
  2330. Result := not FIsEOF;
  2331. end;
  2332. procedure TCustomSQLQuery.Execute;
  2333. begin
  2334. FStatement.Execute;
  2335. end;
  2336. function TCustomSQLQuery.RowsAffected: TRowsCount;
  2337. begin
  2338. Result:=FStatement.RowsAffected;
  2339. end;
  2340. function TCustomSQLQuery.LoadField(FieldDef : TFieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  2341. begin
  2342. result := SQLConnection.LoadField(Cursor,FieldDef,buffer, Createblob)
  2343. end;
  2344. procedure TCustomSQLQuery.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  2345. ABlobBuf: PBufBlobField);
  2346. begin
  2347. SQLConnection.LoadBlobIntoBuffer(FieldDef, ABlobBuf, Cursor,SQLTransaction);
  2348. end;
  2349. procedure TCustomSQLQuery.InternalAddRecord(Buffer: Pointer; AAppend: Boolean);
  2350. begin
  2351. // not implemented - sql dataset
  2352. end;
  2353. procedure TCustomSQLQuery.InternalClose;
  2354. begin
  2355. if assigned(Cursor) then
  2356. begin
  2357. if Cursor.FSelectable then
  2358. FreeFldBuffers;
  2359. // Some SQLConnections does not support statement [un]preparation,
  2360. // so let them do cleanup f.e. cancel pending queries and/or free resultset
  2361. if not Prepared then FStatement.DoUnprepare;
  2362. end;
  2363. if DefaultFields then
  2364. DestroyFields;
  2365. FIsEOF := False;
  2366. if assigned(FUpdateQry) then FreeAndNil(FUpdateQry);
  2367. if assigned(FInsertQry) then FreeAndNil(FInsertQry);
  2368. if assigned(FDeleteQry) then FreeAndNil(FDeleteQry);
  2369. // FRecordSize := 0;
  2370. inherited InternalClose;
  2371. end;
  2372. procedure TCustomSQLQuery.InternalInitFieldDefs;
  2373. begin
  2374. if FLoadingFieldDefs then
  2375. Exit;
  2376. FLoadingFieldDefs := True;
  2377. try
  2378. FieldDefs.Clear;
  2379. Prepare;
  2380. SQLConnection.AddFieldDefs(Cursor,FieldDefs);
  2381. finally
  2382. FLoadingFieldDefs := False;
  2383. if assigned(Cursor) then Cursor.FInitFieldDef := False;
  2384. end;
  2385. end;
  2386. procedure TCustomSQLQuery.InternalOpen;
  2387. var counter, fieldc : integer;
  2388. F : TField;
  2389. IndexFields : TStrings;
  2390. begin
  2391. if IsReadFromPacket then
  2392. begin
  2393. // When we read from file there is no need for Cursor, also note that Database may not be assigned
  2394. //FStatement.AllocateCursor;
  2395. //Cursor.FSelectable:=True;
  2396. //Cursor.FStatementType:=stSelect;
  2397. FUpdateable:=True;
  2398. end
  2399. else
  2400. begin
  2401. Prepare;
  2402. if not Cursor.FSelectable then
  2403. DatabaseError(SErrNoSelectStatement,Self);
  2404. // Call UpdateServerIndexDefs before Execute, to avoid problems with connections
  2405. // which do not allow processing multiple recordsets at a time. (Microsoft
  2406. // calls this MARS, see bug 13241)
  2407. if DefaultFields and FUpdateable and FusePrimaryKeyAsKey and (not IsUniDirectional) then
  2408. UpdateServerIndexDefs;
  2409. Execute;
  2410. if not Cursor.FSelectable then
  2411. DatabaseError(SErrNoSelectStatement,Self);
  2412. // InternalInitFieldDef is only called after a prepare. i.e. not twice if
  2413. // a dataset is opened - closed - opened.
  2414. if Cursor.FInitFieldDef then InternalInitFieldDefs;
  2415. if DefaultFields then
  2416. begin
  2417. CreateFields;
  2418. if FUpdateable and FusePrimaryKeyAsKey and (not IsUniDirectional) then
  2419. for counter := 0 to ServerIndexDefs.Count-1 do
  2420. if ixPrimary in ServerIndexDefs[counter].Options then
  2421. begin
  2422. IndexFields := TStringList.Create;
  2423. ExtractStrings([';'],[' '],pchar(ServerIndexDefs[counter].Fields),IndexFields);
  2424. for fieldc := 0 to IndexFields.Count-1 do
  2425. begin
  2426. F := FindField(IndexFields[fieldc]);
  2427. if F <> nil then
  2428. F.ProviderFlags := F.ProviderFlags + [pfInKey];
  2429. end;
  2430. IndexFields.Free;
  2431. end;
  2432. end;
  2433. end;
  2434. BindFields(True);
  2435. if not ReadOnly and not FUpdateable and (FSchemaType=stNoSchema) then
  2436. begin
  2437. if (trim(FDeleteSQL.Text) <> '') or (trim(FUpdateSQL.Text) <> '') or
  2438. (trim(FInsertSQL.Text) <> '') then FUpdateable := True;
  2439. end;
  2440. inherited InternalOpen;
  2441. end;
  2442. procedure TCustomSQLQuery.InternalRefresh;
  2443. begin
  2444. if (ChangeCount>0) and (sqoCancelUpdatesOnRefresh in Options) then
  2445. CancelUpdates;
  2446. inherited InternalRefresh;
  2447. end;
  2448. // public part
  2449. procedure TCustomSQLQuery.ExecSQL;
  2450. begin
  2451. try
  2452. Prepare;
  2453. Execute;
  2454. If sqoAutoCommit in Options then
  2455. begin
  2456. // Retrieve rows affected
  2457. FStatement.RowsAffected;
  2458. SQLTransaction.Commit;
  2459. end;
  2460. finally
  2461. // Cursor has to be assigned, or else the prepare went wrong before PrepareStatment was
  2462. // called, so UnPrepareStatement shoudn't be called either
  2463. // Don't deallocate cursor; f.e. RowsAffected is requested later
  2464. if not Prepared and (assigned(Database)) and (assigned(Cursor)) then SQLConnection.UnPrepareStatement(Cursor);
  2465. end;
  2466. end;
  2467. procedure TCustomSQLQuery.ApplyUpdates(MaxErrors: Integer);
  2468. begin
  2469. inherited ApplyUpdates(MaxErrors);
  2470. If sqoAutoCommit in Options then
  2471. begin
  2472. // Retrieve rows affected for last update.
  2473. FStatement.RowsAffected;
  2474. SQLTransaction.Commit;
  2475. end;
  2476. end;
  2477. procedure TCustomSQLQuery.Post;
  2478. begin
  2479. inherited Post;
  2480. If (sqoAutoApplyUpdates in Options) then
  2481. ApplyUpdates;
  2482. end;
  2483. procedure TCustomSQLQuery.Delete;
  2484. begin
  2485. inherited Delete;
  2486. If (sqoAutoApplyUpdates in Options) then
  2487. ApplyUpdates;
  2488. end;
  2489. procedure TCustomSQLQuery.SetReadOnly(AValue : Boolean);
  2490. begin
  2491. CheckInactive;
  2492. inherited SetReadOnly(AValue);
  2493. end;
  2494. procedure TCustomSQLQuery.SetParseSQL(AValue : Boolean);
  2495. begin
  2496. CheckInactive;
  2497. FStatement.ParseSQL:=AValue;
  2498. if not AValue then
  2499. FServerFiltered := False;
  2500. end;
  2501. procedure TCustomSQLQuery.SetSQL(const AValue: TStringList);
  2502. begin
  2503. FStatement.SQL.Assign(AValue);
  2504. end;
  2505. procedure TCustomSQLQuery.SetUsePrimaryKeyAsKey(AValue : Boolean);
  2506. begin
  2507. if not Active then FusePrimaryKeyAsKey := AValue
  2508. else
  2509. begin
  2510. // Just temporary, this should be possible in the future
  2511. DatabaseError(SActiveDataset);
  2512. end;
  2513. end;
  2514. procedure TCustomSQLQuery.UpdateServerIndexDefs;
  2515. begin
  2516. FServerIndexDefs.Clear;
  2517. if assigned(DataBase) and (FTableName<>'') then
  2518. SQLConnection.UpdateIndexDefs(ServerIndexDefs,FTableName);
  2519. end;
  2520. function TCustomSQLQuery.NeedLastInsertID: TField;
  2521. Var
  2522. I : Integer;
  2523. begin
  2524. Result:=Nil;
  2525. if sqLastInsertID in SQLConnection.ConnOptions then
  2526. begin
  2527. I:=0;
  2528. While (Result=Nil) and (I<Fields.Count) do
  2529. begin
  2530. Result:=Fields[i];
  2531. if (Result.DataType<>ftAutoInc) or not Result.IsNull then
  2532. Result:=Nil;
  2533. Inc(I);
  2534. end;
  2535. end
  2536. end;
  2537. function TCustomSQLQuery.RefreshLastInsertID(Field: TField): Boolean;
  2538. begin
  2539. Result:=SQLConnection.RefreshLastInsertID(Self, Field);
  2540. end;
  2541. procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind: TUpdateKind);
  2542. Var
  2543. DoRefresh : Boolean;
  2544. LastIDField : TField;
  2545. S : TDataSetState;
  2546. begin
  2547. // Moved to connection: the SQLConnection always has more information about types etc.
  2548. // than SQLQuery itself.
  2549. SQLConnection.ApplyRecUpdate(Self,UpdateKind);
  2550. if UpdateKind=ukInsert then
  2551. LastIDField:=NeedLastInsertID
  2552. else
  2553. LastIDField:=nil;
  2554. DoRefresh:=(UpdateKind in [ukModify,ukInsert]) and NeedRefreshRecord(UpdateKind);
  2555. if assigned(LastIDField) or DoRefresh then
  2556. begin
  2557. // updates fields directly in record buffer of TBufDataSet
  2558. // TDataSet buffers are resynchronized at end of ApplyUpdates process
  2559. S:=SetTempState(dsRefreshFields);
  2560. try
  2561. if assigned(LastIDField) then
  2562. RefreshLastInsertID(LastIDField);
  2563. if DoRefresh then
  2564. RefreshRecord(UpdateKind);
  2565. finally
  2566. RestoreState(S);
  2567. end;
  2568. end;
  2569. end;
  2570. procedure TCustomSQLQuery.SetPacketRecords(aValue: integer);
  2571. begin
  2572. if (AValue=PacketRecords) then exit;
  2573. if (AValue<>-1) and (sqoKeepOpenOnCommit in Options) then
  2574. DatabaseError(SErrDisconnectedPacketRecords);
  2575. Inherited SetPacketRecords(aValue);
  2576. end;
  2577. function TCustomSQLQuery.GetCanModify: Boolean;
  2578. begin
  2579. // the test for assigned(Cursor) is needed for the case that the dataset isn't opened
  2580. if assigned(Cursor) and (Cursor.FStatementType = stSelect) then
  2581. Result:= FUpdateable and (not ReadOnly) and (not IsUniDirectional)
  2582. else
  2583. Result := False;
  2584. end;
  2585. procedure TCustomSQLQuery.SetUpdateMode(AValue : TUpdateMode);
  2586. begin
  2587. FUpdateMode := AValue;
  2588. end;
  2589. procedure TCustomSQLQuery.SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string);
  2590. begin
  2591. FSchemaType:=ASchemaType;
  2592. FSchemaObjectName:=ASchemaObjectName;
  2593. FSchemaPattern:=ASchemaPattern;
  2594. end;
  2595. procedure TCustomSQLQuery.BeforeRefreshOpenCursor;
  2596. begin
  2597. // This is only necessary because TIBConnection can not re-open a
  2598. // prepared cursor. In fact this is wrong, but has never led to
  2599. // problems because in SetActive(false) queries are always
  2600. // unprepared. (which is also wrong, but has to be fixed later)
  2601. if IsPrepared then with SQLConnection do
  2602. UnPrepareStatement(Cursor);
  2603. end;
  2604. function TCustomSQLQuery.LogEvent(EventType: TDBEventType): Boolean;
  2605. begin
  2606. Result:=Assigned(Database) and SQLConnection.LogEvent(EventType);
  2607. end;
  2608. procedure TCustomSQLQuery.Log(EventType: TDBEventType; const Msg: String);
  2609. Var
  2610. M : String;
  2611. begin
  2612. If LogEvent(EventType) then
  2613. begin
  2614. M:=Msg;
  2615. If (Name<>'') then
  2616. M:=Name+' : '+M;
  2617. SQLConnection.Log(EventType,M);
  2618. end;
  2619. end;
  2620. class function TCustomSQLQuery.FieldDefsClass: TFieldDefsClass;
  2621. begin
  2622. Result:=TSQLDBFieldDefs;
  2623. end;
  2624. function TCustomSQLQuery.GetStatementType : TStatementType;
  2625. begin
  2626. if Assigned(Cursor) then
  2627. Result:=Cursor.FStatementType
  2628. else
  2629. Result:=stUnknown;
  2630. end;
  2631. procedure TCustomSQLQuery.SetParamCheck(AValue: Boolean);
  2632. begin
  2633. FStatement.ParamCheck:=AValue;
  2634. end;
  2635. procedure TCustomSQLQuery.SetOptions(AValue: TSQLQueryOptions);
  2636. begin
  2637. if FOptions=AValue then Exit;
  2638. CheckInactive;
  2639. FOptions:=AValue;
  2640. if sqoKeepOpenOnCommit in FOptions then
  2641. PacketRecords:=-1;
  2642. end;
  2643. procedure TCustomSQLQuery.SetSQLConnection(AValue: TSQLConnection);
  2644. begin
  2645. Database:=AValue;
  2646. end;
  2647. procedure TCustomSQLQuery.SetSQLTransaction(AValue: TSQLTransaction);
  2648. begin
  2649. Transaction:=AValue;
  2650. end;
  2651. procedure TCustomSQLQuery.SetInsertSQL(const AValue: TStringList);
  2652. begin
  2653. FInsertSQL.Assign(AValue);
  2654. end;
  2655. procedure TCustomSQLQuery.SetUpdateSQL(const AValue: TStringList);
  2656. begin
  2657. FUpdateSQL.Assign(AValue);
  2658. end;
  2659. procedure TCustomSQLQuery.SetDeleteSQL(const AValue: TStringList);
  2660. begin
  2661. FDeleteSQL.Assign(AValue);
  2662. end;
  2663. procedure TCustomSQLQuery.SetRefreshSQL(const AValue: TStringList);
  2664. begin
  2665. FRefreshSQL.Assign(AValue);
  2666. end;
  2667. procedure TCustomSQLQuery.SetParams(AValue: TParams);
  2668. begin
  2669. FStatement.Params.Assign(AValue);
  2670. end;
  2671. procedure TCustomSQLQuery.SetDataSource(AValue: TDataSource);
  2672. Var
  2673. DS : TDataSource;
  2674. begin
  2675. DS:=DataSource;
  2676. If (AValue<>DS) then
  2677. begin
  2678. If Assigned(AValue) and (AValue.Dataset=Self) then
  2679. DatabaseError(SErrCircularDataSourceReferenceNotAllowed,Self);
  2680. If Assigned(DS) then
  2681. DS.RemoveFreeNotification(Self);
  2682. FStatement.DataSource:=AValue;
  2683. end;
  2684. end;
  2685. function TCustomSQLQuery.GetDataSource: TDataSource;
  2686. begin
  2687. If Assigned(FStatement) then
  2688. Result:=FStatement.DataSource
  2689. else
  2690. Result:=Nil;
  2691. end;
  2692. procedure TCustomSQLQuery.Notification(AComponent: TComponent; Operation: TOperation);
  2693. begin
  2694. Inherited;
  2695. If (Operation=opRemove) and (AComponent=DataSource) then
  2696. DataSource:=Nil;
  2697. end;
  2698. procedure TCustomSQLQuery.DoOnNewRecord;
  2699. begin
  2700. inherited;
  2701. if FSequence.ApplyEvent = saeOnNewRecord then
  2702. FSequence.Apply;
  2703. end;
  2704. procedure TCustomSQLQuery.DoBeforePost;
  2705. begin
  2706. if (State = dsInsert) and (FSequence.ApplyEvent = saeOnPost) then
  2707. FSequence.Apply;
  2708. inherited;
  2709. end;
  2710. function TCustomSQLQuery.PSGetUpdateException(E: Exception; Prev: EUpdateError): EUpdateError;
  2711. var
  2712. PrevErrorCode, ErrorCode: Integer;
  2713. begin
  2714. if Assigned(Prev) then
  2715. PrevErrorCode := Prev.ErrorCode
  2716. else
  2717. PrevErrorCode := 0;
  2718. if E is ESQLDatabaseError then
  2719. ErrorCode := ESQLDatabaseError(E).ErrorCode
  2720. else
  2721. ErrorCode := 0;
  2722. Result := EUpdateError.Create(SOnUpdateError, E.Message, ErrorCode, PrevErrorCode, E);
  2723. end;
  2724. function TCustomSQLQuery.PSGetTableName: string;
  2725. begin
  2726. Result := FTableName;
  2727. end;
  2728. { TSQLScript }
  2729. procedure TSQLScript.ExecuteStatement(SQLStatement: TStrings;
  2730. var StopExecution: Boolean);
  2731. begin
  2732. fquery.SQL.assign(SQLStatement);
  2733. fquery.ExecSQL;
  2734. end;
  2735. procedure TSQLScript.ExecuteDirective(Directive, Argument: String;
  2736. var StopExecution: Boolean);
  2737. begin
  2738. if assigned (FOnDirective) then
  2739. FOnDirective (Self, Directive, Argument, StopExecution);
  2740. end;
  2741. procedure TSQLScript.ExecuteCommit(CommitRetaining: boolean=true);
  2742. begin
  2743. if FTransaction is TSQLTransaction then
  2744. if CommitRetaining then
  2745. TSQLTransaction(FTransaction).CommitRetaining
  2746. else
  2747. begin
  2748. TSQLTransaction(FTransaction).Commit;
  2749. TSQLTransaction(FTransaction).StartTransaction;
  2750. end
  2751. else
  2752. begin
  2753. FTransaction.Active := false;
  2754. FTransaction.Active := true;
  2755. end;
  2756. end;
  2757. procedure TSQLScript.SetDatabase(Value: TDatabase);
  2758. begin
  2759. FDatabase := Value;
  2760. end;
  2761. procedure TSQLScript.SetTransaction(Value: TDBTransaction);
  2762. begin
  2763. FTransaction := Value;
  2764. end;
  2765. procedure TSQLScript.CheckDatabase;
  2766. begin
  2767. If (FDatabase=Nil) then
  2768. DatabaseError(SErrNoDatabaseAvailable,Self)
  2769. end;
  2770. constructor TSQLScript.Create(AOwner: TComponent);
  2771. begin
  2772. inherited Create(AOwner);
  2773. FQuery := TCustomSQLQuery.Create(nil);
  2774. FQuery.ParamCheck := false; // Do not parse for parameters; breaks use of e.g. select bla into :bla in Firebird procedures
  2775. end;
  2776. destructor TSQLScript.Destroy;
  2777. begin
  2778. FQuery.Free;
  2779. inherited Destroy;
  2780. end;
  2781. procedure TSQLScript.Execute;
  2782. begin
  2783. FQuery.DataBase := FDatabase;
  2784. FQuery.Transaction := FTransaction;
  2785. inherited Execute;
  2786. end;
  2787. procedure TSQLScript.ExecuteScript;
  2788. begin
  2789. Execute;
  2790. end;
  2791. { Connection definitions }
  2792. Var
  2793. ConnDefs : TStringList;
  2794. Procedure CheckDefs;
  2795. begin
  2796. If (ConnDefs=Nil) then
  2797. begin
  2798. ConnDefs:=TStringList.Create;
  2799. ConnDefs.Sorted:=True;
  2800. ConnDefs.Duplicates:=dupError;
  2801. end;
  2802. end;
  2803. Procedure DoneDefs;
  2804. Var
  2805. I : Integer;
  2806. begin
  2807. If Assigned(ConnDefs) then
  2808. begin
  2809. For I:=ConnDefs.Count-1 downto 0 do
  2810. begin
  2811. ConnDefs.Objects[i].Free;
  2812. ConnDefs.Delete(I);
  2813. end;
  2814. FreeAndNil(ConnDefs);
  2815. end;
  2816. end;
  2817. Function GetConnectionDef(ConnectorName : String) : TConnectionDef;
  2818. Var
  2819. I : Integer;
  2820. begin
  2821. CheckDefs;
  2822. I:=ConnDefs.IndexOf(ConnectorName);
  2823. If (I<>-1) then
  2824. Result:=TConnectionDef(ConnDefs.Objects[i])
  2825. else
  2826. Result:=Nil;
  2827. end;
  2828. procedure RegisterConnection(Def: TConnectionDefClass);
  2829. Var
  2830. I : Integer;
  2831. begin
  2832. CheckDefs;
  2833. I:=ConnDefs.IndexOf(Def.TypeName);
  2834. If (I=-1) then
  2835. ConnDefs.AddObject(Def.TypeName,Def.Create)
  2836. else
  2837. begin
  2838. ConnDefs.Objects[I].Free;
  2839. ConnDefs.Objects[I]:=Def.Create;
  2840. end;
  2841. end;
  2842. procedure UnRegisterConnection(Def: TConnectionDefClass);
  2843. begin
  2844. UnRegisterConnection(Def.TypeName);
  2845. end;
  2846. procedure UnRegisterConnection(ConnectionName: String);
  2847. Var
  2848. I : Integer;
  2849. begin
  2850. if (ConnDefs<>Nil) then
  2851. begin
  2852. I:=ConnDefs.IndexOf(ConnectionName);
  2853. If (I<>-1) then
  2854. begin
  2855. ConnDefs.Objects[I].Free;
  2856. ConnDefs.Delete(I);
  2857. end;
  2858. end;
  2859. end;
  2860. procedure GetConnectionList(List: TSTrings);
  2861. begin
  2862. CheckDefs;
  2863. List.Text:=ConnDefs.Text;
  2864. end;
  2865. { TSQLConnector }
  2866. procedure TSQLConnector.SetConnectorType(const AValue: String);
  2867. begin
  2868. if FConnectorType<>AValue then
  2869. begin
  2870. CheckDisconnected;
  2871. If Assigned(FProxy) then
  2872. FreeProxy;
  2873. FConnectorType:=AValue;
  2874. CreateProxy;
  2875. end;
  2876. end;
  2877. procedure TSQLConnector.SetTransaction(Value: TSQLTransaction);
  2878. begin
  2879. inherited SetTransaction(Value);
  2880. If Assigned(FProxy) and (FProxy.Transaction<>Value) then
  2881. FProxy.FTransaction:=Value;
  2882. end;
  2883. procedure TSQLConnector.DoInternalConnect;
  2884. Var
  2885. D : TConnectionDef;
  2886. begin
  2887. inherited DoInternalConnect;
  2888. CheckProxy;
  2889. FProxy.CharSet:=Self.CharSet;
  2890. FProxy.DatabaseName:=Self.DatabaseName;
  2891. FProxy.HostName:=Self.HostName;
  2892. FProxy.LogEvents:=Self.LogEvents;
  2893. FProxy.Password:=Self.Password;
  2894. FProxy.Role:=Self.Role;
  2895. FProxy.UserName:=Self.UserName;
  2896. FProxy.FTransaction:=Self.Transaction;
  2897. FProxy.LogEvents:=Self.LogEvents;
  2898. FProxy.OnLog:=Self.OnLog;
  2899. FProxy.Options:=Self.Options;
  2900. D:=GetConnectionDef(ConnectorType);
  2901. D.ApplyParams(Params,FProxy);
  2902. FProxy.Connected:=True;
  2903. end;
  2904. procedure TSQLConnector.DoInternalDisconnect;
  2905. begin
  2906. FProxy.Connected:=False;
  2907. inherited DoInternalDisconnect;
  2908. end;
  2909. procedure TSQLConnector.CheckProxy;
  2910. begin
  2911. If (FProxy=Nil) then
  2912. CreateProxy;
  2913. end;
  2914. procedure TSQLConnector.CreateProxy;
  2915. Var
  2916. D : TConnectionDef;
  2917. begin
  2918. D:=GetConnectionDef(ConnectorType);
  2919. If (D=Nil) then
  2920. DatabaseErrorFmt(SErrUnknownConnectorType,[ConnectorType],Self);
  2921. FProxy:=D.ConnectionClass.Create(Self);
  2922. FFieldNameQuoteChars := FProxy.FieldNameQuoteChars;
  2923. FConnOptions := FProxy.ConnOptions;
  2924. end;
  2925. procedure TSQLConnector.FreeProxy;
  2926. begin
  2927. FProxy.Connected:=False;
  2928. FreeAndNil(FProxy);
  2929. end;
  2930. function TSQLConnector.StrToStatementType(s: string): TStatementType;
  2931. begin
  2932. CheckProxy;
  2933. Result:=FProxy.StrToStatementType(s);
  2934. end;
  2935. function TSQLConnector.GetAsSQLText(Field: TField): string;
  2936. begin
  2937. CheckProxy;
  2938. Result:=FProxy.GetAsSQLText(Field);
  2939. end;
  2940. function TSQLConnector.GetAsSQLText(Param: TParam): string;
  2941. begin
  2942. CheckProxy;
  2943. Result:=FProxy.GetAsSQLText(Param);
  2944. end;
  2945. function TSQLConnector.GetHandle: pointer;
  2946. begin
  2947. CheckProxy;
  2948. Result:=FProxy.GetHandle;
  2949. end;
  2950. function TSQLConnector.AllocateCursorHandle: TSQLCursor;
  2951. begin
  2952. CheckProxy;
  2953. Result:=FProxy.AllocateCursorHandle;
  2954. end;
  2955. procedure TSQLConnector.DeAllocateCursorHandle(var cursor: TSQLCursor);
  2956. begin
  2957. CheckProxy;
  2958. FProxy.DeAllocateCursorHandle(cursor);
  2959. end;
  2960. function TSQLConnector.AllocateTransactionHandle: TSQLHandle;
  2961. begin
  2962. CheckProxy;
  2963. Result:=FProxy.AllocateTransactionHandle;
  2964. end;
  2965. procedure TSQLConnector.PrepareStatement(cursor: TSQLCursor;
  2966. ATransaction: TSQLTransaction; buf: string; AParams: TParams);
  2967. begin
  2968. CheckProxy;
  2969. FProxy.PrepareStatement(cursor, ATransaction, buf, AParams);
  2970. end;
  2971. procedure TSQLConnector.Execute(cursor: TSQLCursor;
  2972. atransaction: tSQLtransaction; AParams: TParams);
  2973. begin
  2974. CheckProxy;
  2975. FProxy.Execute(cursor, atransaction, AParams);
  2976. end;
  2977. function TSQLConnector.Fetch(cursor: TSQLCursor): boolean;
  2978. begin
  2979. CheckProxy;
  2980. Result:=FProxy.Fetch(cursor);
  2981. end;
  2982. procedure TSQLConnector.AddFieldDefs(cursor: TSQLCursor; FieldDefs: TfieldDefs
  2983. );
  2984. begin
  2985. CheckProxy;
  2986. FProxy.AddFieldDefs(cursor, FieldDefs);
  2987. end;
  2988. procedure TSQLConnector.UnPrepareStatement(cursor: TSQLCursor);
  2989. begin
  2990. CheckProxy;
  2991. FProxy.UnPrepareStatement(cursor);
  2992. end;
  2993. procedure TSQLConnector.FreeFldBuffers(cursor: TSQLCursor);
  2994. begin
  2995. CheckProxy;
  2996. FProxy.FreeFldBuffers(cursor);
  2997. end;
  2998. function TSQLConnector.LoadField(cursor: TSQLCursor; FieldDef: TfieldDef;
  2999. buffer: pointer; out CreateBlob: boolean): boolean;
  3000. begin
  3001. CheckProxy;
  3002. Result:=FProxy.LoadField(cursor, FieldDef, buffer, CreateBlob);
  3003. end;
  3004. procedure TSQLConnector.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  3005. ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction: TSQLTransaction);
  3006. begin
  3007. CheckProxy;
  3008. FProxy.LoadBlobIntoBuffer(FieldDef, ABlobBuf, cursor, ATransaction);
  3009. end;
  3010. function TSQLConnector.RowsAffected(cursor: TSQLCursor): TRowsCount;
  3011. begin
  3012. CheckProxy;
  3013. Result := FProxy.RowsAffected(cursor);
  3014. end;
  3015. function TSQLConnector.GetTransactionHandle(trans: TSQLHandle): pointer;
  3016. begin
  3017. CheckProxy;
  3018. Result:=FProxy.GetTransactionHandle(trans);
  3019. end;
  3020. function TSQLConnector.Commit(trans: TSQLHandle): boolean;
  3021. begin
  3022. CheckProxy;
  3023. Result:=FProxy.Commit(trans);
  3024. end;
  3025. function TSQLConnector.RollBack(trans: TSQLHandle): boolean;
  3026. begin
  3027. CheckProxy;
  3028. Result:=FProxy.RollBack(trans);
  3029. end;
  3030. function TSQLConnector.StartDBTransaction(trans: TSQLHandle; aParams: string): boolean;
  3031. begin
  3032. CheckProxy;
  3033. Result:=FProxy.StartDBTransaction(trans, aParams);
  3034. end;
  3035. procedure TSQLConnector.CommitRetaining(trans: TSQLHandle);
  3036. begin
  3037. CheckProxy;
  3038. FProxy.CommitRetaining(trans);
  3039. end;
  3040. procedure TSQLConnector.RollBackRetaining(trans: TSQLHandle);
  3041. begin
  3042. CheckProxy;
  3043. FProxy.RollBackRetaining(trans);
  3044. end;
  3045. procedure TSQLConnector.UpdateIndexDefs(IndexDefs: TIndexDefs;
  3046. TableName: string);
  3047. begin
  3048. CheckProxy;
  3049. FProxy.UpdateIndexDefs(IndexDefs, TableName);
  3050. end;
  3051. function TSQLConnector.GetSchemaInfoSQL(SchemaType: TSchemaType;
  3052. SchemaObjectName, SchemaPattern: string): string;
  3053. begin
  3054. CheckProxy;
  3055. Result:=FProxy.GetSchemaInfoSQL(SchemaType, SchemaObjectName, SchemaPattern);
  3056. end;
  3057. { TConnectionDef }
  3058. class function TConnectionDef.TypeName: String;
  3059. begin
  3060. Result:='';
  3061. end;
  3062. class function TConnectionDef.ConnectionClass: TSQLConnectionClass;
  3063. begin
  3064. Result:=Nil;
  3065. end;
  3066. class function TConnectionDef.Description: String;
  3067. begin
  3068. Result:='';
  3069. end;
  3070. class function TConnectionDef.DefaultLibraryName: String;
  3071. begin
  3072. Result:='';
  3073. end;
  3074. class function TConnectionDef.LoadFunction: TLibraryLoadFunction;
  3075. begin
  3076. Result:=Nil;
  3077. end;
  3078. class function TConnectionDef.UnLoadFunction: TLibraryUnLoadFunction;
  3079. begin
  3080. Result:=Nil;
  3081. end;
  3082. class function TConnectionDef.LoadedLibraryName: string;
  3083. begin
  3084. Result:='';
  3085. end;
  3086. procedure TConnectionDef.ApplyParams(Params: TStrings;
  3087. AConnection: TSQLConnection);
  3088. begin
  3089. AConnection.Params.Assign(Params);
  3090. end;
  3091. { TServerIndexDefs }
  3092. constructor TServerIndexDefs.create(ADataset: TDataset);
  3093. begin
  3094. if not (ADataset is TCustomSQLQuery) then
  3095. DatabaseErrorFmt(SErrNotASQLQuery,[ADataset.Name]);
  3096. inherited create(ADataset);
  3097. end;
  3098. procedure TServerIndexDefs.Update;
  3099. begin
  3100. if (not updated) and assigned(Dataset) then
  3101. begin
  3102. TCustomSQLQuery(Dataset).UpdateServerIndexDefs;
  3103. updated := True;
  3104. end;
  3105. end;
  3106. { TSqlObjectIdenfier }
  3107. constructor TSqlObjectIdenfier.Create(ACollection: TSqlObjectIdentifierList;
  3108. const AObjectName: String; Const ASchemaName: String = '');
  3109. begin
  3110. inherited Create(ACollection);
  3111. FSchemaName:=ASchemaName;
  3112. FObjectName:=AObjectName;
  3113. end;
  3114. { TSqlObjectIdentifierList }
  3115. function TSqlObjectIdentifierList.GetIdentifier(Index: integer): TSqlObjectIdenfier;
  3116. begin
  3117. Result := Items[Index] as TSqlObjectIdenfier;
  3118. end;
  3119. procedure TSqlObjectIdentifierList.SetIdentifier(Index: integer; AValue: TSqlObjectIdenfier);
  3120. begin
  3121. Items[Index] := AValue;
  3122. end;
  3123. function TSqlObjectIdentifierList.AddIdentifier: TSqlObjectIdenfier;
  3124. begin
  3125. Result:=Add as TSqlObjectIdenfier;
  3126. end;
  3127. function TSqlObjectIdentifierList.AddIdentifier(Const AObjectName: String;
  3128. Const ASchemaName: String = ''): TSqlObjectIdenfier;
  3129. begin
  3130. Result:=AddIdentifier();
  3131. Result.SchemaName:=ASchemaName;
  3132. Result.ObjectName:=AObjectName;
  3133. end;
  3134. Initialization
  3135. Finalization
  3136. DoneDefs;
  3137. end.