Advertisement
Guest User

Untitled

a guest
Jul 26th, 2017
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.10 KB | None | 0 0
  1. unit DBDriverManager;
  2.  
  3. interface
  4.  
  5. uses
  6. ZDbcIntfs, Types, Classes, DB, SysUtils, ZClasses, ZCollections, ZCompatibility, ZTokenizer, ZSelectSchema,
  7. ZGenericSqlAnalyser, ZDbcLogging, ZVariant, ZPlainDriver, ZURL, ThreadHelper;
  8.  
  9. type
  10. TSafeDriverManager = class(TInterfacedObject, IZDriverManager)
  11. private
  12. FLock: TLock;
  13. FDrivers: IZCollection;
  14. FLoginTimeout: Integer;
  15. FLoggingListeners: IZCollection;
  16. FHasLoggingListener: Boolean;
  17. procedure LogEvent(const Event: TZLoggingEvent);
  18. public
  19. constructor Create;
  20. destructor Destroy; override;
  21. function GetConnection(const Url: string): IZConnection;
  22. function GetConnectionWithParams(const Url: string; Info: TStrings): IZConnection;
  23. function GetConnectionWithLogin(const Url: string; const User: string; const Password: string): IZConnection;
  24. function GetDriver(const Url: string): IZDriver;
  25. procedure RegisterDriver(Driver: IZDriver);
  26. procedure DeregisterDriver(Driver: IZDriver);
  27. function GetDrivers: IZCollection;
  28. function GetClientVersion(const Url: string): Integer;
  29. function GetLoginTimeout: Integer;
  30. procedure SetLoginTimeout(Value: Integer);
  31. procedure AddLoggingListener(Listener: IZLoggingListener);
  32. procedure RemoveLoggingListener(Listener: IZLoggingListener);
  33. function HasLoggingListener: Boolean;
  34. procedure LogMessage(Category: TZLoggingCategory; const Protocol: RawByteString; const Msg: RawByteString); overload;
  35. procedure LogMessage(const Category: TZLoggingCategory; const Sender: IZLoggingObject); overload;
  36. procedure LogError(Category: TZLoggingCategory; const Protocol: RawByteString; const Msg: RawByteString; ErrorCode: Integer; const Error: RawByteString);
  37. function ConstructURL(const Protocol, HostName, Database, UserName, Password: string; const Port: Integer; const Properties: TStrings = nil; const LibLocation: string = ''): string;
  38. procedure ResolveDatabaseUrl(const Url: string; out HostName: string; out Port: Integer; out Database: string; out UserName: string; out Password: string; ResultInfo: TStrings = nil); overload;
  39. procedure ResolveDatabaseUrl(const Url: string; out Database: string); overload;
  40. end;
  41.  
  42. implementation
  43.  
  44. uses
  45. ZMessages;
  46.  
  47. constructor TSafeDriverManager.Create;
  48. begin
  49. FLock.Init;
  50. FDrivers := TZCollection.Create;
  51. FLoginTimeout := 0;
  52. FLoggingListeners := TZCollection.Create;
  53. FHasLoggingListener := False;
  54. end;
  55.  
  56. {**
  57. Destroys this object and cleanups the memory.
  58. }
  59. destructor TSafeDriverManager.Destroy;
  60. begin
  61. FDrivers := nil;
  62. FLoggingListeners := nil;
  63. FLock.Done;
  64. inherited Destroy;
  65. end;
  66.  
  67. {**
  68. Gets a collection of registered drivers.
  69. @return an unmodifiable collection with registered drivers.
  70. }
  71. function TSafeDriverManager.GetDrivers: IZCollection;
  72. begin
  73. Result := TZUnmodifiableCollection.Create(FDrivers);
  74. end;
  75.  
  76. {**
  77. Gets a login timeout value.
  78. @return a login timeout.
  79. }
  80. function TSafeDriverManager.GetLoginTimeout: Integer;
  81. begin
  82. Result := FLoginTimeout;
  83. end;
  84.  
  85. {**
  86. Sets a new login timeout value.
  87. @param Seconds a new login timeout in seconds.
  88. }
  89. procedure TSafeDriverManager.SetLoginTimeout(Value: Integer);
  90. begin
  91. FLoginTimeout := Value;
  92. end;
  93.  
  94. {**
  95. Registers a driver for specific database.
  96. @param Driver a driver to be registered.
  97. }
  98. procedure TSafeDriverManager.RegisterDriver(Driver: IZDriver);
  99. begin
  100. FLock.Lock;
  101. try
  102. if not FDrivers.contains(Driver) then
  103. FDrivers.Add(Driver);
  104. finally
  105. FLock.Unlock;
  106. end;
  107. end;
  108.  
  109. {**
  110. Unregisters a driver for specific database.
  111. @param Driver a driver to be unregistered.
  112. }
  113. procedure TSafeDriverManager.DeregisterDriver(Driver: IZDriver);
  114. begin
  115. FLock.Lock;
  116. try
  117. FDrivers.Remove(Driver);
  118. finally
  119. FLock.Unlock;
  120. end;
  121. end;
  122.  
  123. {**
  124. Gets a driver which accepts the specified url.
  125. @param Url a database connection url.
  126. @return a found driver or <code>null</code> otherwise.
  127. }
  128. function TSafeDriverManager.GetDriver(const Url: string): IZDriver;
  129. var
  130. I: Integer;
  131. Current: IZDriver;
  132. begin
  133. FLock.Lock;
  134. try
  135. Result := nil;
  136. for I := 0 to FDrivers.Count - 1 do
  137. begin
  138. Current := FDrivers[I] as IZDriver;
  139. if Current.AcceptsURL(Url) then
  140. begin
  141. Result := Current;
  142. Break;
  143. end;
  144. end;
  145. finally
  146. FLock.Unlock;
  147. end;
  148. end;
  149.  
  150. {**
  151. Locates a required driver and opens a connection to the specified database.
  152. @param Url a database connection Url.
  153. @param Info an extra connection parameters.
  154. @return an opened connection.
  155. }
  156. function TSafeDriverManager.GetConnectionWithParams(const Url: string; Info: TStrings): IZConnection;
  157. var
  158. Driver: IZDriver;
  159. begin
  160. Driver := GetDriver(Url);
  161. if Driver = nil then
  162. raise EZSQLException.Create(SDriverWasNotFound);
  163. Result := Driver.Connect(Url, Info);
  164. end;
  165.  
  166. {**
  167. Locates a required driver and returns the client library version number.
  168. @param Url a database connection Url.
  169. @return client library version number.
  170. }
  171. function TSafeDriverManager.GetClientVersion(const Url: string): Integer;
  172. var
  173. Driver: IZDriver;
  174. begin
  175. Driver := GetDriver(Url);
  176. if Driver = nil then
  177. raise EZSQLException.Create(SDriverWasNotFound);
  178. Result := Driver.GetClientVersion(Url);
  179. end;
  180.  
  181. {**
  182. Locates a required driver and opens a connection to the specified database.
  183. @param Url a database connection Url.
  184. @param User a user's name.
  185. @param Password a user's password.
  186. @return an opened connection.
  187. }
  188. function TSafeDriverManager.GetConnectionWithLogin(const Url: string; const User: string; const Password: string): IZConnection;
  189. var
  190. Info: TStrings;
  191. begin
  192. Info := TStringList.Create;
  193. try
  194. Info.Add('username=' + User);
  195. Info.Add('password=' + Password);
  196. Result := GetConnectionWithParams(Url, Info);
  197. finally
  198. Info.Free;
  199. end;
  200. end;
  201.  
  202. {**
  203. Locates a required driver and opens a connection to the specified database.
  204. @param Url a database connection Url.
  205. @return an opened connection.
  206. }
  207. function TSafeDriverManager.GetConnection(const Url: string): IZConnection;
  208. begin
  209. Result := GetConnectionWithParams(Url, nil);
  210. end;
  211.  
  212. {**
  213. Adds a logging listener to log SQL events.
  214. @param Listener a logging interface to be added.
  215. }
  216. procedure TSafeDriverManager.AddLoggingListener(Listener: IZLoggingListener);
  217. begin
  218. FLock.Lock;
  219. try
  220. FLoggingListeners.Add(Listener);
  221. FHasLoggingListener := True;
  222. finally
  223. FLock.Unlock;
  224. end;
  225. end;
  226.  
  227. {**
  228. Removes a logging listener from the list.
  229. @param Listener a logging interface to be removed.
  230. }
  231. procedure TSafeDriverManager.RemoveLoggingListener(Listener: IZLoggingListener);
  232. begin
  233. FLock.Lock;
  234. try
  235. FLoggingListeners.Remove(Listener);
  236. FHasLoggingListener := (FLoggingListeners.Count > 0);
  237. finally
  238. FLock.Unlock;
  239. end;
  240. end;
  241.  
  242. function TSafeDriverManager.HasLoggingListener: Boolean;
  243. begin
  244. result := FHasLoggingListener;
  245. end;
  246.  
  247. {**
  248. Logs a message about event with error result code.
  249. @param Category a category of the message.
  250. @param Protocol a name of the protocol.
  251. @param Msg a description message.
  252. @param ErrorCode an error code.
  253. @param Error an error message.
  254. }
  255. procedure TSafeDriverManager.LogError(Category: TZLoggingCategory; const Protocol: RawByteString; const Msg: RawByteString; ErrorCode: Integer; const Error: RawByteString);
  256. var
  257. Event: TZLoggingEvent;
  258. begin
  259. if not FHasLoggingListener then
  260. Exit;
  261. Event := TZLoggingEvent.Create(Category, Protocol, Msg, ErrorCode, Error);
  262. try
  263. LogEvent(Event);
  264. finally
  265. Event.Destroy;
  266. end;
  267. end;
  268.  
  269. {**
  270. Logs a message about event with error result code.
  271. @param Category a category of the message.
  272. @param Protocol a name of the protocol.
  273. @param Msg a description message.
  274. @param ErrorCode an error code.
  275. @param Error an error message.
  276. }
  277. procedure TSafeDriverManager.LogEvent(const Event: TZLoggingEvent);
  278. var
  279. I: Integer;
  280. Listener: IZLoggingListener;
  281. begin
  282. if not FHasLoggingListener then
  283. Exit;
  284.  
  285. FLock.Lock;
  286. try
  287. for I := 0 to FLoggingListeners.Count - 1 do
  288. begin
  289. Listener := FLoggingListeners[I] as IZLoggingListener;
  290. try
  291. Listener.LogEvent(Event);
  292. except
  293. end;
  294. end;
  295. finally
  296. FLock.Unlock;
  297. end;
  298. end;
  299.  
  300. {**
  301. Logs a message about event with normal result code.
  302. @param Category a category of the message.
  303. @param Protocol a name of the protocol.
  304. @param Msg a description message.
  305. }
  306. procedure TSafeDriverManager.LogMessage(Category: TZLoggingCategory; const Protocol: RawByteString; const Msg: RawByteString);
  307. begin
  308. if not FHasLoggingListener then
  309. Exit;
  310. LogError(Category, Protocol, Msg, 0, '');
  311. end;
  312.  
  313. procedure TSafeDriverManager.LogMessage(const Category: TZLoggingCategory; const Sender: IZLoggingObject);
  314. var
  315. Event: TZLoggingEvent;
  316. begin
  317. if not FHasLoggingListener then
  318. Exit;
  319. Event := Sender.CreateLogEvent(Category);
  320. if Assigned(Event) then
  321. begin
  322. LogEvent(Event);
  323. Event.Free;
  324. end;
  325. end;
  326.  
  327. {**
  328. Constructs a valid URL
  329. @param Protocol the Driver-protocol (must be assigned).
  330. @param HostName the hostname (could be empty).
  331. @param Database the connection-database (could be empty).
  332. @param UserName the username (could be empty).
  333. @param Password the password(could be empty).
  334. @param Port the Server-Port (could be 0).
  335. @param Properties the Database-Properties (could be empty).
  336. }
  337. function TSafeDriverManager.ConstructURL(const Protocol, HostName, Database, UserName, Password: string; const Port: Integer; const Properties: TStrings = nil; const LibLocation: string = ''): string;
  338. var
  339. BaseURL: TZURL;
  340. begin
  341. BaseURL := TZURL.Create;
  342. try
  343. BaseURL.Protocol := Protocol;
  344. BaseURL.HostName := HostName;
  345. BaseURL.Database := Database;
  346. BaseURL.UserName := UserName;
  347. BaseURL.Password := Password;
  348. BaseURL.Port := Port;
  349. if Assigned(Properties) then
  350. BaseURL.Properties.Text := Properties.Text;
  351. BaseURL.LibLocation := LibLocation;
  352. Result := BaseURL.URL;
  353. finally
  354. BaseURL.Free;
  355. end;
  356. end;
  357.  
  358. {**
  359. Resolves a database URL and fills the database connection parameters.
  360. @param Url an initial database URL.
  361. @param HostName a name of the database host.
  362. @param Port a port number.
  363. @param Database a database name.
  364. @param UserName a name of the database user.
  365. @param Password a user's password.
  366. @param ResutlInfo a result info parameters.
  367. }
  368. procedure TSafeDriverManager.ResolveDatabaseUrl(const Url: string; out HostName: string; out Port: Integer; out Database: string; out UserName: string; out Password: string; ResultInfo: TStrings = nil);
  369. var
  370. BaseURL: TZURL;
  371. begin
  372. BaseURL := TZURL.Create;
  373. try
  374. BaseURL.URL := Url;
  375. HostName := BaseURL.HostName;
  376. Port := BaseURL.Port;
  377. Database := BaseURL.Database;
  378. UserName := BaseURL.UserName;
  379. Password := BaseURL.Password;
  380. if Assigned(ResultInfo) then
  381. ResultInfo.Text := BaseURL.Properties.Text;
  382. finally
  383. BaseURL.Free;
  384. end;
  385. end;
  386.  
  387. {**
  388. Resolves a database URL and fills the database parameter for MetaData.
  389. @param Url an initial database URL.
  390. @param Database a database name.
  391. }
  392. procedure TSafeDriverManager.ResolveDatabaseUrl(const Url: string; out Database: string);
  393. var
  394. BaseURL: TZURL;
  395. begin
  396. BaseURL := TZURL.Create;
  397. try
  398. BaseURL.URL := Url;
  399. Database := BaseURL.Database;
  400. finally
  401. BaseURL.Free;
  402. end;
  403. end;
  404.  
  405. initialization
  406. DriverManager := TSafeDriverManager.Create;
  407.  
  408. finalization
  409. DriverManager := nil;
  410.  
  411. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement