Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!uunet!mcsun!cernvax!ethz!marti From: marti@ethz.UUCP (Robert Marti) Newsgroups: comp.lang.c++ Subject: Re: C++ Interfaces to Relational Databses. Keywords: C++, OOP, OODBMS. Message-ID: <2765@ethz.UUCP> Date: 8 Dec 89 10:03:19 GMT References: <6515@pbhyf.PacBell.COM> <1989Dec5.010812.3485@sjsumcs.sjsu.edu> Organization: ETH Zuerich Lines: 100 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 #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