home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1996 February
/
PCWK0296.iso
/
po7_win
/
object10
/
odbase.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-04
|
11KB
|
443 lines
/* Copyright (c) Oracle Corporation 1994. All Rights Reserved */
/*
This source code is provided as a debugging aid for developers
who have purchased Oracle Objects for OLE . Please see the
online help for documentation of these classes.
*/
/*
Oracle Objects for OLE C++ Classes
This file implements the ODatabase class
CREATED ******** 11/22/94
*/
#include "windows.h"
#include <ole2.h>
#include <olenls.h>
#include <dispatch.h>
#ifndef ORACL_ORACLE
#include "oracl.h"
#endif
#ifndef _OracleInProcServer_H_
#include <oratlb.h>
#endif
#ifndef ORAOBJI_ORACLE
#include "oraobji.h"
#endif
static const IID IID_IOraDatabase =
{0x5cdfcf20, 0xffd7, 0x101a, { 0xad, 0xf2, 0x04, 0x02, 0x1c, 0x00, 0x70, 0x02 } };
// ----- ODatabase -----------------------------------------------
ODatabase::ODatabase(void)
{
m_dbname = 0;
m_dbconnect = 0;
m_errtext = 0;
m_numrows = -1;
}
ODatabase::~ODatabase(void)
{
Cleanup();
}
ODatabase::ODatabase(const ODatabase &other)
{
m_dbname = 0;
m_dbconnect = 0;
m_errtext = 0;
m_numrows = -1;
Copy(other); // call our internal copier
}
ODatabase::ODatabase(const OSession &dbsess, const char *dbname, const char *username, const char *pwd, long options)
{
m_dbname = 0;
m_dbconnect = 0;
m_errtext = 0;
m_numrows = -1;
Open(dbsess, dbname, username, pwd, options);
}
ODatabase::ODatabase(const char *dbname, const char *username, const char *pwd, long options)
{
m_dbname = 0;
m_dbconnect = 0;
m_errtext = 0;
m_numrows = -1;
Open(dbname, username, pwd, options);
}
oresult ODatabase::Close(void)
{
return(Cleanup());
}
oresult ODatabase::Cleanup(void)
{
if (m_dbname)
{
OObjectFreeString(m_dbname);
m_dbname = 0;
}
if (m_dbconnect)
{
OObjectFreeString(m_dbconnect);
m_dbconnect = 0;
}
if (m_errtext)
{
OObjectFreeString(m_errtext);
m_errtext = 0;
}
m_numrows = -1;
return(OOracleObject::Cleanup());
}
oresult ODatabase::Open(const char *dbname, const char *username, const char *pwd, long options)
{
// open a session for this database connection
OSession tempSess;
oresult ores;
ores = tempSess.Open();
if (ores == OSUCCESS)
ores = Open(tempSess, dbname, username, pwd, options);
else
{ // couldn't open the temporary session. Some OLE problem
SetInternalError(OERROR_SYSTEM);
}
/*
Note that although the OSession session variable will go away, the OLE session object
(in the oip) will not, because the database has a reference to it. The OLE session object
will go away when the database does.
*/
return(ores);
}
oresult ODatabase::Open(const OSession &sess, const char *dbname, const char *username, const char *pwd, long options)
{
if (!sess.IsOpen())
{ // no valid session
SetInternalError(OERROR_INVPARENT);
return(OFAILURE);
}
if (!dbname || !username)
{
SetInternalError(OERROR_BADARG);
return(OFAILURE);
}
// get the username and password into the right form
// DBCS problem - assumption of single-byte null
BSTR tp;
// password and username can't be more than 30 bytes apiece so...
const char *cp, *cp2;
cp = username;
while (*cp)
cp++; // scan to end of username
if (pwd)
{
cp2 = pwd;
while (*cp2)
cp2++;
}
//if (strlen(username) > 30 || (pwd && strlen(pwd) > 30))
if ((cp-username) > 30 || (pwd && (cp2-pwd)) > 30)
{
SetInternalError(OERROR_BADARG);
return(OFAILURE);
}
char temps[80];
if (pwd)
{ // the username and password are separate
// don't use strcpy, etc so that we don't drag in C runtime
tp = temps;
cp = username;
while (*cp)
*tp++ = *cp++;
*tp++ = '/';
cp = pwd;
while (*cp)
*tp++ = *cp++;
*tp = '\0'; // null terminate;
tp = OObjectAllocString(temps);
}
else
{
// the username must contain a '/'
cp = username;
while (*cp)
{
if (*cp == '/')
break;
cp++;
}
if (*cp != '/')
{ // no slash
SetInternalError(OERROR_BADARG);
return(OFAILURE);
}
tp = OObjectAllocString(username); // contains username/password
}
// get database name into BSTR
BSTR tempdbname = OObjectAllocString(dbname);
if (!tp || !tempdbname)
{
SetInternalError(OERROR_MEMORY);
if (tp)
OObjectFreeString(tp);
if (tempdbname)
OObjectFreeString(tempdbname);
return(OFAILURE);
}
// now do the real work
sess.ErrorReset(); // reset error state of session
IDispatch *dbi = ((_IOraSession *)(sess.Internal()))->get_OpenDatabase(tempdbname, tp, options);
// free the BSTRs
OObjectFreeString(tp);
OObjectFreeString(tempdbname);
return(OpenHelper(dbi, sess.Internal()));
}
oresult ODatabase::OpenHelper(void *idisp, void *otheri)
{
if (!idisp)
{ // couldn't create database
// the actual error is stored in the session object
SetOtherError(otheri);
return(OFAILURE);
}
Cleanup(); // drop old state
// get database interface
void *tempi;
IDispatch *dbi = (IDispatch *) idisp;
HRESULT hc = dbi->QueryInterface(IID_IOraDatabase, &tempi);
dbi->Release();
if (FAILED(hc))
{
SetInternalError(OERROR_NOINTER);
return(OFAILURE);
}
return(SetObjectInterface(tempi)); // this sets error state
}
// overloaded assignment operator
ODatabase &ODatabase::operator=(const ODatabase &other)
{
if (&other == this)
return(*this); // self assignment - do nothing
// clear out our old state
if (OSUCCESS == Cleanup())
{
Copy(other); // call copy constructor
}
// if the cleanup failed (possible but unlikely) we don't do the copy
// and as a result, we pass on the unmodified (or partly cleaned!) object
return(*this);
}
oresult ODatabase::ExecuteSQL(const char *sqls) const
{
long numrows;
if (ActionStart() != OSUCCESS)
return(OFAILURE);
if (!sqls)
{
SetInternalError(OERROR_BADARG);
return(OFAILURE);
}
BSTR tempsql = OObjectAllocString(sqls);
numrows = (((_IOraDatabase *) Internal())->ExecuteSQL((BSTR) sqls));
// un-const this
ODatabase *dbp = (ODatabase *) this;
dbp->m_numrows = numrows;
OObjectFreeString(tempsql);
return((0 == ErrorNumber()) ? OSUCCESS : OFAILURE);
}
long ODatabase::GetRowsProcessed(void) const
{
return m_numrows;
}
long ODatabase::GetOptions(void) const
{
if (ActionStart() != OSUCCESS)
return(ODATABASE_DEFAULT);
return(((_IOraDatabase *) Internal())->get_Options());
}
oresult ODatabase::Copy(const ODatabase &other)
{
// don't bother to copy strings
m_dbname = 0;
m_dbconnect = 0;
return(OOracleObject::Copy(other));
}
const char *ODatabase::GetName(void) const
{
if (ActionStart() != OSUCCESS)
return(NULL);
if (!m_dbname)
{
char *cp = ((_IOraDatabase *) Internal())->get_DatabaseName();
/*
we want to change the state of this const database by changing
the value of m_dbname. Note that we're not really changing the
database, we're only changing what we know about the database
*/
ODatabase *dbp = (ODatabase *) this; // un-const this
dbp->m_dbname = cp;
}
return(m_dbname);
}
const char *ODatabase::GetConnectString(void) const
{
if (ActionStart() != OSUCCESS)
return(NULL);
if (!m_dbconnect)
{
char *cp = ((_IOraDatabase *) Internal())->get_Connect();
/*
we want to change the state of this const database by changing
the value of m_dbname. Note that we're not really changing the
database, we're only changing what we know about the database
*/
ODatabase *dbp = (ODatabase *) this; // un-const this
dbp->m_dbconnect = cp;
}
return(m_dbconnect);
}
OSession ODatabase::GetSession(void) const
{
OSession dbsess;
if (ActionGetStart(&dbsess) != OSUCCESS)
return(dbsess); // returning unopened object - indicates error
IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Session();
dbsess.OpenHelper((void *) connect, Internal());
return(dbsess);
}
OConnection ODatabase::GetConnection(void) const
{
OConnection dbconn;
if (ActionGetStart(&dbconn) != OSUCCESS)
return(dbconn); // returning unopened object - indicates error
IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Connection();
dbconn.OpenHelper((void *) connect, Internal());
return(dbconn);
}
OParameterCollection ODatabase::GetParameters(void) const
{
OParameterCollection pcoll;
if (ActionGetStart(&pcoll) != OSUCCESS)
return(pcoll); // returning unopened object - indicates error
IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Parameters();
pcoll.OpenHelper((void *) connect, Internal());
return(pcoll);
}
long ODatabase::ServerErrorNumber(void) const
{
if (ActionStart() != OSUCCESS)
return(0);
long errno = ((_IOraDatabase *) Internal())->get_LastServerErr();
return(errno);
}
int ODatabase::ServerErrorSQLPos(void) const
{
if (ActionStart() != OSUCCESS)
return(-1);
int errpos = ((_IOraDatabase *) Internal())->get_LastServerErrPos();
return(errpos);
}
const char *ODatabase::GetServerErrorText(void) const
{
if (ActionStart() != OSUCCESS)
return(NULL);
/*
we want to change the state of this const database by changing
the value of m_errtext. Note that we're not really changing the
database, we're only changing what we know about the database
*/
ODatabase *dbp = (ODatabase *) this; // un-const the this pointer
if (m_errtext)
{ // discard old error text (to make sure we always get latest error)
OObjectFreeString(m_errtext);
dbp->m_errtext = 0;
}
char *cp = ((_IOraDatabase *) Internal())->get_LastServerErrText();
dbp->m_errtext = cp;
return(m_errtext);
}
oresult ODatabase::ServerErrorReset(void)
{
if (ActionStart() != OSUCCESS)
return(OFAILURE);
((_IOraDatabase *) Internal())->LastServerErrReset();
return((0 == ErrorNumber()) ? OSUCCESS : OFAILURE);
}