home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / po7_win / object10 / odbase.cpp < prev    next >
C/C++ Source or Header  |  1995-04-04  |  11KB  |  443 lines

  1. /* Copyright (c) Oracle Corporation 1994.  All Rights Reserved */
  2.  
  3. /*
  4.     This source code is provided as a debugging aid for developers
  5.     who have purchased Oracle Objects for OLE    .  Please see the
  6.     online help for documentation of these classes.
  7. */
  8.  
  9. /*
  10.     Oracle Objects for OLE     C++ Classes
  11.     
  12.     This file implements the ODatabase class
  13.                            
  14.     CREATED    ********   11/22/94
  15.  
  16. */
  17.  
  18. #include "windows.h"
  19. #include <ole2.h>
  20. #include <olenls.h>       
  21. #include <dispatch.h>  
  22.  
  23. #ifndef ORACL_ORACLE
  24. #include "oracl.h"
  25. #endif
  26.  
  27. #ifndef _OracleInProcServer_H_
  28. #include <oratlb.h>
  29. #endif
  30.  
  31. #ifndef ORAOBJI_ORACLE
  32. #include "oraobji.h"
  33. #endif
  34.  
  35. static const IID IID_IOraDatabase =
  36. {0x5cdfcf20, 0xffd7, 0x101a, { 0xad, 0xf2, 0x04, 0x02, 0x1c, 0x00, 0x70, 0x02 } };
  37.  
  38. // ----- ODatabase -----------------------------------------------
  39.  
  40. ODatabase::ODatabase(void)
  41. {
  42.     m_dbname = 0;
  43.     m_dbconnect = 0;
  44.     m_errtext = 0;
  45.     m_numrows = -1;
  46. }
  47.  
  48. ODatabase::~ODatabase(void)
  49. {
  50.     Cleanup();
  51. }
  52.  
  53. ODatabase::ODatabase(const ODatabase &other)
  54. {
  55.     m_dbname = 0;
  56.     m_dbconnect = 0;
  57.     m_errtext = 0;
  58.     m_numrows = -1;
  59.     Copy(other);  // call our internal copier
  60. }
  61.  
  62. ODatabase::ODatabase(const OSession &dbsess, const char *dbname, const char *username, const char *pwd, long options)
  63. {
  64.     m_dbname = 0;
  65.     m_dbconnect = 0;
  66.     m_errtext = 0;
  67.     m_numrows = -1;
  68.     Open(dbsess, dbname, username, pwd, options);
  69. }
  70.  
  71. ODatabase::ODatabase(const char *dbname, const char *username, const char *pwd, long options)
  72. {
  73.     m_dbname = 0;
  74.     m_dbconnect = 0;
  75.     m_errtext = 0;
  76.     m_numrows = -1;
  77.     Open(dbname, username, pwd, options);
  78. }
  79.  
  80. oresult ODatabase::Close(void)
  81. {
  82.     return(Cleanup());
  83. }
  84.  
  85. oresult ODatabase::Cleanup(void)
  86.     if (m_dbname)
  87.     {
  88.         OObjectFreeString(m_dbname);
  89.         m_dbname = 0;
  90.     }
  91.     if (m_dbconnect)
  92.     {
  93.         OObjectFreeString(m_dbconnect);
  94.         m_dbconnect = 0;
  95.     }
  96.     if (m_errtext)
  97.     {
  98.         OObjectFreeString(m_errtext);
  99.         m_errtext = 0;
  100.     }
  101.     m_numrows = -1;
  102.     
  103.     return(OOracleObject::Cleanup());
  104. }
  105.  
  106. oresult ODatabase::Open(const char *dbname, const char *username, const char *pwd, long options)
  107. {
  108.     // open a session for this database connection
  109.     OSession tempSess;
  110.     oresult ores;
  111.     
  112.     ores = tempSess.Open();
  113.     if (ores == OSUCCESS)
  114.         ores = Open(tempSess, dbname, username, pwd, options);
  115.     else
  116.     { // couldn't open the temporary session.  Some OLE problem
  117.         SetInternalError(OERROR_SYSTEM);
  118.     }
  119.    
  120.     /*
  121.         Note that although the OSession session variable will go away, the OLE session object
  122.         (in the oip) will not, because the database has a reference to it.  The OLE session object
  123.         will go away when the database does.
  124.     */
  125.     
  126.     return(ores);
  127. }
  128.  
  129. oresult ODatabase::Open(const OSession &sess, const char *dbname, const char *username, const char *pwd, long options)
  130. {
  131.     if (!sess.IsOpen())
  132.     { // no valid session
  133.         SetInternalError(OERROR_INVPARENT); 
  134.         return(OFAILURE);
  135.     }
  136.     if (!dbname || !username)
  137.     {
  138.         SetInternalError(OERROR_BADARG);
  139.         return(OFAILURE);
  140.     }
  141.     
  142.     // get the username and password into the right form 
  143.     // DBCS problem - assumption of single-byte null
  144.     BSTR tp;
  145.     // password and username can't be more than 30 bytes apiece so...
  146.     const char *cp, *cp2;
  147.     cp = username;
  148.     while (*cp)
  149.         cp++; // scan to end of username
  150.     if (pwd)
  151.     {
  152.         cp2 = pwd;
  153.         while (*cp2)
  154.             cp2++;
  155.     }
  156.     //if (strlen(username) > 30 || (pwd && strlen(pwd) > 30))
  157.     if ((cp-username) > 30 || (pwd && (cp2-pwd)) > 30)
  158.     { 
  159.         SetInternalError(OERROR_BADARG);
  160.         return(OFAILURE);
  161.     }
  162.     
  163.     char temps[80];
  164.     if (pwd)
  165.     { // the username and password are separate
  166.         // don't use strcpy, etc so that we don't drag in C runtime
  167.         tp = temps;
  168.         cp = username;
  169.         while (*cp)
  170.             *tp++ = *cp++;
  171.         *tp++ = '/';
  172.         cp = pwd;
  173.         while (*cp)
  174.             *tp++ = *cp++;
  175.         *tp = '\0';  // null terminate;
  176.         tp = OObjectAllocString(temps);
  177.     }
  178.     else
  179.     {
  180.         // the username must contain a '/'
  181.         cp = username;
  182.         while (*cp)
  183.         {
  184.             if (*cp == '/')
  185.                 break;
  186.             cp++;
  187.         }
  188.         if (*cp != '/')
  189.         { // no slash
  190.             SetInternalError(OERROR_BADARG);
  191.             return(OFAILURE);
  192.         }
  193.         tp = OObjectAllocString(username); // contains username/password
  194.     }
  195.     
  196.     // get database name into BSTR
  197.     BSTR tempdbname = OObjectAllocString(dbname);
  198.     
  199.     if (!tp || !tempdbname)
  200.     {
  201.         SetInternalError(OERROR_MEMORY);
  202.         if (tp)
  203.             OObjectFreeString(tp);
  204.         if (tempdbname)
  205.             OObjectFreeString(tempdbname);
  206.         return(OFAILURE);
  207.     }
  208.     
  209.     // now do the real work
  210.     sess.ErrorReset(); // reset error state of session
  211.     
  212.     IDispatch *dbi = ((_IOraSession *)(sess.Internal()))->get_OpenDatabase(tempdbname, tp, options); 
  213.     // free the BSTRs
  214.     OObjectFreeString(tp);
  215.     OObjectFreeString(tempdbname);
  216.     
  217.     return(OpenHelper(dbi, sess.Internal()));
  218. }
  219.  
  220. oresult ODatabase::OpenHelper(void *idisp, void *otheri)
  221. {
  222.     if (!idisp)
  223.     { // couldn't create database
  224.         // the actual error is stored in the session object
  225.         SetOtherError(otheri);
  226.         return(OFAILURE);
  227.     }
  228.     
  229.     Cleanup(); // drop old state
  230.     
  231.     // get database interface
  232.     void *tempi;
  233.     IDispatch *dbi = (IDispatch *) idisp;
  234.     HRESULT hc = dbi->QueryInterface(IID_IOraDatabase, &tempi);
  235.     dbi->Release();
  236.     
  237.     if (FAILED(hc))
  238.     {
  239.         SetInternalError(OERROR_NOINTER);
  240.         return(OFAILURE);
  241.     }
  242.     
  243.     return(SetObjectInterface(tempi));  // this sets error state
  244. }
  245.  
  246. // overloaded assignment operator
  247. ODatabase &ODatabase::operator=(const ODatabase &other)
  248. {
  249.     if (&other == this)
  250.         return(*this); // self assignment - do nothing
  251.     
  252.     // clear out our old state
  253.     if (OSUCCESS == Cleanup())
  254.     {
  255.         Copy(other); // call copy constructor
  256.     }
  257.     // if the cleanup failed (possible but unlikely) we don't do the copy
  258.     //    and as a result, we pass on the unmodified (or partly cleaned!) object
  259.     
  260.     return(*this);
  261.  
  262. oresult ODatabase::ExecuteSQL(const char *sqls) const
  263. {   
  264.     long    numrows;
  265.     
  266.     if (ActionStart() != OSUCCESS)
  267.         return(OFAILURE);
  268.     
  269.     if (!sqls)
  270.     {
  271.         SetInternalError(OERROR_BADARG);
  272.         return(OFAILURE);
  273.     }
  274.     
  275.     BSTR tempsql = OObjectAllocString(sqls);
  276.     numrows = (((_IOraDatabase *) Internal())->ExecuteSQL((BSTR) sqls));
  277.     // un-const this
  278.     ODatabase *dbp = (ODatabase *) this;
  279.     dbp->m_numrows = numrows;
  280.     OObjectFreeString(tempsql);
  281.     
  282.     return((0 == ErrorNumber()) ? OSUCCESS : OFAILURE);
  283. }
  284.  
  285. long ODatabase::GetRowsProcessed(void) const
  286. {
  287.     return m_numrows;
  288. }
  289.  
  290. long ODatabase::GetOptions(void) const
  291. {
  292.     if (ActionStart() != OSUCCESS)
  293.         return(ODATABASE_DEFAULT);
  294.     
  295.     return(((_IOraDatabase *) Internal())->get_Options());
  296. }
  297.  
  298. oresult ODatabase::Copy(const ODatabase &other)
  299. {
  300.     // don't bother to copy strings
  301.     m_dbname = 0;
  302.     m_dbconnect = 0;
  303.     return(OOracleObject::Copy(other));
  304. }
  305.  
  306. const char *ODatabase::GetName(void) const
  307. {
  308.     if (ActionStart() != OSUCCESS)
  309.         return(NULL);
  310.     
  311.     if (!m_dbname)
  312.     {
  313.         char *cp = ((_IOraDatabase *) Internal())->get_DatabaseName();
  314.         /*
  315.             we want to change the state of this const database by changing
  316.             the value of m_dbname.  Note that we're not really changing the
  317.             database, we're only changing what we know about the database
  318.         */
  319.         ODatabase *dbp = (ODatabase *) this;  // un-const this
  320.         dbp->m_dbname = cp;
  321.     }
  322.     
  323.     return(m_dbname);                                                             
  324. }
  325.  
  326. const char *ODatabase::GetConnectString(void) const
  327. {
  328.     if (ActionStart() != OSUCCESS)
  329.         return(NULL);
  330.     
  331.     if (!m_dbconnect)
  332.     {
  333.         char *cp = ((_IOraDatabase *) Internal())->get_Connect();
  334.         /*
  335.             we want to change the state of this const database by changing
  336.             the value of m_dbname.  Note that we're not really changing the
  337.             database, we're only changing what we know about the database
  338.         */
  339.         ODatabase *dbp = (ODatabase *) this;  // un-const this
  340.         dbp->m_dbconnect = cp;
  341.     }
  342.     
  343.     return(m_dbconnect);                                                             
  344. }    
  345.  
  346. OSession ODatabase::GetSession(void) const
  347. {
  348.     OSession dbsess;
  349.  
  350.     if (ActionGetStart(&dbsess) != OSUCCESS)
  351.         return(dbsess); // returning unopened object - indicates error
  352.     
  353.     IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Session();
  354.     dbsess.OpenHelper((void *) connect, Internal());
  355.     
  356.     return(dbsess);
  357. }
  358.  
  359. OConnection ODatabase::GetConnection(void) const
  360. {
  361.     OConnection dbconn;
  362.     
  363.     if (ActionGetStart(&dbconn) != OSUCCESS)
  364.         return(dbconn); // returning unopened object - indicates error
  365.     
  366.     IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Connection();
  367.     
  368.     dbconn.OpenHelper((void *) connect, Internal());
  369.     return(dbconn);
  370. }
  371.  
  372. OParameterCollection ODatabase::GetParameters(void) const
  373. {
  374.     OParameterCollection pcoll;
  375.     
  376.     if (ActionGetStart(&pcoll) != OSUCCESS)
  377.         return(pcoll); // returning unopened object - indicates error
  378.     
  379.     IDispatch *connect = ((_IOraDatabase *) (Internal()))->get_Parameters();
  380.     
  381.     pcoll.OpenHelper((void *) connect, Internal());
  382.     return(pcoll);
  383. }
  384.  
  385. long ODatabase::ServerErrorNumber(void) const
  386. {
  387.     if (ActionStart() != OSUCCESS)
  388.         return(0);
  389.     
  390.     long errno = ((_IOraDatabase *) Internal())->get_LastServerErr();
  391.     
  392.     return(errno);
  393. }
  394.  
  395. int ODatabase::ServerErrorSQLPos(void) const
  396. {
  397.     if (ActionStart() != OSUCCESS)
  398.         return(-1);
  399.     
  400.     int errpos = ((_IOraDatabase *) Internal())->get_LastServerErrPos();
  401.     
  402.     return(errpos);
  403. }
  404.  
  405. const char *ODatabase::GetServerErrorText(void) const
  406. {
  407.     if (ActionStart() != OSUCCESS)
  408.         return(NULL);
  409.     
  410.     /*
  411.         we want to change the state of this const database by changing
  412.         the value of m_errtext.  Note that we're not really changing the
  413.         database, we're only changing what we know about the database
  414.     */                                                             
  415.     ODatabase *dbp = (ODatabase *) this;  // un-const the this pointer
  416.  
  417.     if (m_errtext)
  418.     { // discard old error text (to make sure we always get latest error)
  419.         OObjectFreeString(m_errtext);
  420.         dbp->m_errtext = 0;
  421.     }
  422.     
  423.     char *cp = ((_IOraDatabase *) Internal())->get_LastServerErrText();
  424.  
  425.     dbp->m_errtext = cp;
  426.  
  427.     return(m_errtext);
  428. }
  429.  
  430. oresult ODatabase::ServerErrorReset(void)
  431. {
  432.     if (ActionStart() != OSUCCESS)
  433.         return(OFAILURE);
  434.     
  435.     ((_IOraDatabase *) Internal())->LastServerErrReset();
  436.     
  437.     return((0 == ErrorNumber()) ? OSUCCESS : OFAILURE);
  438. }
  439.  
  440.  
  441.