sqldb.pp 105 KB

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