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-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,72b10ed43fd78730 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-01-02 22:58:45 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newspeer.monmouth.com!news.monmouth.com!shell.monmouth.com!not-for-mail From: ka@sorry.no.email (Kenneth Almquist) Newsgroups: comp.lang.ada Subject: Re: Call for review: Database API for the GNADE Project Date: 3 Jan 2002 01:58:38 -0500 Organization: A poorly-installed InterNetNews site Message-ID: References: <3C2E334F.EF4C534@snafu.de> NNTP-Posting-Host: shell.monmouth.com Xref: archiver1.google.com comp.lang.ada:18472 Date: 2002-01-03T01:58:38-05:00 List-Id: Michael Erdmann wrote: > X : Connection.Object; > Connect(X); > declare > q : Query.Object( X ); > begin > Statement( q, "select * from employees where name = ?" ); > Bind( q, 1, Name ); > Execute( q ); > ..... > end ; I wonder if replacing the various Bind procedures with generic packages would be better: declare Statement : constant SQL_Statement := Prepare(Connection, "select * from employees where empno = ?"); package Empno is new Set_Statement_Integer(Statement, 1); begin Empno.Set(Name); Result := Execute_Query(Statement); ... Set_Statement_Integer is a generic package containing a single procedure named Set. We use a generic package rather than a generic procedure so that we can perform validity checking when the package is instantiated, rather than performing a check every time a new value is assigned to empno. I've changed Execute to Execute_Query because when we execute a query we get back a set of results, whereas when we execute other types of SQL statements we get back a status code. > result := Execute( statement ); > while not End_of( result ) loop > row := Fetch( result ); > name := Get( row, 1 ); > boss := Get( row, 2 ); > ....... > loop; Is the row value valid after a subsequent fetch operation? If not, we could eliminate the row variable and get the fields of the current row directly from the result variable. Again, generics might be useful to get the row numbers out of the code: declare Row : SQL_Row; function Get_Name is new Get_Row_String(1); function Has_Boss is new Get_Row_Is_Null(2); function Get_Boss is new Get_Row_Integer(2); begin ... Row := Fetch(Result); Name := Get_Name(Row); if Has_Boss(Row) then Boss := Get_Boss(Row); else Put_Line("The CEO does not have a boss"); end if; ... > Mode: The fetch mode controls the behavior of the cursor in the > result set. Modes are: Forward, Backward. As far as I know, this is not supported by standard SQL, and I can't think of a reason why anyone would need this. > If the server drops the connection the procedure Disconnection_Event is > called. In order to implement specific behavior, the procedure may be > overloaded. If I understand correctly, Server_Error will be raised after this procedure is called. It seems like this procedure is unnecessary, since anything done by this procedure could instead be done by an exception handler. I hope these random thoughts are helpful. Kenneth Almquist