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