[comp.lang.c++] C++ interfaces to Relational Databses.

mtc@PacBell.COM (Mitchell T. Christensen) (12/01/89)

	
	Hi there,

	We here at Pac*Bell are preparing to delve into Object Oriented
	production using c++.  We have a problem though.  I am unable to
	come up with a clean interface for c++ to our "standardized" DBMS
	Oracle. 

	Is there anyone out there who has solved this problem?

	Is there anyone out there who knows of an Object Oriented interface
	to ANY relational databases?  I understand that OODBMS's such as
	Gemstone would be the ideal solution to this problem but we are
	limited as to which DB platforms we are "allowed" to use.

	Thanks in advance.


-- 
/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-
Mitch Christensen - {ihnp4,dual,lll-crg,qantel,pyramid}!pacbell!pbhyf!mtc
/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-/-\-

horstman@sjsumcs.sjsu.edu (Cay Horstmann) (12/05/89)

In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen) writes:
>
>
>	
>	Hi there,
>
>	We here at Pac*Bell are preparing to delve into Object Oriented
>	production using c++.  We have a problem though.  I am unable to
>	come up with a clean interface for c++ to our "standardized" DBMS
>	Oracle. 
>
>	Is there anyone out there who has solved this problem?
>
I'd like to amend this query--does anyone know of some set of classes
implementing SQL? One could have a table class and overloaded operators
for the relational operations instead of the yucky SQL syntax. Somewhere
down the line they should map to embedded SQL queries. Is any such work
done anywhere?

Cay Horstmann
horstman@sjsumcs.sjsu.edu

fst@gtenmc.UUCP (Fariborz "Skip" Tavakkolian) (12/06/89)

In article <1989Dec5.010812.3485@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
>In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen) writes:
>>
>>
>>	Oracle. 
>>	Is there anyone out there who has solved this problem?
>>
>I'd like to amend this query--does anyone know of some set of classes
>implementing SQL? One could have a table class and overloaded operators
>for the relational operations instead of the yucky SQL syntax. Somewhere
>down the line they should map to embedded SQL queries. Is any such work
>done anywhere?
>Cay Horstmann
>horstman@sjsumcs.sjsu.edu


I have been thinking about a nice way to handle this for some time now.
I am still using embedded SQL in my C++ routines (I think this is my payment
for a past sin).  But here are some untried ideas.

Say you have something like:

    class Query {
    private:
       .
       .
       .
    public:
	Query(char* query_statement);
	~Query();
	prepare();
	execute(char* inputfmt, char *outputfmt, ...);
	...
    };

Then you could do this:

    Query foo("select tabid from systables where tabname = ?");

and then you could invoke Query::prepare() which ``finds out'' (in talking
to db-agent or looking up database catalogs) what is expected as input and
output (i.e. compiling the query) and setup internal storage for it.
Then you could execute the query like so:

    foo.execute("%s", "%d",  "systables", &someintvar);

Where the the number of input and output vars would be variable and dependent
on the query. My main reason for having an input and output format specifier
(a la printf(3), scanf(3)), is the following:  A database type DATE may be
stored as a "long" internally, but you want to be able to compare it to things
like "12/06/89" (i.e. char array), where the internal format does not tell
you what the host variable type may be.

You could also have a class called QueryCursor where you expect to
have a number of retrieved rows:

    QueryCursor xfoo("cursor_name", "select * from systables");

Then you could either have a QueryCursorIterator class (If that makes sense)
or have some member function like:

    QueryCursor::Fetch(DIRECTION sense, char* outputfmt, ...);

(WHERE:    enum DIRECTION { NEXT, PREVIOUS, /* or whatever */ } )

One other class you may need is probably the SimpleStatement class
for things like update, delete, grant, etc.

Hope this helps.

-- 
Fariborz "Skip" Tavakkolian of  Automated Cellular Engineering
Currently consulting at         GTE Telecom, Inc.
Mail                            tiny1!fst@mcgp1 / tiny1!fst@gtenmc / fst@gtenmc

grp@unify.uucp (Greg Pasquariello) (12/07/89)

In article <1989Dec5.010812.3485@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
>In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen) writes:
>>
>>
>>	
>>	Hi there,
>>
>>	We here at Pac*Bell are preparing to delve into Object Oriented
>>	production using c++.  We have a problem though.  I am unable to
>>	come up with a clean interface for c++ to our "standardized" DBMS
>>	Oracle. 
>>
>>	Is there anyone out there who has solved this problem?
>>
>I'd like to amend this query--does anyone know of some set of classes
>implementing SQL? 
>
>Cay Horstmann
>horstman@sjsumcs.sjsu.edu

In my previous life with EDS/ATT I began to implement such a set of classes.
I don't have them anymore.  Are these of general interest?

-Greg

-- 
-------------------------------------------------------------------------------
Greg Pasquariello	(916) 920-9092		grp@unify.UUCP
Unify Corporation				...!{csusac, pyramid}!unify!grp

dsa@dlogics.UUCP (David Angulo) (12/07/89)

In article <1989Dec5.010812.3485@sjsumcs.sjsu.edu>, horstman@sjsumcs.sjsu.edu (Cay Horstmann) writes:
> In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen) writes:
> >
> >
> >	
> >	Hi there,
> >
> >	We here at Pac*Bell are preparing to delve into Object Oriented
> >	production using c++.  We have a problem though.  I am unable to
> >	come up with a clean interface for c++ to our "standardized" DBMS
> >	Oracle. 
> >
> >	Is there anyone out there who has solved this problem?
> >
> I'd like to amend this query--does anyone know of some set of classes
> implementing SQL? One could have a table class and overloaded operators
> for the relational operations instead of the yucky SQL syntax. Somewhere
> down the line they should map to embedded SQL queries. Is any such work
> done anywhere?
> 
You can't really have a set of classes to implement SQL because when you
have an embedded SQL statement, you must include the table name and the
column name.  This is then precompiled into calls to some generic routines.
You can (with Oracle) call the generic routines yourself but this is quite
cumbersome and subject to change.  What we did is to create a code generator
that generates a class for each table (actually it generates quite a few
things for each table: documentation, the SQL statements to create the table,
and the code for the class, etc.).  This code has methods for insert,
update, fetch, etc. and contains the eSQL statements to do this.  We
then run the SQL preprocessor and take its outputted code (which it thinks
is C) and run it through the C++ compiler.  Hope this helps - email me if
you want a sample output of the code.

S
i
g
h

-- 
David S. Angulo                  (312) 266-3134
Datalogics                       Internet: dsa@dlogics.UUCP
441 W. Huron                     UUCP: ..!uunet!dlogics!dsa
Chicago, Il. 60610               FAX: (312) 266-4473

marti@ethz.UUCP (Robert Marti) (12/08/89)

In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen)
writes:
>	[We are] unable to come up with a clean interface for C++ to our
>     "standardized" DBMS Oracle.  Is there anyone out there who has
>     solved this problem?

Yes, we believe we have solved the problem.  About two years ago, we
designed a call interface to Oracle for Modula-2 (no flames, please ;-).
Although our interface was influenced by Oracle's OCI (formerly known
as HLI), we believe that our solution should be portable to other DBMSs
which support call interfaces, e.g., Sybase.  [As an aside: Oracle's
OCI isn't all that bad once you give the procedures sensible names and
leave some of the unnecessary parameters away ...]

I have recently rewritten this interface in C++.  I feel that the concepts
of classes, overloading and default parameters all have contributed to
make the interface both safer and cleaner than the Modula-2 version from
which it was derived.  The following class SQL_Request forms the core of
our interface:

class SQL_Request {
  public:
    SQL_Request(const char* statement);
      // Create a database request which subsequently can be executed
      // several times with possibly different input parameters by
      // calling member function Execute.

    ~SQL_Request();
      // Drop the database request.

    void BindInPar(const char* colName, const char* varAdr, int size,
                   const SQL_NullInd* indAdr = 0);
    void BindInPar(const char* colName, const int* varAdr,
                   const SQL_NullInd* indAdr = 0);
    void BindInPar(const char* colName, const double* varAdr,
                   const SQL_NullInd* indAdr = 0);
      // Bind the program variable at address varAdr as an input parameter
      // to column colName in the SQL statement associated with this request.
      // (indAdr may contain the address of a null indicator variable.)

    void BindOutPar(const char* colName, const char* varAdr, int size,
                    const SQL_NullInd* indAdr = 0);
    void BindOutPar(const char* colName, const int* varAdr,
                    const SQL_NullInd* indAdr = 0);
    void BindOutPar(const char* colName, const double* varAdr,
                    const SQL_NullInd* indAdr = 0);
      // Bind the program variable at address varAdr as an output parameter
      // to column colName in the SQL statement associated with this request.
      // (indAdr may contain the address of a null indicator variable.)

    SQL_Code Execute();
      // Execute this request.
      // Note: Execute copies the values of all bound input parameters
      // from the program variables into the database columns.

    SQL_code Fetch();
      // Fetch the next row associated with this request.
      // Note: Fetch copies the values of all bound output parameters
      // from the database columns into the program variables.

  private:
    // ...
};


As an illustration, here is a simple example of how to use this
interface:

#include <stdio.h>
#include "SQL.h"

  int empNo;
  char empName[20];
  double empSal;
  SQL_NullInd nullSal;

  SQL_Request query = "SELECT empNo, eName, sal \
                       FROM Emp \
                       WHERE sal > :sal";
  query.BindInPar("sal", &empSal);
  query.BindOutPar("empNo", &empNo);
  query.BindOutPar("eName", empName, sizeof(empName));
  query.BindOutPar("sal", &empSal, &nullSal);
  printf("enter minimum salary: ");
  scanf(" %f", &empSal);
  query.Execute();
  while (query.Fetch() == SQL_ok) {
    printf("%4d     %s", empNo, empName);
    if (nullSal == SQL_null) printf("    ** null salary **\n");
    else printf("     %f\n", empSal);
  }


I hope this helps ...

-- 
Robert Marti                      Phone:      +41 1 256 52 36
Institut fur Informationssysteme
ETH-Zentrum                       CSNET/ARPA: marti%inf.ethz.ch@relay.cs.net
CH-8092 Zurich, Switzerland       UUCP:       ...uunet!mcvax!ethz!marti

steve@jack.sns.com (J. Steven Harrison) (12/10/89)

In article <6515@pbhyf.PacBell.COM> mtc@PacBell.COM (Mitchell T. Christensen) writes:
>	We here at Pac*Bell are preparing to delve into Object Oriented
>	production using c++.  We have a problem though.  I am unable to
>	come up with a clean interface for c++ to our "standardized" DBMS
>	Oracle. 
>
We currently are doing development with Oracle using Pro*C and AT&T's Cfront
2.0.  It took some work but we experienced our FCS on Friday and all is
well.  

A couple of hacks to the Pro*C headers put us in business.  The hardest part,
as it turns out was getting Cfront ported to the Pyramids!

Contact me at this address if you have any specific questions.


-- 
____*_  Dr. J. Steven Harrison      {sun,sharkey,pacbell}!indetech!steve
\  / /  Independence Technologies   Director Database Applications
 \/ /   42705 Lawrence Place        FAX: 415 438-2034
  \/    Fremont, CA 94538           Voice: 415 438-2011

brad@sqwest.sq.com (Brad Might) (12/13/89)

>   You can't really have a set of classes to implement SQL because when you
>   have an embedded SQL statement, you must include the table name and the
>   column name.  This is then precompiled into calls to some generic routines.

	You can however send sql statements to Oracle at run-time and have it
	execute (dynamic sql).  You will have to build internal structures based
	on the information that Oracle returns about the statement

	- number, type, size of columns

	You could have an object which receives and holds this info as a buffer
	between you application and db.

	DBInterface.sendSQL(SQLStatement);

	ncols =	DBInterface.getNumCols() ;

	while (DBInterface.getNextRow()){
		for (i = 0 ; i < ncols; i++){
			switch (DBInterface.colType(i)) {
				case Chars:
				    printf("%s ", DBInterface.getString(i);
				    break;
				case Integer:
				    printf("%d ", DBInterface.getInt(i);
				   break ;
			}
		}
	}

-- 
Brad Might					brad@sq.com (brad@sq ?)
SoftQuad West					brad!sq!utzoo!...
(604) 585-1999