sqldb.pp 78 KB

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