* Re: APQ
@ 2004-12-16 4:37 Christoph Karl Walter Grein
0 siblings, 0 replies; 28+ messages in thread
From: Christoph Karl Walter Grein @ 2004-12-16 4:37 UTC (permalink / raw)
To: comp.lang.ada
> 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.
You could use my version of this library:
http://home.t-online.de/home/christ-usch.grein/Ada/Safe_Pointers.html
It was published in Ada User Journal, Volume 20, Number 2 (Juli 1999)
and as a reprint in Ada Letters, Volume XIX, Number 4, December 1999.
It's in a very liberal license.
__________________________________________________________
Mit WEB.DE FreePhone mit hoechster Qualitaet ab 0 Ct./Min.
weltweit telefonieren! http://freephone.web.de/?mc=021201
^ permalink raw reply [flat|nested] 28+ messages in thread
* APQ @ 2004-12-15 23:31 Brian May 2004-12-16 11:34 ` APQ Warren W. Gay VE3WWG 2004-12-17 13:54 ` APQ Dmitry A. Kazakov 0 siblings, 2 replies; 28+ messages in thread From: Brian May @ 2004-12-15 23:31 UTC (permalink / raw) Hello, Here are my suggested changes to APQ (not actually done or tested). 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. 2. No change to Connection_Type or Root_Connection_Type. 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 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. * 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. Comments? -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-15 23:31 APQ Brian May @ 2004-12-16 11:34 ` Warren W. Gay VE3WWG 2004-12-16 23:58 ` APQ Randy Brukardt 2004-12-17 13:54 ` APQ Dmitry A. Kazakov 1 sibling, 1 reply; 28+ messages in thread From: Warren W. Gay VE3WWG @ 2004-12-16 11:34 UTC (permalink / raw) Brian May wrote: > Hello, > > Here are my suggested changes to APQ (not actually done or tested). I'll just respond briefly here, since I am on my way to work.. > 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. > > 2. No change to Connection_Type or Root_Connection_Type. > > 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 has the following methods: > > * Connect method takes a string, which is the connection URL. Note: > Two ways of implementing: Ok, this makes sense because you don't know the type of Connection_Type apriori. I generally favour Booch components myself, which includes a smart pointer. ... > 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. Answer: I wanted to put some code at the top level so that I wouldn't have to repeat it for every database. For some reason the compiler wouldn't let me do it (perhaps I was missing something). I would be happy to have this done, but I was unable to make it so in practice. Maybe someone else can figure it out. > 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. You have to be real careful here, because database products like Sybase use callbacks and things can change. In fact, Sybase was a monster to tame with its oodles of states and callbacks. > I hope this helps explain what I said earlier... I believe this solves > a number of concerns with the existing system in one go. I'll try to respond more fully later on, but this seems to make sense. -- Warren W. Gay VE3WWG http://home.cogeco.ca/~ve3wwg ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-16 11:34 ` APQ Warren W. Gay VE3WWG @ 2004-12-16 23:58 ` Randy Brukardt 2004-12-17 3:45 ` APQ Brian May 0 siblings, 1 reply; 28+ messages in thread From: Randy Brukardt @ 2004-12-16 23:58 UTC (permalink / raw) "Warren W. Gay VE3WWG" <ve3wwg@NoSpam.cogeco.ca> wrote in message news:Onewd.204$Wt5.95202@read2.cgocable.net... ... > > Why not make the procedures abstract instead of having them raise > > an Is_Abstract? This way the checks can be done at compile time. > > Answer: I wanted to put some code at the top level so that I > wouldn't have to repeat it for every database. For some reason > the compiler wouldn't let me do it (perhaps I was missing > something). I would be happy to have this done, but I was > unable to make it so in practice. Maybe someone else can > figure it out. I haven't looked at the code in question, but it certainly is possible to have concrete operations and components on an abstract type (the type has be abstract - if it is tagged - to have abstract subprograms). We do it all the time in Claw and its related programs. That's the big difference between an abstract type and an Ada 2005 interface (which can't have any data or concrete subprograms). Randy. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-16 23:58 ` APQ Randy Brukardt @ 2004-12-17 3:45 ` Brian May 2004-12-17 4:03 ` APQ Warren W. Gay VE3WWG ` (2 more replies) 0 siblings, 3 replies; 28+ messages in thread From: Brian May @ 2004-12-17 3:45 UTC (permalink / raw) >>>>> "Randy" == Randy Brukardt <randy@rrsoftware.com> writes: Randy> I haven't looked at the code in question, but it certainly Randy> is possible to have concrete operations and components on Randy> an abstract type (the type has be abstract - if it is Randy> tagged - to have abstract subprograms). We do it all the Randy> time in Claw and its related programs. That's the big Randy> difference between an abstract type and an Ada 2005 Randy> interface (which can't have any data or concrete Randy> subprograms). I tried to get it working, but couldn't: ... type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with private; ... procedure Connect(C : in out Root_Connection_Type) is abstract; procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class) is abstract; ... gcc-3.4 -c -gnata -gnatf -gnato -gnatwp -O0 comp_mysql.adb apq.ads:126:14: abstract subprogram not allowed for type "Root_Connection_Type" apq.ads:127:14: abstract subprogram not allowed for type "Root_Connection_Type" apq.ads:584:09: nonabstract type has abstract subprogram "Connect" gnatmake: "comp_mysql.adb" compilation error make: *** [mysql1] Error 4 ... What did I do wrong? How do I create a abstract type that is derived from Ada.Finalization.Limited_Controlled? I thought I made it quite clear that Root_Connection_Type is abstract. Should I try the same thing with GNAT? -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 3:45 ` APQ Brian May @ 2004-12-17 4:03 ` Warren W. Gay VE3WWG 2004-12-17 4:38 ` APQ Brian May 2004-12-17 8:59 ` APQ Stephen Leake 2004-12-17 14:12 ` APQ Dmitry A. Kazakov 2 siblings, 1 reply; 28+ messages in thread From: Warren W. Gay VE3WWG @ 2004-12-17 4:03 UTC (permalink / raw) Brian May wrote: >>>>>>"Randy" == Randy Brukardt <randy@rrsoftware.com> writes: > Randy> I haven't looked at the code in question, but it certainly > Randy> is possible to have concrete operations and components on > Randy> an abstract type (the type has be abstract - if it is > Randy> tagged - to have abstract subprograms). We do it all the > Randy> time in Claw and its related programs. That's the big > Randy> difference between an abstract type and an Ada 2005 > Randy> interface (which can't have any data or concrete > Randy> subprograms). > > I tried to get it working, but couldn't: > ... > type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with private; > ... > procedure Connect(C : in out Root_Connection_Type) is abstract; > procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class) is abstract; > ... > gcc-3.4 -c -gnata -gnatf -gnato -gnatwp -O0 comp_mysql.adb > apq.ads:126:14: abstract subprogram not allowed for type "Root_Connection_Type" > apq.ads:127:14: abstract subprogram not allowed for type "Root_Connection_Type" > apq.ads:584:09: nonabstract type has abstract subprogram "Connect" > gnatmake: "comp_mysql.adb" compilation error > make: *** [mysql1] Error 4 > > What did I do wrong? How do I create a abstract type that is derived > from Ada.Finalization.Limited_Controlled? The error looks familiar, though I don't understand the reason for the "limitation" that the compiler is imposing. Warren. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 4:03 ` APQ Warren W. Gay VE3WWG @ 2004-12-17 4:38 ` Brian May 2004-12-17 9:06 ` APQ Egil H. H�vik 0 siblings, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-17 4:38 UTC (permalink / raw) >>>>> "Warren" == Warren W Gay VE3WWG <ve3wwg@NoSpam.cogeco.ca> writes: Warren> The error looks familiar, though I don't understand the reason Warren> for the "limitation" that the compiler is imposing. It would make perfect sense if I hadn't declared the type to be abstract. If a type has any abstract methods, then the type must be abstract too. This in turn prohibits creating any objects based on this type. Child types do not need to be defined abstract if the define all the abstract methods. I believe this is just what we required for this situation. However, in this case the type is abstract (or so I believe), hence the error will not occur. Obviously, I am wrong, because the error is occurring ;-). -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 4:38 ` APQ Brian May @ 2004-12-17 9:06 ` Egil H. H�vik 2004-12-17 11:42 ` APQ Brian May 0 siblings, 1 reply; 28+ messages in thread From: Egil H. H�vik @ 2004-12-17 9:06 UTC (permalink / raw) "Brian May" <bam@snoopy.apana.org.au> wrote in message news:sa41xdpsfnt.fsf@snoopy.apana.org.au... > >>>>> "Warren" == Warren W Gay VE3WWG <ve3wwg@NoSpam.cogeco.ca> writes: > > Warren> The error looks familiar, though I don't understand the reason > Warren> for the "limitation" that the compiler is imposing. > > It would make perfect sense if I hadn't declared the type to be > abstract. If a type has any abstract methods, then the type must be > abstract too. This in turn prohibits creating any objects based on > this type. Child types do not need to be defined abstract if the > define all the abstract methods. I believe this is just what we > required for this situation. > > However, in this case the type is abstract (or so I believe), hence > the error will not occur. > My guess is that your full declaration of Root_Connection_Type in the private part is not abstract: ... type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with private; ... private type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with null record; -- full declaration. This must also be abstract ... ~egilhh ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 9:06 ` APQ Egil H. H�vik @ 2004-12-17 11:42 ` Brian May 2004-12-17 22:55 ` APQ Brian May 0 siblings, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-17 11:42 UTC (permalink / raw) >>>>> "Egil" == Egil H H�vik <egil.harald.hoevik@REMOVEkongsberg.com> writes: Egil> My guess is that your full declaration of Root_Connection_Type in the Egil> private part Egil> is not abstract: Good point. I meant to change it in both places, but I think I ended up changing it in only one place... Thanks for your assistance. Will try it out tomorrow. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 11:42 ` APQ Brian May @ 2004-12-17 22:55 ` Brian May 2004-12-18 15:52 ` APQ Warren W. Gay VE3WWG 0 siblings, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-17 22:55 UTC (permalink / raw) [-- Attachment #1: Type: text/plain, Size: 891 bytes --] >>>>> "Brian" == Brian May <bam@snoopy.apana.org.au> writes: Brian> Good point. I meant to change it in both places, but I think I ended Brian> up changing it in only one place... You were right, I missed it up. Here is a patch that turns all methods into abstract methods. Unfortunately, I could not make Finalize abstract, the compiler complained that abstract methods must be visible (Finalize is in the private section). This restriction seems strange to me, but I am not going to argue with the compiler and left the function generating an exception at run-time. I suspect Finalize doesn't need to be abstract, but didn't go exploring enough to verify why it is abstract. Also, I noticed that the pointers are "access all". I couldn't see any requirement for "all", and my code still compiles, so I changed them to "access". This eliminates a potential source of errors. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: patch for abstract methods --] [-- Type: text/x-patch, Size: 13506 bytes --] --- apq-2.1-old/apq.ads 2003-09-25 05:56:24.000000000 +1000 +++ apq-2.1/apq.ads 2004-12-18 09:50:31.000000000 +1100 @@ -90,7 +90,7 @@ type Column_Index_Type is new Positive; - type Root_Connection_Type is new Ada.Finalization.Limited_Controlled with private; + type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with private; type Trace_Mode_Type is ( Trace_None, -- No tracing @@ -101,10 +101,10 @@ type Fetch_Mode_Type is ( Sequential_Fetch, Random_Fetch ); - type Root_Query_Type is new Ada.Finalization.Controlled with private; + type Root_Query_Type is abstract new Ada.Finalization.Controlled with private; - function Engine_Of(C : Root_Connection_Type) return Database_Type; + function Engine_Of(C : Root_Connection_Type) return Database_Type is Abstract; function New_Query(C : Root_Connection_Type) return Root_Query_Type'Class; procedure Set_Host_Name(C : in out Root_Connection_Type; Host_Name : String); @@ -123,13 +123,13 @@ function User(C : Root_Connection_Type) return String; function Password(C : Root_Connection_Type) return String; - procedure Connect(C : in out Root_Connection_Type); -- IS ABSTRACT - procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class); -- IS ABSTRACT - procedure Disconnect(C : in out Root_Connection_Type); -- IS ABSTRACT - - function Is_Connected(C : Root_Connection_Type) return Boolean; -- IS ABSTRACT - procedure Reset(C : in out Root_Connection_Type); -- IS ABSTRACT - function Error_Message(C : Root_Connection_Type) return String; -- IS ABSTRACT + procedure Connect(C : in out Root_Connection_Type) is abstract; + procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class) is abstract; + procedure Disconnect(C : in out Root_Connection_Type) is abstract; + + function Is_Connected(C : Root_Connection_Type) return Boolean is abstract; + procedure Reset(C : in out Root_Connection_Type) is abstract; + function Error_Message(C : Root_Connection_Type) return String is abstract; function In_Abort_State(C : Root_Connection_Type) return Boolean; @@ -137,7 +137,7 @@ function Will_Rollback_On_Finalize(C : Root_Connection_Type) return Boolean; - function Engine_Of(Q : Root_Query_Type) return Database_Type; + function Engine_Of(Q : Root_Query_Type) return Database_Type is Abstract; procedure Clear(Q : in out Root_Query_Type); function Fetch_Mode(Q : Root_Query_Type) return Fetch_Mode_Type; @@ -160,40 +160,40 @@ procedure Append_Quoted(Q : in out Root_Query_Type; Connection : Root_Connection_Type'Class; SQL : String; After : String := ""); procedure Append_Quoted(Q : in out Root_Query_Type; Connection : Root_Connection_Type'Class; SQL : Ada.Strings.Unbounded.Unbounded_String; After : String := ""); - procedure Execute(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class); - procedure Execute_Checked(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class; Msg : String := ""); + procedure Execute(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is abstract; + procedure Execute_Checked(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class; Msg : String := "") is abstract; - procedure Begin_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class); - procedure Commit_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class); - procedure Rollback_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class); + procedure Begin_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is abstract; + procedure Commit_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is abstract; + procedure Rollback_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is abstract; procedure Raise_Exceptions(Query : in out Root_Query_Type; Raise_On : Boolean := True); procedure Report_Errors(Query : in out Root_Query_Type; Report_On : Boolean := True); - procedure Rewind(Q : in out Root_Query_Type); - procedure Fetch(Q : in out Root_Query_Type); - procedure Fetch(Q : in out Root_Query_Type; TX : Tuple_Index_Type); - - function End_of_Query(Q : Root_Query_Type) return Boolean; - function Tuple(Q : Root_Query_Type) return Tuple_Index_Type; - function Tuples(Q : Root_Query_Type) return Tuple_Count_Type; + procedure Rewind(Q : in out Root_Query_Type) is abstract; + procedure Fetch(Q : in out Root_Query_Type) is abstract; + procedure Fetch(Q : in out Root_Query_Type; TX : Tuple_Index_Type) is abstract; + + function End_of_Query(Q : Root_Query_Type) return Boolean is abstract; + function Tuple(Q : Root_Query_Type) return Tuple_Index_Type is abstract; + function Tuples(Q : Root_Query_Type) return Tuple_Count_Type is abstract; - function Value(Query : Root_Query_Type; CX : Column_Index_Type) return String; -- Abstract + function Value(Query : Root_Query_Type; CX : Column_Index_Type) return String is abstract; procedure Value(Query: Root_Query_Type; CX : Column_Index_Type; V : out String); function Value(Query : Root_Query_Type; CX : Column_Index_Type) return Ada.Strings.Unbounded.Unbounded_String; function Value(Query : Root_Query_Type; CX : Column_Index_Type) return Row_ID_Type; function Value(Query : Root_Query_Type; CX : Column_Index_Type) return APQ_Bitstring; - function Result(Query : Root_Query_Type) return Natural; -- Returns Result_Type'Pos() + function Result(Query : Root_Query_Type) return Natural is abstract; -- Returns Result_Type'Pos() - function Is_Null(Q : Root_Query_Type; CX : Column_Index_Type) return Boolean; + function Is_Null(Q : Root_Query_Type; CX : Column_Index_Type) return Boolean is abstract; - function Command_Oid(Query : Root_Query_Type) return Row_ID_Type; - function Null_Oid(Query : Root_Query_Type) return Row_ID_Type; + function Command_Oid(Query : Root_Query_Type) return Row_ID_Type is abstract; + function Null_Oid(Query : Root_Query_Type) return Row_ID_Type is abstract; - function Error_Message(Query : Root_Query_Type) return String; - function Is_Duplicate_Key(Query : Root_Query_Type) return Boolean; + function Error_Message(Query : Root_Query_Type) return String is abstract; + function Is_Duplicate_Key(Query : Root_Query_Type) return Boolean is abstract; function To_String(Query : Root_Query_Type) return String; @@ -573,15 +573,15 @@ package CStr renames Interfaces.C_Streams; - type String_Ptr is access all String; + type String_Ptr is access String; type String_Ptr_Array is array(Natural range <>) of String_Ptr; - type String_Ptr_Array_Access is access all String_Ptr_Array; - type Stream_Element_Array_Ptr is access all Ada.Streams.Stream_Element_Array; + type String_Ptr_Array_Access is access String_Ptr_Array; + type Stream_Element_Array_Ptr is access Ada.Streams.Stream_Element_Array; subtype Port_Integer is Integer range 0..32768; type Port_Format_Type is ( IP_Port, UNIX_Port ); - type Root_Connection_Type is new Ada.Finalization.Limited_Controlled with + type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with record Host_Name : String_Ptr; -- Host name string or.. Host_Address : String_Ptr; -- Host IP address @@ -602,7 +602,7 @@ procedure Clear_Abort_State(C : in out Root_Connection_Type); - type Root_Query_Type is new Ada.Finalization.Controlled with + type Root_Query_Type is abstract new Ada.Finalization.Controlled with record Count : Natural := 0; -- # of elements in the Collection Alloc : Natural := 0; -- # of allocated elements in the Collection --- apq-2.1-old/apq.adb 2003-09-25 05:56:24.000000000 +1000 +++ apq-2.1/apq.adb 2004-12-18 09:10:51.000000000 +1100 @@ -198,38 +198,6 @@ -- ABSTRACT PRIMITIVES - procedure Connect(C : in out Root_Connection_Type) is - begin - raise Is_Abstract; - end Connect; - - procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class) is - begin - raise Is_Abstract; - end Connect; - - procedure Disconnect(C : in out Root_Connection_Type) is - begin - raise Is_Abstract; - end Disconnect; - - function Is_Connected(C : Root_Connection_Type) return Boolean is - begin - raise Is_Abstract; - return False; - end Is_Connected; - - procedure Reset(C : in out Root_Connection_Type) is - begin - raise Is_Abstract; - end Reset; - - function Error_Message(C : Root_Connection_Type) return String is - begin - raise Is_Abstract; - return ""; - end Error_Message; - procedure Clear(Q : in out Root_Query_Type) is begin for X in 1..Q.Count loop @@ -368,45 +336,6 @@ end; end To_String; - procedure Rewind(Q : in out Root_Query_Type) is - begin - raise Is_Abstract; - end Rewind; - - procedure Fetch(Q : in out Root_Query_Type) is - begin - raise Is_Abstract; - end Fetch; - - procedure Fetch(Q : in out Root_Query_Type; TX : Tuple_Index_Type) is - begin - raise Is_Abstract; - end Fetch; - - function End_of_Query(Q : Root_Query_Type) return Boolean is - begin - raise Is_Abstract; - return False; - end End_of_Query; - - function Tuple(Q : Root_Query_Type) return Tuple_Index_Type is - begin - raise Is_Abstract; - return Tuple_Index_Type'First; - end Tuple; - - function Tuples(Q : Root_Query_Type) return Tuple_Count_Type is - begin - raise Is_Abstract; - return Tuple_Count_Type'First; - end Tuples; - - function Value(Query : Root_Query_Type; CX : Column_Index_Type) return String is - begin - raise Is_Abstract; - return ":-)"; - end Value; - function Value(Query : Root_Query_Type; CX : Column_Index_Type) return Ada.Strings.Unbounded.Unbounded_String is use Ada.Strings.Unbounded; begin @@ -443,73 +372,6 @@ return C.Rollback_Finalize; end Will_Rollback_On_Finalize; - function Result(Query : Root_Query_Type) return Natural is - begin - raise Is_Abstract; -- This primitive must be overridden by the implementation - return 0; -- This is just to satisfy the compiler (not executed) - end Result; - - function Engine_Of(C : Root_Connection_Type) return Database_Type is - begin - raise Is_Abstract; -- Must be overridden - return Database_Type'First; -- To quiet the compiler - end Engine_Of; - - function Engine_Of(Q : Root_Query_Type) return Database_Type is - begin - raise Is_Abstract; -- Must be overridden - return Database_Type'First; -- To quiet the compiler - end Engine_Of; - - function Command_Oid(Query : Root_Query_Type) return Row_ID_Type is - begin - raise Is_Abstract; - return Row_ID_Type'First; - end Command_Oid; - - function Null_Oid(Query : Root_Query_Type) return Row_ID_Type is - begin - raise Is_Abstract; - return Row_ID_Type'First; - end Null_Oid; - - function Error_Message(Query : Root_Query_Type) return String is - begin - raise Is_Abstract; - return ""; - end Error_Message; - - function Is_Duplicate_Key(Query : Root_Query_Type) return Boolean is - begin - raise Is_Abstract; - return False; - end Is_Duplicate_Key; - - procedure Execute(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is - begin - raise Is_Abstract; - end Execute; - - procedure Execute_Checked(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class; Msg : String := "") is - begin - raise Is_Abstract; - end Execute_Checked; - - procedure Begin_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is - begin - raise Is_Abstract; - end Begin_Work; - - procedure Commit_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is - begin - raise Is_Abstract; - end Commit_Work; - - procedure Rollback_Work(Query : in out Root_Query_Type; Connection : in out Root_Connection_Type'Class) is - begin - raise Is_Abstract; - end Rollback_Work; - function Time_Component(TM : Ada.Calendar.Day_Duration; Unit : Time_Unit) return Natural is begin case Unit is @@ -1178,12 +1040,6 @@ end if; end Encode_Bitstring; - function Is_Null(Q : Root_Query_Type; CX : Column_Index_Type) return Boolean is - begin - raise Is_Abstract; -- Must be overriden - return False; - end Is_Null; - function Column_Is_Null(Q : Root_Query_Type'Class; CX : Column_Index_Type) return Ind_Type is begin return Ind_Type(Is_Null(Root_Query_Type'Class(Q),CX)); @@ -1373,7 +1229,6 @@ procedure Date_Fetch(Query : Root_Query_Type'Class; CX : Column_Index_Type; V : out Val_Type; Indicator : out Ind_Type) is function Value is new Date_Value(Val_Type); - D : APQ_Date; begin Indicator := Ind_Type( Is_Null(Root_Query_Type'Class(Query),CX) ); if not Indicator then [-- Attachment #3: Type: text/plain, Size: 40 bytes --] -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 22:55 ` APQ Brian May @ 2004-12-18 15:52 ` Warren W. Gay VE3WWG 2004-12-18 18:23 ` APQ Dmitry A. Kazakov 2004-12-22 10:07 ` APQ Martin Krischik 0 siblings, 2 replies; 28+ messages in thread From: Warren W. Gay VE3WWG @ 2004-12-18 15:52 UTC (permalink / raw) Brian May wrote: >>>>>>"Brian" == Brian May <bam@snoopy.apana.org.au> writes: > > > Brian> Good point. I meant to change it in both places, but I think I ended > Brian> up changing it in only one place... > > You were right, I missed it up. > > Here is a patch that turns all methods into abstract methods. Ok, Brian, hang on to your patches. I am trying to get my Source Forge account reactivated (something's happened to it), and then get this project up there. I am surprised that that was all there was to it. I must have made the same mistake. > Unfortunately, I could not make Finalize abstract, the compiler > complained that abstract methods must be visible (Finalize is in the > private section). This restriction seems strange to me, but I am not > going to argue with the compiler and left the function generating an > exception at run-time. > > I suspect Finalize doesn't need to be abstract, but didn't go > exploring enough to verify why it is abstract. Normally, you would want to override Finalize, because you will have allocated references within the derived object to clean up etc. However, 90% is better than nothing ;-) > Also, I noticed that the pointers are "access all". I couldn't see any > requirement for "all", and my code still compiles, so I changed them > to "access". This eliminates a potential source of errors. I can't imagine it making a practical difference here, but perhaps I lack imagination on this point. Warren. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-18 15:52 ` APQ Warren W. Gay VE3WWG @ 2004-12-18 18:23 ` Dmitry A. Kazakov 2004-12-21 23:34 ` APQ Brian May 2004-12-22 10:07 ` APQ Martin Krischik 1 sibling, 1 reply; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-18 18:23 UTC (permalink / raw) On Sat, 18 Dec 2004 10:52:52 -0500, Warren W. Gay VE3WWG wrote: > Brian May wrote: >> Also, I noticed that the pointers are "access all". I couldn't see any >> requirement for "all", and my code still compiles, so I changed them >> to "access". This eliminates a potential source of errors. > > I can't imagine it making a practical difference here, but > perhaps I lack imagination on this point. Potentially plain access pointers could be more efficient. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-18 18:23 ` APQ Dmitry A. Kazakov @ 2004-12-21 23:34 ` Brian May 2004-12-22 8:57 ` APQ Dmitry A. Kazakov 0 siblings, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-21 23:34 UTC (permalink / raw) >>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: Dmitry> Potentially plain access pointers could be more efficient. There have been other benefits described on this newsgroup. For instance, it prevents this type of error: declare A : aliased XYZ_Type; Ptr : XYZ_Ptr_Type := A'Access; begin ... Free(Ptr); end; Sure that is obvious in this case, but in a more complicated situation... The C++ solution is for programmers to impose rules on themselves, e.g. this pointer will only point to memory allocated dynamically. In Ada you can have the compiler enforce these rules, and it makes sense to let the compiler do this. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-21 23:34 ` APQ Brian May @ 2004-12-22 8:57 ` Dmitry A. Kazakov 0 siblings, 0 replies; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-22 8:57 UTC (permalink / raw) On Wed, 22 Dec 2004 10:34:12 +1100, Brian May wrote: >>>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: > > Dmitry> Potentially plain access pointers could be more efficient. > > There have been other benefits described on this newsgroup. For > instance, it prevents this type of error: > > declare > A : aliased XYZ_Type; > Ptr : XYZ_Ptr_Type := A'Access; > begin > ... > Free(Ptr); > end; Good point! -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-18 15:52 ` APQ Warren W. Gay VE3WWG 2004-12-18 18:23 ` APQ Dmitry A. Kazakov @ 2004-12-22 10:07 ` Martin Krischik 2004-12-22 13:15 ` APQ Dmitry A. Kazakov 1 sibling, 1 reply; 28+ messages in thread From: Martin Krischik @ 2004-12-22 10:07 UTC (permalink / raw) Warren W. Gay VE3WWG wrote: > I can't imagine it making a practical difference here, but > perhaps I lack imagination on this point. http://en.wikibooks.org/wiki/Programming:Ada:Types:access#access_vs._access_all Martin -- mailto://krischik@users.sourceforge.net http://www.ada.krischik.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-22 10:07 ` APQ Martin Krischik @ 2004-12-22 13:15 ` Dmitry A. Kazakov 2004-12-22 16:53 ` APQ Martin Krischik 0 siblings, 1 reply; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-22 13:15 UTC (permalink / raw) On Wed, 22 Dec 2004 11:07:44 +0100, Martin Krischik wrote: > Warren W. Gay VE3WWG wrote: > >> I can't imagine it making a practical difference here, but >> perhaps I lack imagination on this point. > > http://en.wikibooks.org/wiki/Programming:Ada:Types:access#access_vs._access_all Pool-specific access types do not do well: 1. Upcast/downcast conversions do not work. You'll need Unchecked_Conversion of pointers. It is nasty and dangerous. 2. '[Unchecked_]Access does not work (otherwise, (1) would be a minor problem). 3. Rosen's trick does not work. Very bad. Move it to Initialize? That won't work either, because of 2. 4. Construction/destruction is headache. Wished to insert a newly created object into a list? Not from Initialize! To delete it from there upon destruction? Nay! 5. Access discriminants cannot be pool-specific. Converting to general access to specific one is again an Unchecked_Conversion of worst kind. 6. There is no way to restrict objects allocations to a definite set of pools. "type X (<>) is ..." does not count. In general, I think that the issue should be thoroughly reworked. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-22 13:15 ` APQ Dmitry A. Kazakov @ 2004-12-22 16:53 ` Martin Krischik 2004-12-22 17:21 ` APQ Dmitry A. Kazakov 0 siblings, 1 reply; 28+ messages in thread From: Martin Krischik @ 2004-12-22 16:53 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Wed, 22 Dec 2004 11:07:44 +0100, Martin Krischik wrote: > >> Warren W. Gay VE3WWG wrote: >> >>> I can't imagine it making a practical difference here, but >>> perhaps I lack imagination on this point. >> >> http://en.wikibooks.org/wiki/Programming:Ada:Types:access#access_vs._access_all > > Pool-specific access types do not do well: > > 1. Upcast/downcast conversions do not work. You'll need > Unchecked_Conversion of pointers. It is nasty and dangerous. > > 2. '[Unchecked_]Access does not work (otherwise, (1) would be a minor > problem). > > 3. Rosen's trick does not work. Very bad. Move it to Initialize? That > won't work either, because of 2. > > 4. Construction/destruction is headache. Wished to insert a newly created > object into a list? Not from Initialize! To delete it from there upon > destruction? Nay! > > 5. Access discriminants cannot be pool-specific. Converting to general > access to specific one is again an Unchecked_Conversion of worst kind. > > 6. There is no way to restrict objects allocations to a definite set of > pools. "type X (<>) is ..." does not count. > > In general, I think that the issue should be thoroughly reworked. Well, ist wiki. Klick on [edit] and make your point. It OK by me - actually it is he hole point of wiki: incremental impovement. With Regards Martin -- mailto://krischik@users.sourceforge.net http://www.ada.krischik.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-22 16:53 ` APQ Martin Krischik @ 2004-12-22 17:21 ` Dmitry A. Kazakov 2004-12-22 18:23 ` APQ Martin Krischik 0 siblings, 1 reply; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-22 17:21 UTC (permalink / raw) On Wed, 22 Dec 2004 17:53:14 +0100, Martin Krischik wrote: > Dmitry A. Kazakov wrote: > >> On Wed, 22 Dec 2004 11:07:44 +0100, Martin Krischik wrote: >> >>> Warren W. Gay VE3WWG wrote: >>> >>>> I can't imagine it making a practical difference here, but >>>> perhaps I lack imagination on this point. >>> >>> > http://en.wikibooks.org/wiki/Programming:Ada:Types:access#access_vs._access_all >> >> Pool-specific access types do not do well: >> >> 1. Upcast/downcast conversions do not work. You'll need >> Unchecked_Conversion of pointers. It is nasty and dangerous. >> >> 2. '[Unchecked_]Access does not work (otherwise, (1) would be a minor >> problem). >> >> 3. Rosen's trick does not work. Very bad. Move it to Initialize? That >> won't work either, because of 2. >> >> 4. Construction/destruction is headache. Wished to insert a newly created >> object into a list? Not from Initialize! To delete it from there upon >> destruction? Nay! >> >> 5. Access discriminants cannot be pool-specific. Converting to general >> access to specific one is again an Unchecked_Conversion of worst kind. >> >> 6. There is no way to restrict objects allocations to a definite set of >> pools. "type X (<>) is ..." does not count. >> >> In general, I think that the issue should be thoroughly reworked. > > Well, ist wiki. Klick on [edit] and make your point. It OK by me - actually > it is he hole point of wiki: incremental impovement. Of what? Is wiki =ARG or else [edit button] = AI? (:-)) -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-22 17:21 ` APQ Dmitry A. Kazakov @ 2004-12-22 18:23 ` Martin Krischik 0 siblings, 0 replies; 28+ messages in thread From: Martin Krischik @ 2004-12-22 18:23 UTC (permalink / raw) Dmitry A. Kazakov wrote: > On Wed, 22 Dec 2004 17:53:14 +0100, Martin Krischik wrote: > >> Dmitry A. Kazakov wrote: >> >>> On Wed, 22 Dec 2004 11:07:44 +0100, Martin Krischik wrote: >>> >>>> Warren W. Gay VE3WWG wrote: >>>> >>>>> I can't imagine it making a practical difference here, but >>>>> perhaps I lack imagination on this point. >>>> >>>> >> http://en.wikibooks.org/wiki/Programming:Ada:Types:access#access_vs._access_all >>> >>> Pool-specific access types do not do well: >>> >>> 1. Upcast/downcast conversions do not work. You'll need >>> Unchecked_Conversion of pointers. It is nasty and dangerous. >>> >>> 2. '[Unchecked_]Access does not work (otherwise, (1) would be a minor >>> problem). >>> >>> 3. Rosen's trick does not work. Very bad. Move it to Initialize? That >>> won't work either, because of 2. >>> >>> 4. Construction/destruction is headache. Wished to insert a newly >>> created object into a list? Not from Initialize! To delete it from there >>> upon destruction? Nay! >>> >>> 5. Access discriminants cannot be pool-specific. Converting to general >>> access to specific one is again an Unchecked_Conversion of worst kind. >>> >>> 6. There is no way to restrict objects allocations to a definite set of >>> pools. "type X (<>) is ..." does not count. >>> >>> In general, I think that the issue should be thoroughly reworked. >> >> Well, ist wiki. Klick on [edit] and make your point. It OK by me - >> actually it is he hole point of wiki: incremental impovement. > > Of what? Is wiki =ARG or else [edit button] = AI? (:-)) I thought you mean that the wiki tutorial "Programming:Ada" need some reworking as it states the disadvantages of Pool-specific access not clear enough. As for ARG and the AI - well I guess you know the procedure - if not I can tell you :-) . With Regards Martin. -- mailto://krischik@users.sourceforge.net http://www.ada.krischik.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 3:45 ` APQ Brian May 2004-12-17 4:03 ` APQ Warren W. Gay VE3WWG @ 2004-12-17 8:59 ` Stephen Leake 2004-12-17 14:12 ` APQ Dmitry A. Kazakov 2 siblings, 0 replies; 28+ messages in thread From: Stephen Leake @ 2004-12-17 8:59 UTC (permalink / raw) To: comp.lang.ada Brian May <bam@snoopy.apana.org.au> writes: > I tried to get it working, but couldn't: please post a _complete_ example, so we can try to compile it. The most likely answer is that there is something wrong in the code you didn't post. -- -- Stephe ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 3:45 ` APQ Brian May 2004-12-17 4:03 ` APQ Warren W. Gay VE3WWG 2004-12-17 8:59 ` APQ Stephen Leake @ 2004-12-17 14:12 ` Dmitry A. Kazakov 2004-12-17 23:20 ` APQ Brian May 2004-12-21 23:29 ` APQ Brian May 2 siblings, 2 replies; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-17 14:12 UTC (permalink / raw) On Fri, 17 Dec 2004 14:45:17 +1100, Brian May wrote: > type Root_Connection_Type is abstract new Ada.Finalization.Limited_Controlled with private; If you are going to rework it, then derive it directly from an abstract object used for reference counting. That would save one level of indirection: type Root_Connection_Type is abstract new Object.Entity with private; > procedure Connect(C : in out Root_Connection_Type) is abstract; This is 100% legal. Probably you have conflicting views. > procedure Connect(C : in out Root_Connection_Type; Same_As : Root_Connection_Type'Class) is abstract; Are you going to clone connections between different DBs? The above looks like an attempt to emulate multiple dispatch.! It should be: procedure Connect ( C : in out Root_Connection_Type; Same_As : Root_Connection_Type -- Same types required! ) is abstract; However would be is pretty useless, when you have a class-wide object at hand. I suppose that the idea was to make a copy of a limited object. Then it should better be: function Copy (C : Root_Connection_Type) return Root_Connection_Ptr is abstract; This would allocate a copy and connect it to the same DB. Because reference counting is intended you will need dynamic allocation anyway. The user will of course do it all with handles: function Copy (C : Handle) return Handle is Clone_Ptr : Root_Connection_Type_Ptr := Copy (Ptr (C).all); -- This clones the object pointed by the handle, the reference -- count of the copy is initially 0 begin return Ref (Clone_Ptr); -- Result is a handle, and the reference count is 1, now end Copy; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 14:12 ` APQ Dmitry A. Kazakov @ 2004-12-17 23:20 ` Brian May 2004-12-18 16:13 ` APQ Dmitry A. Kazakov 2004-12-21 23:29 ` APQ Brian May 1 sibling, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-17 23:20 UTC (permalink / raw) >>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: Dmitry> Are you going to clone connections between different DBs? Dmitry> The above looks like an attempt to emulate multiple Dmitry> dispatch.! Dmitry> It should be: Dmitry> procedure Connect Dmitry> ( C : in out Root_Connection_Type; Dmitry> Same_As : Root_Connection_Type -- Same types required! Dmitry> ) is abstract; I will look in more detail at the rest of what you have written latter. I think your ideas are good. However, I think the above is illegal, as Ada doesn't "know" what parameter to use for dispatching to the correct routine. The same thing, I believe applies to a function that takes Root_Connection_Type as a parameter and returns a Root_Connection_Type. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 23:20 ` APQ Brian May @ 2004-12-18 16:13 ` Dmitry A. Kazakov 0 siblings, 0 replies; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-18 16:13 UTC (permalink / raw) On Sat, 18 Dec 2004 10:20:25 +1100, Brian May wrote: >>>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: > > Dmitry> Are you going to clone connections between different DBs? > Dmitry> The above looks like an attempt to emulate multiple > Dmitry> dispatch.! > > Dmitry> It should be: > > Dmitry> procedure Connect > Dmitry> ( C : in out Root_Connection_Type; > Dmitry> Same_As : Root_Connection_Type -- Same types required! > Dmitry> ) is abstract; > > I will look in more detail at the rest of what you have written > latter. I think your ideas are good. However, I think the above is > illegal, as Ada doesn't "know" what parameter to use for dispatching > to the correct routine. It is legal. You will have a run-time exception if the tags of actual parameters are different. In fact it is a limited form of multiple dispatch. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-17 14:12 ` APQ Dmitry A. Kazakov 2004-12-17 23:20 ` APQ Brian May @ 2004-12-21 23:29 ` Brian May 2004-12-22 9:14 ` APQ Dmitry A. Kazakov 1 sibling, 1 reply; 28+ messages in thread From: Brian May @ 2004-12-21 23:29 UTC (permalink / raw) >>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: >> procedure Connect(C : in out Root_Connection_Type; Same_As : >> Root_Connection_Type'Class) is abstract; Dmitry> Are you going to clone connections between different DBs? Dmitry> The above looks like an attempt to emulate multiple Dmitry> dispatch.! I read a documentation somewhere that said the code below is not legal, and the above had to be used instead... The documentation said the code body could check the types were correct. However, on advice from Dmitry, I tried a test case with the code below, and it seems to work fine. Need to keep my eyes open for that reference. Wonder if it was that dodgy guide on the web about Ada for C++ programmers... Dmitry> It should be: Dmitry> procedure Connect Dmitry> ( C : in out Root_Connection_Type; Dmitry> Same_As : Root_Connection_Type -- Same types required! Dmitry> ) is abstract; Dmitry> However would be is pretty useless, when you have a Dmitry> class-wide object at hand. Dmitry> I suppose that the idea was to make a copy of a limited Dmitry> object. Then it should better be: Dmitry> function Copy (C : Root_Connection_Type) Dmitry> return Root_Connection_Ptr is abstract; Dmitry> This would allocate a copy and connect it to the same Dmitry> DB. Because reference counting is intended you will need Dmitry> dynamic allocation anyway. The user will of course do it Dmitry> all with handles: I have a suspicion this would not work as Root_Connection_Type is a limited type. Or am I yet again mistaken? Can somebody please let me know what applications a cloning function has? I frequently hear of such functions, but rarely (if ever) needed to use one. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-21 23:29 ` APQ Brian May @ 2004-12-22 9:14 ` Dmitry A. Kazakov 2005-01-04 21:32 ` APQ Brian May 0 siblings, 1 reply; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-22 9:14 UTC (permalink / raw) On Wed, 22 Dec 2004 10:29:01 +1100, Brian May wrote: >>>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: > Dmitry> function Copy (C : Root_Connection_Type) > Dmitry> return Root_Connection_Ptr is abstract; > > Dmitry> This would allocate a copy and connect it to the same > Dmitry> DB. Because reference counting is intended you will need > Dmitry> dynamic allocation anyway. The user will of course do it > Dmitry> all with handles: > > I have a suspicion this would not work as Root_Connection_Type is a > limited type. Or am I yet again mistaken? You probably mean this: function Copy (C : Root_Connection_Type'Class) return Root_Connection_Ptr is begin return new Root_Connection_Type'Class'(C); end Copy; This indeed cannot work for limited types. This was the reason why Copy was declared abstract primitive instead: function Copy (C : Root_Connection_Type) return Root_Connection_Ptr is abstract; It will dispatch to an implementation which knows how to copy itself: function Copy (C : My_Connection_Type) return Root_Connection_Ptr is Result : Root_Connection_Ptr := new My_Connection_Type; Object : My_Connection_Type renames My_Connection_Type (Result.all); begin Object.Field_Foo := C.Field_Foo; ... -- Clone me tender return Result; exception when others => Free (Result); -- No memory leaks! raise; end Copy; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-22 9:14 ` APQ Dmitry A. Kazakov @ 2005-01-04 21:32 ` Brian May 2005-01-05 11:58 ` APQ Dmitry A. Kazakov 0 siblings, 1 reply; 28+ messages in thread From: Brian May @ 2005-01-04 21:32 UTC (permalink / raw) >>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: Dmitry> You probably mean this: Dmitry> function Copy (C : Root_Connection_Type'Class) Dmitry> return Root_Connection_Ptr is Dmitry> begin Dmitry> return new Root_Connection_Type'Class'(C); Dmitry> end Copy; Dmitry> This indeed cannot work for limited types. This was the Dmitry> reason why Copy was declared abstract primitive instead: Dmitry> function Copy (C : Root_Connection_Type) Dmitry> return Root_Connection_Ptr is abstract; Dmitry> It will dispatch to an implementation which knows how to Dmitry> copy itself: I am under the impression (perhaps wrong impression, I haven't tested it) that A := Copy(C); will not work if C is a limited type, as there is an implied copy operation from the RHS to the LHS. Also the thread "Return_By_Reference or Return_By_Copy (GNAT bug?)" might be relevant here. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2005-01-04 21:32 ` APQ Brian May @ 2005-01-05 11:58 ` Dmitry A. Kazakov 0 siblings, 0 replies; 28+ messages in thread From: Dmitry A. Kazakov @ 2005-01-05 11:58 UTC (permalink / raw) On Wed, 05 Jan 2005 08:32:53 +1100, Brian May wrote: >>>>>> "Dmitry" == Dmitry A Kazakov <mailbox@dmitry-kazakov.de> writes: > > Dmitry> You probably mean this: > > Dmitry> function Copy (C : Root_Connection_Type'Class) > Dmitry> return Root_Connection_Ptr is > Dmitry> begin > Dmitry> return new Root_Connection_Type'Class'(C); > Dmitry> end Copy; > > Dmitry> This indeed cannot work for limited types. This was the > Dmitry> reason why Copy was declared abstract primitive instead: > > Dmitry> function Copy (C : Root_Connection_Type) > Dmitry> return Root_Connection_Ptr is abstract; > > Dmitry> It will dispatch to an implementation which knows how to > Dmitry> copy itself: > > I am under the impression (perhaps wrong impression, I haven't tested > it) that > > A := Copy(C); > > will not work if C is a limited type, as there is an implied copy > operation from the RHS to the LHS. The following is an fully operational implementation of what I meant based on Simple Components (http://www.dmitry-kazakov.de/ada/components.htm): -- The test program first: with Connections; use Connections; with Connections.My_Connections; procedure Test_Connections is A : Connection; -- Illegal, will not compile B : Connection := Connections.My_Connections.Create (10); C : Connection := Copy (B); -- Make a copy D : Connection := B; -- Reference begin null; end Test_Connections; Here B and D are handles to the same internal connection object. They share it. C is a handle to a copy of the object pointed by B,D. The connection objects are automatically destroyed when the last handle disappear. User sees only the type Connection. -- Abstract connection interface. A connection is a handle to -- the connection object. Handles are not limited, objects are. with Object; with Object.Handle; package Connections is type Connection (<>) is private; function Copy (C : Connection) return Connection; private type Root_Connection_Object is abstract new Object.Entity with null record; type Root_Connection_Ptr is access Root_Connection_Object'Class; function Copy (C : Root_Connection_Object) return Root_Connection_Ptr is abstract; package Connection_Handles is new Object.Handle (Root_Connection_Object, Root_Connection_Ptr); type Connection is new Connection_Handles.Handle with null record; function Ref (C : Root_Connection_Ptr) return Connection; end Connections; package body Connections is function Copy (C : Connection) return Connection is begin return Ref (Copy (Ptr (C).all)); end Copy; function Ref (C : Root_Connection_Ptr) return Connection is begin return (Connection_Handles.Ref (C) with null record); end Ref; end Connections; -- An implementation: My_Connection package Connections.My_Connections is function Create (Parameter : Integer) return Connection; private type My_Connection_Object is new Root_Connection_Object with record I : Integer; end record; function Copy (C : My_Connection_Object) return Root_Connection_Ptr; end Connections.My_Connections; package body Connections.My_Connections is function Create (Parameter : Integer) return Connection is This : Root_Connection_Ptr := new My_Connection_Object; Object : My_Connection_Object renames My_Connection_Object (This.all); begin Object.I := Parameter; return Ref (This); end Create; function Copy (C : My_Connection_Object) return Root_Connection_Ptr is This : Root_Connection_Ptr := new My_Connection_Object; Object : My_Connection_Object renames My_Connection_Object (This.all); begin Object.I := C.I; return This; end Copy; end Connections.My_Connections; > Also the thread "Return_By_Reference or Return_By_Copy (GNAT bug?)" might > be relevant here. Only in Ada 2005 there will be a way to have limited object constructors. Which will be BTW still too little for a proper construction model. There still will be no constructors with parameters. No copy constructors. No class-wide constructors. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: APQ 2004-12-15 23:31 APQ Brian May 2004-12-16 11:34 ` APQ Warren W. Gay VE3WWG @ 2004-12-17 13:54 ` Dmitry A. Kazakov 1 sibling, 0 replies; 28+ messages in thread From: Dmitry A. Kazakov @ 2004-12-17 13:54 UTC (permalink / raw) 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 ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2005-01-05 11:58 UTC | newest] Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-12-16 4:37 APQ Christoph Karl Walter Grein -- strict thread matches above, loose matches on Subject: below -- 2004-12-15 23:31 APQ Brian May 2004-12-16 11:34 ` APQ Warren W. Gay VE3WWG 2004-12-16 23:58 ` APQ Randy Brukardt 2004-12-17 3:45 ` APQ Brian May 2004-12-17 4:03 ` APQ Warren W. Gay VE3WWG 2004-12-17 4:38 ` APQ Brian May 2004-12-17 9:06 ` APQ Egil H. H�vik 2004-12-17 11:42 ` APQ Brian May 2004-12-17 22:55 ` APQ Brian May 2004-12-18 15:52 ` APQ Warren W. Gay VE3WWG 2004-12-18 18:23 ` APQ Dmitry A. Kazakov 2004-12-21 23:34 ` APQ Brian May 2004-12-22 8:57 ` APQ Dmitry A. Kazakov 2004-12-22 10:07 ` APQ Martin Krischik 2004-12-22 13:15 ` APQ Dmitry A. Kazakov 2004-12-22 16:53 ` APQ Martin Krischik 2004-12-22 17:21 ` APQ Dmitry A. Kazakov 2004-12-22 18:23 ` APQ Martin Krischik 2004-12-17 8:59 ` APQ Stephen Leake 2004-12-17 14:12 ` APQ Dmitry A. Kazakov 2004-12-17 23:20 ` APQ Brian May 2004-12-18 16:13 ` APQ Dmitry A. Kazakov 2004-12-21 23:29 ` APQ Brian May 2004-12-22 9:14 ` APQ Dmitry A. Kazakov 2005-01-04 21:32 ` APQ Brian May 2005-01-05 11:58 ` APQ Dmitry A. Kazakov 2004-12-17 13:54 ` APQ Dmitry A. Kazakov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox