From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,2843c5eea3415584 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: APQ Date: Fri, 17 Dec 2004 14:54:56 +0100 Message-ID: <43jrvek9m28o.r8ywhg3uqgud.dlg@40tude.net> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Trace: individual.net FwqTRhWe2MXVo6lce/iIFQmk8InyUqhMeW5UgcT++JPPrgBpA= User-Agent: 40tude_Dialog/2.0.12.1 Xref: g2news1.google.com comp.lang.ada:7034 Date: 2004-12-17T14:54:56+01:00 List-Id: On Thu, 16 Dec 2004 10:31:49 +1100, Brian May wrote: > 1. Decide on or write a "smart pointer" library. ie. a library that > manages pointers based on a reference count. Obviously the license > must be compatible with the license of APQ. I have one in http://www.dmitry-kazakov.de/ada/components.htm > 3. Create new Database_Type. This type should not be > tagged. Applications will use this instead of the > Root_Connection_Type. It has the following data: > > * Smart pointer to Root_Connection_Type'Class. This is dynamically > allocated when the connection is created. It should *be* a smart pointer. Generally with components it goes as follows: package APQ.Handles is type Database_Type is private; -- Here all visible methods function Connect (...) return Data_Base_Type; ... private -- Wrapper type for Root_Connection_Type'Class, to implement -- mix-in. Necessary, only because Root_Connection_Type is not -- a descendant of Object.Entity. Ptr points to the connection -- object allocated by Connect. Data_Base_Object itself is also -- allocated by Connect. It is destroyed as soon as the -- last handle to it disappears. -- type Root_Connection_Ptr is access Root_Connection_Type'Class; type Data_Base_Object is new Object.Entity with record Ptr : Root_Connection_Ptr; end record; type Data_Base_Ptr is access Data_Base_Object'Class; -- -- Finalize deletes Ptr. -- procedure Finalize (Object : Data_Base_Object); -- -- Handles, for internal use, they do not have any -- interesting methods. -- package Connection_Handles is new Object.Handle (Data_Base_Object, Data_Base_Ptr); -- -- Database_Type is a handle -- type Database_Type is new Connection_Handles.Handle; end APQ.Handles; > It has the following methods: > > * Connect method takes a string, which is the connection URL. Note: > Two ways of implementing: > > 1. connect is hard-coded to support every possible database, and > parses the URL itself. > > 2. each database is registered in a global list, connect > determines the most appropriate database based on prefix in URL > and calls appropriate connect method with URL. > > The second method is more complicated but more flexible. In any > case, changing this should not require changing the user API. > > * All methods associated with Root_Connection_Type. This does *not* > include options to set options specific to the database, like user > name or password. These call the appropriate routine in the > Root_Connection_Type'Class. Status information should perhaps be > cached, so it remains constant even after queries (might be more > appropriate way to handle errors). > > * New_Query takes a *Database_Type* parameter, not a > Root_Connection_Type parameter. This function constraints a query > and saves a smart pointer to the Root_Connection_Type contained > within the Database_Type variable. You could leave it as is and add a handle to a query, which will be created from a handle to data base. It is a standard pattern: user interface has only handles: Handle to connection ---> Connection_Object --> Connection_Type Handle to query ---> Query_Object --------> Query_Type Handle to connection Query_Object has a handle to its connection as a component. This ensures that the Connection_Object will never be finalized before it. The original Conncetion_Type and Query_Type may be left intact. They will be allocated by handle constructors and destroyed automatically. > * Debatable: Function that returns smart pointer to > Root_Connection_Type'Class. This might be required to access > database specific functions. Ideally it shouldn't be required. > > 4. Modify Root_Query_Type class: > > New_Query is the only function that takes a *Database_Type* > parameter. > > The functions that use to require Root_Connection_Type now use the > smart pointer that was saved instead. > > Why not make the procedures abstract instead of having them raise > an Is_Abstract? This way the checks can be done at compile time. > > Execute already returns exception if not connected. > > Add methods for obtaining and clearing status information. This > should be cached so if you execute two separate queries (in two > separate variables) on the same database, you will get two status > messages saved. > > I hope this helps explain what I said earlier... I believe this solves > a number of concerns with the existing system in one go. > > The major difference is that I have created a new Database_Type class, > which allows the Connection_Type to be shared in a safe manner between > the user Database_Type and the user Query_Type classes. > > This would involve making incompatible changes to Root_Query_Type. It > might be possible to avoid this, not sure if it would be worth the > effort. No, if you would make a handle for Root_Query_Type. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de